Changeset 210010 in webkit
- Timestamp:
- Dec 19, 2016, 6:03:02 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r209980 r210010 1 2016-12-19 Mark Lam <mark.lam@apple.com> 2 3 Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 2: Rollout r209952. 4 https://bugs.webkit.org/show_bug.cgi?id=166049 5 6 Not reviewed. 7 8 * stress/deeply-nested-finallys.js: Removed. 9 * stress/test-finally.js: Removed. 10 1 11 2016-12-19 Saam Barati <sbarati@apple.com> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r210007 r210010 1 2016-12-19 Mark Lam <mark.lam@apple.com> 2 3 Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 2: Rollout r209952. 4 https://bugs.webkit.org/show_bug.cgi?id=166049 5 6 Not reviewed. 7 8 * bytecode/HandlerInfo.h: 9 (JSC::HandlerInfoBase::typeName): 10 * bytecompiler/BytecodeGenerator.cpp: 11 (JSC::BytecodeGenerator::generate): 12 (JSC::BytecodeGenerator::BytecodeGenerator): 13 (JSC::BytecodeGenerator::emitReturn): 14 (JSC::BytecodeGenerator::pushFinallyControlFlowScope): 15 (JSC::BytecodeGenerator::pushIteratorCloseControlFlowScope): 16 (JSC::BytecodeGenerator::popFinallyControlFlowScope): 17 (JSC::BytecodeGenerator::popIteratorCloseControlFlowScope): 18 (JSC::BytecodeGenerator::emitComplexPopScopes): 19 (JSC::BytecodeGenerator::emitPopScopes): 20 (JSC::BytecodeGenerator::pushTry): 21 (JSC::BytecodeGenerator::popTryAndEmitCatch): 22 (JSC::BytecodeGenerator::labelScopeDepth): 23 (JSC::BytecodeGenerator::pushLocalControlFlowScope): 24 (JSC::BytecodeGenerator::popLocalControlFlowScope): 25 (JSC::BytecodeGenerator::emitEnumeration): 26 (JSC::BytecodeGenerator::emitYield): 27 (JSC::BytecodeGenerator::emitDelegateYield): 28 (JSC::BytecodeGenerator::popTry): Deleted. 29 (JSC::BytecodeGenerator::emitCatch): Deleted. 30 (JSC::BytecodeGenerator::restoreScopeRegister): Deleted. 31 (JSC::BytecodeGenerator::labelScopeDepthToLexicalScopeIndex): Deleted. 32 (JSC::BytecodeGenerator::emitIsNumber): Deleted. 33 (JSC::BytecodeGenerator::emitJumpViaFinallyIfNeeded): Deleted. 34 (JSC::BytecodeGenerator::emitReturnViaFinallyIfNeeded): Deleted. 35 (JSC::BytecodeGenerator::emitFinallyCompletion): Deleted. 36 (JSC::BytecodeGenerator::allocateFinallyRegisters): Deleted. 37 (JSC::BytecodeGenerator::releaseFinallyRegisters): Deleted. 38 (JSC::BytecodeGenerator::emitCompareFinallyActionAndJumpIf): Deleted. 39 * bytecompiler/BytecodeGenerator.h: 40 (JSC::BytecodeGenerator::isInFinallyBlock): 41 (JSC::FinallyJump::FinallyJump): Deleted. 42 (JSC::FinallyContext::FinallyContext): Deleted. 43 (JSC::FinallyContext::outerContext): Deleted. 44 (JSC::FinallyContext::finallyLabel): Deleted. 45 (JSC::FinallyContext::depth): Deleted. 46 (JSC::FinallyContext::numberOfBreaksOrContinues): Deleted. 47 (JSC::FinallyContext::incNumberOfBreaksOrContinues): Deleted. 48 (JSC::FinallyContext::handlesReturns): Deleted. 49 (JSC::FinallyContext::setHandlesReturns): Deleted. 50 (JSC::FinallyContext::registerJump): Deleted. 51 (JSC::FinallyContext::numberOfJumps): Deleted. 52 (JSC::FinallyContext::jumps): Deleted. 53 (JSC::ControlFlowScope::ControlFlowScope): Deleted. 54 (JSC::ControlFlowScope::isLabelScope): Deleted. 55 (JSC::ControlFlowScope::isFinallyScope): Deleted. 56 (JSC::BytecodeGenerator::currentLexicalScopeIndex): Deleted. 57 (JSC::BytecodeGenerator::FinallyRegistersScope::FinallyRegistersScope): Deleted. 58 (JSC::BytecodeGenerator::FinallyRegistersScope::~FinallyRegistersScope): Deleted. 59 (JSC::BytecodeGenerator::finallyActionRegister): Deleted. 60 (JSC::BytecodeGenerator::finallyReturnValueRegister): Deleted. 61 (JSC::BytecodeGenerator::emitSetFinallyActionToNormalCompletion): Deleted. 62 (JSC::BytecodeGenerator::emitSetFinallyActionToReturnCompletion): Deleted. 63 (JSC::BytecodeGenerator::emitSetFinallyActionToJumpID): Deleted. 64 (JSC::BytecodeGenerator::emitSetFinallyReturnValueRegister): Deleted. 65 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNormalCompletion): Deleted. 66 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotJump): Deleted. 67 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsReturnCompletion): Deleted. 68 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotReturnCompletion): Deleted. 69 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotThrowCompletion): Deleted. 70 (JSC::BytecodeGenerator::emitJumpIfCompletionTypeIsThrow): Deleted. 71 (JSC::BytecodeGenerator::bytecodeOffsetToJumpID): Deleted. 72 * bytecompiler/NodesCodegen.cpp: 73 (JSC::ContinueNode::emitBytecode): 74 (JSC::BreakNode::emitBytecode): 75 (JSC::ReturnNode::emitBytecode): 76 (JSC::TryNode::emitBytecode): 77 1 78 2016-12-19 Mark Lam <mark.lam@apple.com> 2 79 -
trunk/Source/JavaScriptCore/bytecode/HandlerInfo.h
r209952 r210010 32 32 33 33 enum class HandlerType { 34 Catch= 0,35 Finally= 1,36 SynthesizedCatch= 2,34 Illegal = 0, 35 Catch = 1, 36 Finally = 2, 37 37 SynthesizedFinally = 3 38 38 }; … … 54 54 case HandlerType::Finally: 55 55 return "finally"; 56 case HandlerType::SynthesizedCatch:57 return "synthesized catch";58 56 case HandlerType::SynthesizedFinally: 59 57 return "synthesized finally"; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r210007 r210010 157 157 continue; 158 158 159 ASSERT(range.tryData->handlerType != HandlerType::Illegal); 159 160 UnlinkedHandlerInfo info(static_cast<uint32_t>(start), static_cast<uint32_t>(end), 160 161 static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->handlerType); … … 680 681 pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ); 681 682 682 RefPtr<Label> catchLabel = newLabel();683 683 TryData* tryFormalParametersData = nullptr; 684 bool needTryCatch = isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList; 685 if (needTryCatch) { 684 if (isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList) { 686 685 RefPtr<Label> tryFormalParametersStart = emitLabel(newLabel().get()); 687 tryFormalParametersData = pushTry(tryFormalParametersStart.get() , catchLabel.get(), HandlerType::SynthesizedCatch);686 tryFormalParametersData = pushTry(tryFormalParametersStart.get()); 688 687 } 689 688 690 689 initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures, shouldCreateArgumentsVariableInParameterScope); 691 690 692 if ( needTryCatch) {691 if (isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList) { 693 692 RefPtr<Label> didNotThrow = newLabel(); 694 693 emitJump(didNotThrow.get()); 695 emitLabel(catchLabel.get()); 696 popTry(tryFormalParametersData, catchLabel.get()); 697 694 RefPtr<RegisterID> exception = newTemporary(); 698 695 RefPtr<RegisterID> thrownValue = newTemporary(); 699 Re gisterID* unused = newTemporary();700 emitCatch(unused, thrownValue.get());696 RefPtr<Label> catchHere = emitLabel(newLabel().get()); 697 popTryAndEmitCatch(tryFormalParametersData, exception.get(), thrownValue.get(), catchHere.get(), HandlerType::Catch); 701 698 702 699 // return promiseCapability.@reject(thrownValue) … … 3497 3494 } 3498 3495 3499 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src , ReturnFrom from)3496 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src) 3500 3497 { 3501 3498 if (isConstructor()) { … … 3503 3500 bool srcIsThis = src->index() == m_thisRegister.index(); 3504 3501 3505 if (mightBeDerived && (srcIsThis || from == ReturnFrom::Finally))3502 if (mightBeDerived && srcIsThis) 3506 3503 emitTDZCheck(src); 3507 3504 3508 if (!srcIsThis || from == ReturnFrom::Finally) {3505 if (!srcIsThis) { 3509 3506 RefPtr<Label> isObjectLabel = newLabel(); 3510 3507 emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get()); … … 3684 3681 } 3685 3682 3686 FinallyContext* BytecodeGenerator::pushFinallyControlFlowScope(Label* finallyLabel)3683 void BytecodeGenerator::pushFinallyControlFlowScope(StatementNode* finallyBlock) 3687 3684 { 3688 3685 // Reclaim free label scopes. … … 3690 3687 m_labelScopes.removeLast(); 3691 3688 3692 ControlFlowScope scope(ControlFlowScope::Finally, currentLexicalScopeIndex(), FinallyContext(m_currentFinallyContext, finallyLabel, m_finallyDepth)); 3693 m_controlFlowScopeStack.append(WTFMove(scope)); 3694 3689 ControlFlowScope scope; 3690 scope.isFinallyBlock = true; 3691 FinallyContext context = { 3692 finallyBlock, 3693 nullptr, 3694 nullptr, 3695 static_cast<unsigned>(m_controlFlowScopeStack.size()), 3696 static_cast<unsigned>(m_switchContextStack.size()), 3697 static_cast<unsigned>(m_forInContextStack.size()), 3698 static_cast<unsigned>(m_tryContextStack.size()), 3699 static_cast<unsigned>(m_labelScopes.size()), 3700 static_cast<unsigned>(m_lexicalScopeStack.size()), 3701 m_finallyDepth, 3702 m_localScopeDepth 3703 }; 3704 scope.finallyContext = context; 3705 m_controlFlowScopeStack.append(scope); 3695 3706 m_finallyDepth++; 3696 m_currentFinallyContext = &m_controlFlowScopeStack.last().finallyContext; 3697 return m_currentFinallyContext; 3698 } 3699 3700 FinallyContext BytecodeGenerator::popFinallyControlFlowScope() 3707 } 3708 3709 void BytecodeGenerator::pushIteratorCloseControlFlowScope(RegisterID* iterator, ThrowableExpressionData* node) 3710 { 3711 // Reclaim free label scopes. 3712 while (m_labelScopes.size() && !m_labelScopes.last().refCount()) 3713 m_labelScopes.removeLast(); 3714 3715 ControlFlowScope scope; 3716 scope.isFinallyBlock = true; 3717 FinallyContext context = { 3718 nullptr, 3719 iterator, 3720 node, 3721 static_cast<unsigned>(m_controlFlowScopeStack.size()), 3722 static_cast<unsigned>(m_switchContextStack.size()), 3723 static_cast<unsigned>(m_forInContextStack.size()), 3724 static_cast<unsigned>(m_tryContextStack.size()), 3725 static_cast<unsigned>(m_labelScopes.size()), 3726 static_cast<unsigned>(m_lexicalScopeStack.size()), 3727 m_finallyDepth, 3728 m_localScopeDepth 3729 }; 3730 scope.finallyContext = context; 3731 m_controlFlowScopeStack.append(scope); 3732 m_finallyDepth++; 3733 } 3734 3735 void BytecodeGenerator::popFinallyControlFlowScope() 3701 3736 { 3702 3737 ASSERT(m_controlFlowScopeStack.size()); 3703 ASSERT(m_controlFlowScopeStack.last().isFinallyScope()); 3738 ASSERT(m_controlFlowScopeStack.last().isFinallyBlock); 3739 ASSERT(m_controlFlowScopeStack.last().finallyContext.finallyBlock); 3740 ASSERT(!m_controlFlowScopeStack.last().finallyContext.iterator); 3741 ASSERT(!m_controlFlowScopeStack.last().finallyContext.enumerationNode); 3704 3742 ASSERT(m_finallyDepth > 0); 3705 ASSERT(m_currentFinallyContext); 3706 m_currentFinallyContext = m_currentFinallyContext->outerContext(); 3743 m_controlFlowScopeStack.removeLast(); 3707 3744 m_finallyDepth--; 3708 return m_controlFlowScopeStack.takeLast().finallyContext; 3745 } 3746 3747 void BytecodeGenerator::popIteratorCloseControlFlowScope() 3748 { 3749 ASSERT(m_controlFlowScopeStack.size()); 3750 ASSERT(m_controlFlowScopeStack.last().isFinallyBlock); 3751 ASSERT(!m_controlFlowScopeStack.last().finallyContext.finallyBlock); 3752 ASSERT(m_controlFlowScopeStack.last().finallyContext.iterator); 3753 ASSERT(m_controlFlowScopeStack.last().finallyContext.enumerationNode); 3754 ASSERT(m_finallyDepth > 0); 3755 m_controlFlowScopeStack.removeLast(); 3756 m_finallyDepth--; 3709 3757 } 3710 3758 … … 3806 3854 emitMove(m_topMostScope, scopeRegister()); 3807 3855 } 3808 3809 TryData* BytecodeGenerator::pushTry(Label* start, Label* handlerLabel, HandlerType handlerType) 3856 3857 void BytecodeGenerator::emitComplexPopScopes(RegisterID* scope, ControlFlowScope* topScope, ControlFlowScope* bottomScope) 3858 { 3859 while (topScope > bottomScope) { 3860 // First we count the number of dynamic scopes we need to remove to get 3861 // to a finally block. 3862 int numberOfNormalScopes = 0; 3863 while (topScope > bottomScope) { 3864 if (topScope->isFinallyBlock) 3865 break; 3866 ++numberOfNormalScopes; 3867 --topScope; 3868 } 3869 3870 if (numberOfNormalScopes) { 3871 // We need to remove a number of dynamic scopes to get to the next 3872 // finally block 3873 RefPtr<RegisterID> parentScope = newTemporary(); 3874 while (numberOfNormalScopes--) { 3875 parentScope = emitGetParentScope(parentScope.get(), scope); 3876 emitMove(scope, parentScope.get()); 3877 } 3878 3879 // If topScope == bottomScope then there isn't a finally block left to emit. 3880 if (topScope == bottomScope) 3881 return; 3882 } 3883 3884 Vector<ControlFlowScope> savedControlFlowScopeStack; 3885 Vector<SwitchInfo> savedSwitchContextStack; 3886 Vector<RefPtr<ForInContext>> savedForInContextStack; 3887 Vector<TryContext> poppedTryContexts; 3888 Vector<LexicalScopeStackEntry> savedLexicalScopeStack; 3889 LabelScopeStore savedLabelScopes; 3890 while (topScope > bottomScope && topScope->isFinallyBlock) { 3891 RefPtr<Label> beforeFinally = emitLabel(newLabel().get()); 3892 3893 // Save the current state of the world while instating the state of the world 3894 // for the finally block. 3895 FinallyContext finallyContext = topScope->finallyContext; 3896 bool flipScopes = finallyContext.controlFlowScopeStackSize != m_controlFlowScopeStack.size(); 3897 bool flipSwitches = finallyContext.switchContextStackSize != m_switchContextStack.size(); 3898 bool flipForIns = finallyContext.forInContextStackSize != m_forInContextStack.size(); 3899 bool flipTries = finallyContext.tryContextStackSize != m_tryContextStack.size(); 3900 bool flipLabelScopes = finallyContext.labelScopesSize != m_labelScopes.size(); 3901 bool flipLexicalScopeStack = finallyContext.lexicalScopeStackSize != m_lexicalScopeStack.size(); 3902 int topScopeIndex = -1; 3903 int bottomScopeIndex = -1; 3904 if (flipScopes) { 3905 topScopeIndex = topScope - m_controlFlowScopeStack.begin(); 3906 bottomScopeIndex = bottomScope - m_controlFlowScopeStack.begin(); 3907 savedControlFlowScopeStack = m_controlFlowScopeStack; 3908 m_controlFlowScopeStack.shrink(finallyContext.controlFlowScopeStackSize); 3909 } 3910 if (flipSwitches) { 3911 savedSwitchContextStack = m_switchContextStack; 3912 m_switchContextStack.shrink(finallyContext.switchContextStackSize); 3913 } 3914 if (flipForIns) { 3915 savedForInContextStack = m_forInContextStack; 3916 m_forInContextStack.shrink(finallyContext.forInContextStackSize); 3917 } 3918 if (flipTries) { 3919 while (m_tryContextStack.size() != finallyContext.tryContextStackSize) { 3920 ASSERT(m_tryContextStack.size() > finallyContext.tryContextStackSize); 3921 TryContext context = m_tryContextStack.takeLast(); 3922 TryRange range; 3923 range.start = context.start; 3924 range.end = beforeFinally; 3925 range.tryData = context.tryData; 3926 m_tryRanges.append(range); 3927 poppedTryContexts.append(context); 3928 } 3929 } 3930 if (flipLabelScopes) { 3931 savedLabelScopes = m_labelScopes; 3932 while (m_labelScopes.size() > finallyContext.labelScopesSize) 3933 m_labelScopes.removeLast(); 3934 } 3935 if (flipLexicalScopeStack) { 3936 savedLexicalScopeStack = m_lexicalScopeStack; 3937 m_lexicalScopeStack.shrink(finallyContext.lexicalScopeStackSize); 3938 } 3939 int savedFinallyDepth = m_finallyDepth; 3940 m_finallyDepth = finallyContext.finallyDepth; 3941 int savedDynamicScopeDepth = m_localScopeDepth; 3942 m_localScopeDepth = finallyContext.dynamicScopeDepth; 3943 3944 if (finallyContext.finallyBlock) { 3945 // Emit the finally block. 3946 emitNode(finallyContext.finallyBlock); 3947 } else { 3948 // Emit the IteratorClose block. 3949 ASSERT(finallyContext.iterator); 3950 emitIteratorClose(finallyContext.iterator, finallyContext.enumerationNode); 3951 } 3952 3953 RefPtr<Label> afterFinally = emitLabel(newLabel().get()); 3954 3955 // Restore the state of the world. 3956 if (flipScopes) { 3957 m_controlFlowScopeStack = savedControlFlowScopeStack; 3958 topScope = &m_controlFlowScopeStack[topScopeIndex]; // assert it's within bounds 3959 bottomScope = m_controlFlowScopeStack.begin() + bottomScopeIndex; // don't assert, since it the index might be -1. 3960 } 3961 if (flipSwitches) 3962 m_switchContextStack = savedSwitchContextStack; 3963 if (flipForIns) 3964 m_forInContextStack = savedForInContextStack; 3965 if (flipTries) { 3966 ASSERT(m_tryContextStack.size() == finallyContext.tryContextStackSize); 3967 for (unsigned i = poppedTryContexts.size(); i--;) { 3968 TryContext context = poppedTryContexts[i]; 3969 context.start = afterFinally; 3970 m_tryContextStack.append(context); 3971 } 3972 poppedTryContexts.clear(); 3973 } 3974 if (flipLabelScopes) 3975 m_labelScopes = savedLabelScopes; 3976 if (flipLexicalScopeStack) 3977 m_lexicalScopeStack = savedLexicalScopeStack; 3978 m_finallyDepth = savedFinallyDepth; 3979 m_localScopeDepth = savedDynamicScopeDepth; 3980 3981 --topScope; 3982 } 3983 } 3984 } 3985 3986 void BytecodeGenerator::emitPopScopes(RegisterID* scope, int targetScopeDepth) 3987 { 3988 ASSERT(labelScopeDepth() - targetScopeDepth >= 0); 3989 3990 size_t scopeDelta = labelScopeDepth() - targetScopeDepth; 3991 ASSERT(scopeDelta <= m_controlFlowScopeStack.size()); 3992 if (!scopeDelta) 3993 return; 3994 3995 if (!m_finallyDepth) { 3996 RefPtr<RegisterID> parentScope = newTemporary(); 3997 while (scopeDelta--) { 3998 parentScope = emitGetParentScope(parentScope.get(), scope); 3999 emitMove(scope, parentScope.get()); 4000 } 4001 return; 4002 } 4003 4004 emitComplexPopScopes(scope, &m_controlFlowScopeStack.last(), &m_controlFlowScopeStack.last() - scopeDelta); 4005 } 4006 4007 TryData* BytecodeGenerator::pushTry(Label* start) 3810 4008 { 3811 4009 TryData tryData; 3812 tryData.target = handlerLabel;3813 tryData.handlerType = handlerType;4010 tryData.target = newLabel(); 4011 tryData.handlerType = HandlerType::Illegal; 3814 4012 m_tryData.append(tryData); 3815 4013 TryData* result = &m_tryData.last(); … … 3824 4022 } 3825 4023 3826 void BytecodeGenerator::popTry (TryData* tryData, Label* end)4024 void BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType handlerType) 3827 4025 { 3828 4026 m_usesExceptions = true; … … 3836 4034 m_tryRanges.append(tryRange); 3837 4035 m_tryContextStack.removeLast(); 3838 } 3839 3840 void BytecodeGenerator::emitCatch(RegisterID* exceptionRegister, RegisterID* thrownValueRegister) 3841 { 4036 4037 emitLabel(tryRange.tryData->target.get()); 4038 tryRange.tryData->handlerType = handlerType; 4039 3842 4040 emitOpcode(op_catch); 3843 4041 instructions().append(exceptionRegister->index()); 3844 4042 instructions().append(thrownValueRegister->index()); 3845 } 3846 3847 void BytecodeGenerator::restoreScopeRegister(int lexicalScopeIndex) 3848 { 3849 if (lexicalScopeIndex == CurrentLexicalScopeIndex) 3850 return; // No change needed. 3851 3852 if (lexicalScopeIndex != OutermostLexicalScopeIndex) { 3853 ASSERT(lexicalScopeIndex < static_cast<int>(m_lexicalScopeStack.size())); 3854 int endIndex = lexicalScopeIndex + 1; 3855 for (size_t i = endIndex; i--; ) { 3856 if (m_lexicalScopeStack[i].m_scope) { 3857 emitMove(scopeRegister(), m_lexicalScopeStack[i].m_scope); 3858 return; 3859 } 3860 } 3861 } 3862 // Note that if we don't find a local scope in the current function/program, 3863 // we must grab the outer-most scope of this bytecode generation. 3864 emitMove(scopeRegister(), m_topMostScope); 3865 } 3866 3867 void BytecodeGenerator::restoreScopeRegister() 3868 { 3869 restoreScopeRegister(currentLexicalScopeIndex()); 3870 } 3871 3872 int BytecodeGenerator::labelScopeDepthToLexicalScopeIndex(int targetLabelScopeDepth) 3873 { 3874 ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0); 3875 size_t scopeDelta = labelScopeDepth() - targetLabelScopeDepth; 3876 ASSERT(scopeDelta <= m_controlFlowScopeStack.size()); 3877 if (!scopeDelta) 3878 return CurrentLexicalScopeIndex; 3879 3880 ControlFlowScope& targetScope = m_controlFlowScopeStack[targetLabelScopeDepth]; 3881 return targetScope.lexicalScopeIndex; 4043 4044 bool foundLocalScope = false; 4045 for (unsigned i = m_lexicalScopeStack.size(); i--; ) { 4046 // Note that if we don't find a local scope in the current function/program, 4047 // we must grab the outer-most scope of this bytecode generation. 4048 if (m_lexicalScopeStack[i].m_scope) { 4049 foundLocalScope = true; 4050 emitMove(scopeRegister(), m_lexicalScopeStack[i].m_scope); 4051 break; 4052 } 4053 } 4054 if (!foundLocalScope) 4055 emitMove(scopeRegister(), m_topMostScope); 3882 4056 } 3883 4057 … … 3888 4062 3889 4063 int BytecodeGenerator::labelScopeDepth() const 3890 { 3891 int depth = localScopeDepth() + m_finallyDepth; 3892 ASSERT(depth == static_cast<int>(m_controlFlowScopeStack.size())); 3893 return depth; 4064 { 4065 return localScopeDepth() + m_finallyDepth; 3894 4066 } 3895 4067 … … 3961 4133 void BytecodeGenerator::pushLocalControlFlowScope() 3962 4134 { 3963 ControlFlowScope scope(ControlFlowScope::Label, currentLexicalScopeIndex()); 3964 m_controlFlowScopeStack.append(WTFMove(scope)); 4135 ControlFlowScope scope; 4136 scope.isFinallyBlock = false; 4137 m_controlFlowScopeStack.append(scope); 3965 4138 m_localScopeDepth++; 3966 4139 } … … 3969 4142 { 3970 4143 ASSERT(m_controlFlowScopeStack.size()); 3971 ASSERT(!m_controlFlowScopeStack.last().isFinally Scope());4144 ASSERT(!m_controlFlowScopeStack.last().isFinallyBlock); 3972 4145 m_controlFlowScopeStack.removeLast(); 3973 4146 m_localScopeDepth--; … … 4124 4297 return false; 4125 4298 } 4126 4299 4127 4300 void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable) 4128 4301 { 4129 FinallyRegistersScope finallyRegistersScope(*this);4130 4131 4302 RefPtr<RegisterID> subject = newTemporary(); 4132 4303 emitNode(subject.get(), subjectNode); … … 4139 4310 4140 4311 RefPtr<Label> loopDone = newLabel(); 4141 RefPtr<Label> tryStartLabel = newLabel();4142 RefPtr<Label> finallyViaThrowLabel = newLabel();4143 RefPtr<Label> finallyLabel = newLabel();4144 RefPtr<Label> catchLabel = newLabel();4145 RefPtr<Label> endCatchLabel = newLabel();4146 4147 4312 // RefPtr<Register> iterator's lifetime must be longer than IteratorCloseContext. 4148 FinallyContext* finallyContext = pushFinallyControlFlowScope(finallyLabel.get()); 4149 4313 pushIteratorCloseControlFlowScope(iterator.get(), node); 4150 4314 { 4151 4315 LabelScopePtr scope = newLabelScope(LabelScope::Loop); … … 4159 4323 emitLoopHint(); 4160 4324 4325 RefPtr<Label> tryStartLabel = newLabel(); 4161 4326 emitLabel(tryStartLabel.get()); 4162 TryData* tryData = pushTry(tryStartLabel.get() , finallyViaThrowLabel.get(), HandlerType::SynthesizedFinally);4327 TryData* tryData = pushTry(tryStartLabel.get()); 4163 4328 callBack(*this, value.get()); 4164 4329 emitJump(scope->continueTarget()); 4165 4330 4166 // IteratorClose sequence for abrupt completions.4331 // IteratorClose sequence for throw-ed control flow. 4167 4332 { 4168 // Finally block for the enumeration. 4169 emitLabel(finallyViaThrowLabel.get()); 4170 popTry(tryData, finallyViaThrowLabel.get()); 4171 4172 RegisterID* unused = newTemporary(); 4173 emitCatch(finallyActionRegister(), unused); 4174 // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw. 4175 4176 emitLabel(finallyLabel.get()); 4177 restoreScopeRegister(); 4178 4179 RefPtr<Label> finallyDone = newLabel(); 4333 RefPtr<Label> catchHere = emitLabel(newLabel().get()); 4334 RefPtr<RegisterID> exceptionRegister = newTemporary(); 4335 RefPtr<RegisterID> thrownValueRegister = newTemporary(); 4336 popTryAndEmitCatch(tryData, exceptionRegister.get(), 4337 thrownValueRegister.get(), catchHere.get(), HandlerType::SynthesizedFinally); 4338 4339 RefPtr<Label> catchDone = newLabel(); 4180 4340 4181 4341 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword); 4182 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), finallyDone.get()); 4183 4184 RefPtr<RegisterID> originalFinallyActionRegister = newTemporary(); 4185 emitMove(originalFinallyActionRegister.get(), finallyActionRegister()); 4342 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), catchDone.get()); 4186 4343 4187 4344 RefPtr<Label> returnCallTryStart = newLabel(); 4188 4345 emitLabel(returnCallTryStart.get()); 4189 TryData* returnCallTryData = pushTry(returnCallTryStart.get() , catchLabel.get(), HandlerType::SynthesizedCatch);4346 TryData* returnCallTryData = pushTry(returnCallTryStart.get()); 4190 4347 4191 4348 CallArguments returnArguments(*this, nullptr); 4192 4349 emitMove(returnArguments.thisRegister(), iterator.get()); 4193 4350 emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No); 4194 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), finallyDone.get()); 4195 emitThrowTypeError(ASCIILiteral("Iterator result interface is not an object.")); 4196 4197 emitLabel(finallyDone.get()); 4198 emitFinallyCompletion(*finallyContext, endCatchLabel.get()); 4199 4200 popTry(returnCallTryData, finallyDone.get()); 4201 4202 // Catch block for exceptions that may be thrown while calling the return 4203 // handler in the enumeration finally block. The only reason we need this 4204 // catch block is because if entered the above finally block due to a thrown 4205 // exception, then we want to re-throw the original exception on exiting 4206 // the finally block. Otherwise, we'll let any new exception pass through. 4207 { 4208 emitLabel(catchLabel.get()); 4209 RefPtr<RegisterID> exceptionRegister = newTemporary(); 4210 RegisterID* unused = newTemporary(); 4211 emitCatch(exceptionRegister.get(), unused); 4212 restoreScopeRegister(); 4213 4214 RefPtr<Label> throwLabel = newLabel(); 4215 emitJumpIfCompletionTypeIsThrow(originalFinallyActionRegister.get(), throwLabel.get()); 4216 emitMove(originalFinallyActionRegister.get(), exceptionRegister.get()); 4217 4218 emitLabel(throwLabel.get()); 4219 emitThrow(originalFinallyActionRegister.get()); 4220 4221 emitLabel(endCatchLabel.get()); 4222 } 4351 4352 emitLabel(catchDone.get()); 4353 emitThrow(exceptionRegister.get()); 4354 4355 // Absorb exception. 4356 popTryAndEmitCatch(returnCallTryData, newTemporary(), 4357 newTemporary(), catchDone.get(), HandlerType::SynthesizedFinally); 4358 emitThrow(exceptionRegister.get()); 4223 4359 } 4224 4360 … … 4241 4377 4242 4378 // IteratorClose sequence for break-ed control flow. 4243 pop FinallyControlFlowScope();4379 popIteratorCloseControlFlowScope(); 4244 4380 emitIteratorClose(iterator.get(), node); 4245 4381 emitLabel(loopDone.get()); … … 4357 4493 { 4358 4494 emitOpcode(op_is_object); 4359 instructions().append(dst->index());4360 instructions().append(src->index());4361 return dst;4362 }4363 4364 RegisterID* BytecodeGenerator::emitIsNumber(RegisterID* dst, RegisterID* src)4365 {4366 emitOpcode(op_is_number);4367 4495 instructions().append(dst->index()); 4368 4496 instructions().append(src->index()); … … 4657 4785 { 4658 4786 RefPtr<RegisterID> returnRegister = generatorValueRegister(); 4659 bool hasFinally = emitReturnViaFinallyIfNeeded(returnRegister.get()); 4660 if (!hasFinally) 4661 emitReturn(returnRegister.get()); 4787 if (isInFinallyBlock()) { 4788 returnRegister = emitMove(newTemporary(), returnRegister.get()); 4789 emitPopScopes(scopeRegister(), 0); 4790 } 4791 emitReturn(returnRegister.get()); 4662 4792 } 4663 4793 … … 4762 4892 4763 4893 emitLabel(returnSequence.get()); 4764 bool hasFinally = emitReturnViaFinallyIfNeeded(value.get());4765 if (!hasFinally)4766 4894 if (isInFinallyBlock()) 4895 emitPopScopes(scopeRegister(), 0); 4896 emitReturn(value.get()); 4767 4897 } 4768 4898 … … 4792 4922 RegisterID* completedState = emitLoad(nullptr, jsNumber(state)); 4793 4923 emitPutById(generatorRegister(), propertyNames().builtinNames().generatorStatePrivateName(), completedState); 4794 }4795 4796 bool BytecodeGenerator::emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label* jumpTarget)4797 {4798 ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0);4799 size_t scopeDelta = labelScopeDepth() - targetLabelScopeDepth;4800 ASSERT(scopeDelta <= m_controlFlowScopeStack.size());4801 if (!scopeDelta)4802 return false; // No finallys to thread through.4803 4804 ControlFlowScope* topScope = &m_controlFlowScopeStack.last();4805 ControlFlowScope* bottomScope = &m_controlFlowScopeStack.last() - scopeDelta;4806 4807 FinallyContext* innermostFinallyContext = nullptr;4808 FinallyContext* outermostFinallyContext = nullptr;4809 while (topScope > bottomScope) {4810 if (topScope->isFinallyScope()) {4811 FinallyContext* finallyContext = &topScope->finallyContext;4812 if (!innermostFinallyContext)4813 innermostFinallyContext = finallyContext;4814 outermostFinallyContext = finallyContext;4815 finallyContext->incNumberOfBreaksOrContinues();4816 }4817 --topScope;4818 }4819 if (!outermostFinallyContext)4820 return false; // No finallys to thread through.4821 4822 int jumpID = bytecodeOffsetToJumpID(instructions().size());4823 int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth);4824 outermostFinallyContext->registerJump(jumpID, lexicalScopeIndex, jumpTarget);4825 4826 emitSetFinallyActionToJumpID(jumpID);4827 emitJump(innermostFinallyContext->finallyLabel());4828 return true; // We'll be jumping to a finally block.4829 }4830 4831 bool BytecodeGenerator::emitReturnViaFinallyIfNeeded(RegisterID* returnRegister)4832 {4833 if (!m_controlFlowScopeStack.size())4834 return false; // No finallys to thread through.4835 4836 ControlFlowScope* topScope = &m_controlFlowScopeStack.last();4837 ControlFlowScope* bottomScope = &m_controlFlowScopeStack.first();4838 4839 FinallyContext* innermostFinallyContext = nullptr;4840 while (topScope >= bottomScope) {4841 if (topScope->isFinallyScope()) {4842 FinallyContext* finallyContext = &topScope->finallyContext;4843 if (!innermostFinallyContext)4844 innermostFinallyContext = finallyContext;4845 finallyContext->setHandlesReturns();4846 }4847 --topScope;4848 }4849 if (!innermostFinallyContext)4850 return false; // No finallys to thread through.4851 4852 emitSetFinallyActionToReturnCompletion();4853 emitSetFinallyReturnValueRegister(returnRegister);4854 emitJump(innermostFinallyContext->finallyLabel());4855 return true; // We'll be jumping to a finally block.4856 }4857 4858 void BytecodeGenerator::emitFinallyCompletion(FinallyContext& context, Label* normalCompletionLabel)4859 {4860 // FIXME: switch the finallyActionRegister to only store int values for all CompletionTypes. This is more optimal for JIT type speculation.4861 // https://bugs.webkit.org/show_bug.cgi?id=1659794862 emitJumpIfFinallyActionIsNormalCompletion(normalCompletionLabel);4863 4864 if (context.numberOfBreaksOrContinues() || context.handlesReturns()) {4865 FinallyContext* outerContext = context.outerContext();4866 if (outerContext) {4867 // We are not the outermost finally.4868 size_t numberOfJumps = context.numberOfJumps();4869 for (size_t i = 0; i < numberOfJumps; i++) {4870 RefPtr<Label> nextLabel = newLabel();4871 auto& jump = context.jumps(i);4872 emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());4873 4874 restoreScopeRegister(jump.targetLexicalScopeIndex);4875 emitSetFinallyActionToNormalCompletion();4876 emitJump(jump.targetLabel.get());4877 4878 emitLabel(nextLabel.get());4879 }4880 4881 bool hasBreaksOrContinuesNotCoveredByJumps = context.numberOfBreaksOrContinues() > numberOfJumps;4882 if (hasBreaksOrContinuesNotCoveredByJumps || context.handlesReturns())4883 emitJumpIfFinallyActionIsNotThrowCompletion(outerContext->finallyLabel());4884 4885 } else {4886 // We are the outermost finally.4887 size_t numberOfJumps = context.numberOfJumps();4888 ASSERT(numberOfJumps == context.numberOfBreaksOrContinues());4889 4890 for (size_t i = 0; i < numberOfJumps; i++) {4891 RefPtr<Label> nextLabel = newLabel();4892 auto& jump = context.jumps(i);4893 emitJumpIfFinallyActionIsNotJump(jump.jumpID, nextLabel.get());4894 4895 restoreScopeRegister(jump.targetLexicalScopeIndex);4896 emitSetFinallyActionToNormalCompletion();4897 emitJump(jump.targetLabel.get());4898 4899 emitLabel(nextLabel.get());4900 }4901 4902 if (context.handlesReturns()) {4903 RefPtr<Label> notReturnLabel = newLabel();4904 emitJumpIfFinallyActionIsNotReturnCompletion(notReturnLabel.get());4905 4906 emitWillLeaveCallFrameDebugHook();4907 emitReturn(finallyReturnValueRegister(), ReturnFrom::Finally);4908 4909 emitLabel(notReturnLabel.get());4910 }4911 }4912 }4913 emitThrow(finallyActionRegister());4914 }4915 4916 bool BytecodeGenerator::allocateFinallyRegisters()4917 {4918 if (m_finallyActionRegister)4919 return false;4920 4921 ASSERT(!m_finallyReturnValueRegister);4922 m_finallyActionRegister = newTemporary();4923 m_finallyReturnValueRegister = newTemporary();4924 4925 emitSetFinallyActionToNormalCompletion();4926 emitMoveEmptyValue(m_finallyReturnValueRegister.get());4927 return true;4928 }4929 4930 void BytecodeGenerator::releaseFinallyRegisters()4931 {4932 ASSERT(m_finallyActionRegister && m_finallyReturnValueRegister);4933 m_finallyActionRegister = nullptr;4934 m_finallyReturnValueRegister = nullptr;4935 }4936 4937 void BytecodeGenerator::emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget)4938 {4939 RefPtr<RegisterID> tempRegister = newTemporary();4940 RegisterID* valueConstant = addConstantValue(JSValue(value));4941 OperandTypes operandTypes = OperandTypes(ResultType::numberTypeIsInt32(), ResultType::unknownType());4942 4943 auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, finallyActionRegister(), operandTypes);4944 emitJumpIfTrue(equivalenceResult, jumpTarget);4945 4924 } 4946 4925 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r210007 r210010 81 81 }; 82 82 83 struct FinallyJump {84 FinallyJump(int jumpID, int targetLexicalScopeIndex, Label* targetLabel)85 : jumpID(jumpID)86 , targetLexicalScopeIndex(targetLexicalScopeIndex)87 , targetLabel(targetLabel)88 { }89 90 int jumpID { 0 };91 int targetLexicalScopeIndex { 0 };92 RefPtr<Label> targetLabel;93 };94 95 83 struct FinallyContext { 96 FinallyContext() { } 97 FinallyContext(FinallyContext* outerContext, Label* finallyLabel, int finallyDepth) 98 : m_outerContext(outerContext) 99 , m_finallyLabel(finallyLabel) 100 , m_finallyDepth(finallyDepth) 101 { 102 ASSERT(!m_jumps || m_jumps->isEmpty()); 103 } 104 105 FinallyContext* outerContext() const { return m_outerContext; } 106 Label* finallyLabel() const { return m_finallyLabel; } 107 int depth() const { return m_finallyDepth; } 108 109 unsigned numberOfBreaksOrContinues() const { return m_numberOfBreaksOrContinues; } 110 void incNumberOfBreaksOrContinues() 111 { 112 ASSERT(m_numberOfBreaksOrContinues < INT_MAX); 113 m_numberOfBreaksOrContinues++; 114 } 115 116 bool handlesReturns() const { return m_handlesReturns; } 117 void setHandlesReturns() { m_handlesReturns = true; } 118 119 void registerJump(int jumpID, int lexicalScopeIndex, Label* targetLabel) 120 { 121 if (!m_jumps) 122 m_jumps = std::make_unique<Vector<FinallyJump>>(); 123 m_jumps->append(FinallyJump(jumpID, lexicalScopeIndex, targetLabel)); 124 } 125 126 size_t numberOfJumps() const { return m_jumps ? m_jumps->size() : 0; } 127 FinallyJump& jumps(size_t i) { return (*m_jumps)[i]; } 128 129 private: 130 FinallyContext* m_outerContext { nullptr }; 131 Label* m_finallyLabel { nullptr }; 132 int m_finallyDepth { 0 }; 133 unsigned m_numberOfBreaksOrContinues { 0 }; 134 bool m_handlesReturns { false }; 135 std::unique_ptr<Vector<FinallyJump>> m_jumps; 84 StatementNode* finallyBlock; 85 RegisterID* iterator; 86 ThrowableExpressionData* enumerationNode; 87 unsigned controlFlowScopeStackSize; 88 unsigned switchContextStackSize; 89 unsigned forInContextStackSize; 90 unsigned tryContextStackSize; 91 unsigned labelScopesSize; 92 unsigned lexicalScopeStackSize; 93 int finallyDepth; 94 int dynamicScopeDepth; 136 95 }; 137 96 138 97 struct ControlFlowScope { 139 typedef uint8_t Type; 140 enum { 141 Label, 142 Finally 143 }; 144 ControlFlowScope(Type type, int lexicalScopeIndex, FinallyContext&& finallyContext = FinallyContext()) 145 : type(type) 146 , lexicalScopeIndex(lexicalScopeIndex) 147 , finallyContext(std::forward<FinallyContext>(finallyContext)) 148 { } 149 150 bool isLabelScope() const { return type == Label; } 151 bool isFinallyScope() const { return type == Finally; } 152 153 Type type; 154 int lexicalScopeIndex; 98 bool isFinallyBlock; 155 99 FinallyContext finallyContext; 156 100 }; … … 662 606 RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*); 663 607 664 enum class ReturnFrom { Normal, Finally }; 665 RegisterID* emitReturn(RegisterID* src, ReturnFrom = ReturnFrom::Normal); 608 RegisterID* emitReturn(RegisterID* src); 666 609 RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); } 667 610 … … 684 627 PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target); 685 628 PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target); 629 void emitPopScopes(RegisterID* srcDst, int targetScopeDepth); 686 630 687 631 void emitEnter(); … … 706 650 RegisterID* emitIsSet(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSSetType); } 707 651 RegisterID* emitIsObject(RegisterID* dst, RegisterID* src); 708 RegisterID* emitIsNumber(RegisterID* dst, RegisterID* src);709 652 RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src); 710 653 RegisterID* emitIsEmpty(RegisterID* dst, RegisterID* src); … … 721 664 722 665 // Start a try block. 'start' must have been emitted. 723 TryData* pushTry(Label* start , Label* handlerLabel, HandlerType);666 TryData* pushTry(Label* start); 724 667 // End a try block. 'end' must have been emitted. 725 void popTry(TryData*, Label* end); 726 void emitCatch(RegisterID* exceptionRegister, RegisterID* thrownValueRegister); 727 728 private: 729 static const int CurrentLexicalScopeIndex = -2; 730 static const int OutermostLexicalScopeIndex = -1; 731 732 public: 733 void restoreScopeRegister(); 734 void restoreScopeRegister(int lexicalScopeIndex); 735 736 int currentLexicalScopeIndex() const 737 { 738 int size = static_cast<int>(m_lexicalScopeStack.size()); 739 ASSERT(static_cast<size_t>(size) == m_lexicalScopeStack.size()); 740 ASSERT(size >= 0); 741 int index = size - 1; 742 return index; 743 } 744 745 int labelScopeDepthToLexicalScopeIndex(int labelScopeDepth); 668 void popTryAndEmitCatch(TryData*, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType); 746 669 747 670 void emitThrow(RegisterID* exc) … … 776 699 void emitWillLeaveCallFrameDebugHook(); 777 700 778 class FinallyRegistersScope { 779 public: 780 FinallyRegistersScope(BytecodeGenerator& generator, bool needFinallyRegisters = true) 781 : m_generator(generator) 782 { 783 if (needFinallyRegisters && m_generator.allocateFinallyRegisters()) 784 m_needToReleaseOnDestruction = true; 785 } 786 ~FinallyRegistersScope() 787 { 788 if (m_needToReleaseOnDestruction) 789 m_generator.releaseFinallyRegisters(); 790 } 791 792 private: 793 BytecodeGenerator& m_generator; 794 bool m_needToReleaseOnDestruction { false }; 795 }; 796 797 RegisterID* finallyActionRegister() const 798 { 799 ASSERT(m_finallyActionRegister); 800 return m_finallyActionRegister.get(); 801 } 802 RegisterID* finallyReturnValueRegister() const 803 { 804 ASSERT(m_finallyReturnValueRegister); 805 return m_finallyReturnValueRegister.get(); 806 } 807 808 void emitSetFinallyActionToNormalCompletion() 809 { 810 emitMoveEmptyValue(m_finallyActionRegister.get()); 811 } 812 void emitSetFinallyActionToReturnCompletion() 813 { 814 emitLoad(finallyActionRegister(), JSValue(static_cast<int>(CompletionType::Return))); 815 } 816 void emitSetFinallyActionToJumpID(int jumpID) 817 { 818 emitLoad(finallyActionRegister(), JSValue(jumpID)); 819 } 820 void emitSetFinallyReturnValueRegister(RegisterID* reg) 821 { 822 emitMove(finallyReturnValueRegister(), reg); 823 } 824 825 void emitJumpIfFinallyActionIsNormalCompletion(Label* jumpTarget) 826 { 827 emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyActionRegister()), jumpTarget); 828 } 829 830 void emitJumpIfFinallyActionIsNotJump(int jumpID, Label* jumpTarget) 831 { 832 emitCompareFinallyActionAndJumpIf(op_nstricteq, jumpID, jumpTarget); 833 } 834 835 void emitJumpIfFinallyActionIsReturnCompletion(Label* jumpTarget) 836 { 837 emitCompareFinallyActionAndJumpIf(op_stricteq, static_cast<int>(CompletionType::Return), jumpTarget); 838 } 839 void emitJumpIfFinallyActionIsNotReturnCompletion(Label* jumpTarget) 840 { 841 emitCompareFinallyActionAndJumpIf(op_nstricteq, static_cast<int>(CompletionType::Return), jumpTarget); 842 } 843 844 void emitJumpIfFinallyActionIsNotThrowCompletion(Label* jumpTarget) 845 { 846 emitJumpIfTrue(emitIsNumber(newTemporary(), finallyActionRegister()), jumpTarget); 847 } 848 void emitJumpIfCompletionTypeIsThrow(RegisterID* reg, Label* jumpTarget) 849 { 850 emitJumpIfFalse(emitIsNumber(newTemporary(), reg), jumpTarget); 851 } 852 853 bool emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label* jumpTarget); 854 bool emitReturnViaFinallyIfNeeded(RegisterID* returnRegister); 855 void emitFinallyCompletion(FinallyContext&, Label* normalCompletionLabel); 856 857 private: 858 void emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget); 859 860 int bytecodeOffsetToJumpID(unsigned offset) 861 { 862 int jumpID = offset + static_cast<int>(CompletionType::NumberOfTypes); 863 ASSERT(jumpID >= static_cast<int>(CompletionType::NumberOfTypes)); 864 return jumpID; 865 } 866 867 bool allocateFinallyRegisters(); 868 void releaseFinallyRegisters(); 869 870 public: 871 FinallyContext* pushFinallyControlFlowScope(Label* finallyLabel); 872 FinallyContext popFinallyControlFlowScope(); 701 bool isInFinallyBlock() { return m_finallyDepth > 0; } 702 703 void pushFinallyControlFlowScope(StatementNode* finallyBlock); 704 void popFinallyControlFlowScope(); 705 void pushIteratorCloseControlFlowScope(RegisterID* iterator, ThrowableExpressionData* enumerationNode); 706 void popIteratorCloseControlFlowScope(); 873 707 874 708 void pushIndexedForInScope(RegisterID* local, RegisterID* index); … … 964 798 void allocateCalleeSaveSpace(); 965 799 void allocateAndEmitScope(); 800 void emitComplexPopScopes(RegisterID*, ControlFlowScope* topScope, ControlFlowScope* bottomScope); 966 801 967 802 typedef HashMap<double, JSValue> NumberMap; … … 1101 936 RegisterID* m_promiseCapabilityRegister { nullptr }; 1102 937 1103 // The spec at https://tc39.github.io/ecma262/#sec-completion-record-specification-type says1104 // that there are 5 types of completions. Conceptually, we'll set m_finallyActionRegister1105 // to one of these completion types. However, to optimize our implementation, we'll encode1106 // these type info as follows:1107 //1108 // CompletionType::Normal - m_finallyActionRegister is empty.1109 // CompletionType::Break - m_finallyActionRegister is an int JSValue jumpID.1110 // CompletionType::Continue - m_finallyActionRegister is an int JSValue jumpID.1111 // CompletionType::Return - m_finallyActionRegister is the Return enum as an int JSValue.1112 // CompletionType::Throw - m_finallyActionRegister is the Exception object to rethrow.1113 //1114 // Hence, of the 5 completion types, only the CompletionType::Return enum value is used in1115 // our implementation. The rest are just provided for completeness.1116 1117 enum class CompletionType : int {1118 Normal,1119 Break,1120 Continue,1121 Return,1122 Throw,1123 1124 NumberOfTypes1125 };1126 1127 RefPtr<RegisterID> m_finallyActionRegister;1128 RefPtr<RegisterID> m_finallyReturnValueRegister;1129 1130 FinallyContext* m_currentFinallyContext { nullptr };1131 1132 938 SegmentedVector<RegisterID*, 16> m_localRegistersForCalleeSaveRegisters; 1133 939 SegmentedVector<RegisterID, 32> m_constantPoolRegisters; … … 1144 950 void popLocalControlFlowScope(); 1145 951 1146 // FIXME: Restore overflow checking with UnsafeVectorOverflow once SegmentVector supports it. 1147 // https://bugs.webkit.org/show_bug.cgi?id=165980 1148 SegmentedVector<ControlFlowScope, 16> m_controlFlowScopeStack; 952 Vector<ControlFlowScope, 0, UnsafeVectorOverflow> m_controlFlowScopeStack; 1149 953 Vector<SwitchInfo> m_switchContextStack; 1150 954 Vector<RefPtr<ForInContext>> m_forInContextStack; -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r210007 r210010 2999 2999 ASSERT(scope); 3000 3000 3001 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->continueTarget()); 3002 if (!hasFinally) { 3003 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth()); 3004 generator.restoreScopeRegister(lexicalScopeIndex); 3005 generator.emitJump(scope->continueTarget()); 3006 } 3001 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth()); 3002 generator.emitJump(scope->continueTarget()); 3007 3003 3008 3004 generator.emitProfileControlFlow(endOffset()); … … 3030 3026 ASSERT(scope); 3031 3027 3032 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->breakTarget()); 3033 if (!hasFinally) { 3034 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth()); 3035 generator.restoreScopeRegister(lexicalScopeIndex); 3036 generator.emitJump(scope->breakTarget()); 3037 } 3028 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth()); 3029 generator.emitJump(scope->breakTarget()); 3038 3030 3039 3031 generator.emitProfileControlFlow(endOffset()); … … 3052 3044 3053 3045 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd()); 3054 3055 bool hasFinally = generator.emitReturnViaFinallyIfNeeded(returnRegister.get());3056 if (!hasFinally) {3057 generator.emitWillLeaveCallFrameDebugHook();3058 generator.emitReturn(returnRegister.get()); 3059 }3060 3061 generator.emitProfileControlFlow(endOffset()); 3046 if (generator.isInFinallyBlock()) { 3047 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get()); 3048 generator.emitPopScopes(generator.scopeRegister(), 0); 3049 } 3050 3051 generator.emitWillLeaveCallFrameDebugHook(); 3052 generator.emitReturn(returnRegister.get()); 3053 generator.emitProfileControlFlow(endOffset()); 3062 3054 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the 3063 3055 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode. … … 3288 3280 3289 3281 ASSERT(m_catchBlock || m_finallyBlock); 3290 BytecodeGenerator::FinallyRegistersScope finallyRegistersScope(generator, m_finallyBlock);3291 3292 RefPtr<Label> catchLabel;3293 RefPtr<Label> catchEndLabel;3294 RefPtr<Label> finallyViaThrowLabel;3295 RefPtr<Label> finallyLabel;3296 RefPtr<Label> finallyEndLabel;3297 3282 3298 3283 RefPtr<Label> tryStartLabel = generator.newLabel(); 3299 3284 generator.emitLabel(tryStartLabel.get()); 3300 3301 if (m_finallyBlock) { 3302 finallyViaThrowLabel = generator.newLabel(); 3303 finallyLabel = generator.newLabel(); 3304 finallyEndLabel = generator.newLabel(); 3305 3306 generator.pushFinallyControlFlowScope(finallyLabel.get()); 3307 } 3285 3286 if (m_finallyBlock) 3287 generator.pushFinallyControlFlowScope(m_finallyBlock); 3288 TryData* tryData = generator.pushTry(tryStartLabel.get()); 3289 3290 generator.emitNode(dst, m_tryBlock); 3291 3308 3292 if (m_catchBlock) { 3309 catchLabel = generator.newLabel(); 3310 catchEndLabel = generator.newLabel(); 3311 } 3312 3313 Label* tryHandlerLabel = m_catchBlock ? catchLabel.get() : finallyViaThrowLabel.get(); 3314 HandlerType tryHandlerType = m_catchBlock ? HandlerType::Catch : HandlerType::Finally; 3315 TryData* tryData = generator.pushTry(tryStartLabel.get(), tryHandlerLabel, tryHandlerType); 3316 3317 generator.emitNode(dst, m_tryBlock); 3318 3319 // The finallyActionRegister is an empty value by default, which implies CompletionType::Normal. 3320 if (m_finallyBlock) 3321 generator.emitJump(finallyLabel.get()); 3322 else 3293 RefPtr<Label> catchEndLabel = generator.newLabel(); 3294 3295 // Normal path: jump over the catch block. 3323 3296 generator.emitJump(catchEndLabel.get()); 3324 3297 3325 RefPtr<Label> endTryLabel = generator.emitLabel(generator.newLabel().get());3326 generator.popTry(tryData, endTryLabel.get());3327 3328 if (m_catchBlock) {3329 3298 // Uncaught exception path: the catch block. 3330 generator.emitLabel(catchLabel.get()); 3299 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); 3300 RefPtr<RegisterID> exceptionRegister = generator.newTemporary(); 3331 3301 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary(); 3332 RegisterID* unused = generator.newTemporary(); 3333 generator.emitCatch(unused, thrownValueRegister.get()); 3334 generator.restoreScopeRegister(); 3335 3336 TryData* tryData = nullptr; 3302 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), here.get(), HandlerType::Catch); 3303 3337 3304 if (m_finallyBlock) { 3338 3305 // If the catch block throws an exception and we have a finally block, then the finally 3339 3306 // block should "catch" that exception. 3340 tryData = generator.pushTry( catchLabel.get(), finallyViaThrowLabel.get(), HandlerType::Finally);3307 tryData = generator.pushTry(here.get()); 3341 3308 } 3342 3309 … … 3350 3317 generator.emitLoad(thrownValueRegister.get(), jsUndefined()); 3351 3318 generator.emitPopCatchScope(m_lexicalVariables); 3352 3353 if (m_finallyBlock) {3354 generator.emitSetFinallyActionToNormalCompletion();3355 generator.emitJump(finallyLabel.get());3356 generator.popTry(tryData, finallyViaThrowLabel.get());3357 }3358 3359 3319 generator.emitLabel(catchEndLabel.get()); 3360 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);3361 3320 } 3362 3321 3363 3322 if (m_finallyBlock) { 3364 FinallyContext finallyContext = generator.popFinallyControlFlowScope(); 3365 3366 // Entry to the finally block for CompletionType::Throw. 3367 generator.emitLabel(finallyViaThrowLabel.get()); 3368 RegisterID* unused = generator.newTemporary(); 3369 generator.emitCatch(generator.finallyActionRegister(), unused); 3370 // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw. 3371 3372 // Entry to the finally block for CompletionTypes other than Throw. 3373 generator.emitLabel(finallyLabel.get()); 3374 generator.restoreScopeRegister(); 3323 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get()); 3324 3325 generator.popFinallyControlFlowScope(); 3326 3327 RefPtr<Label> finallyEndLabel = generator.newLabel(); 3375 3328 3376 3329 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1; 3330 3331 // Normal path: run the finally code, and jump to the end. 3377 3332 generator.emitProfileControlFlow(finallyStartOffset); 3378 3333 generator.emitNodeInTailPosition(dst, m_finallyBlock); 3379 3380 generator.emitFinallyCompletion(finallyContext, finallyEndLabel.get()); 3334 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1); 3335 generator.emitJump(finallyEndLabel.get()); 3336 3337 // Uncaught exception path: invoke the finally block, then re-throw the exception. 3338 RefPtr<RegisterID> exceptionRegister = generator.newTemporary(); 3339 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary(); 3340 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), preFinallyLabel.get(), HandlerType::Finally); 3341 generator.emitProfileControlFlow(finallyStartOffset); 3342 generator.emitNodeInTailPosition(dst, m_finallyBlock); 3343 generator.emitThrow(exceptionRegister.get()); 3344 3381 3345 generator.emitLabel(finallyEndLabel.get()); 3382 3346 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1); 3383 } 3347 } else 3348 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1); 3349 3384 3350 } 3385 3351 -
trunk/Source/WTF/ChangeLog
r209952 r210010 1 2016-12-19 Mark Lam <mark.lam@apple.com> 2 3 Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 2: Rollout r209952. 4 https://bugs.webkit.org/show_bug.cgi?id=166049 5 6 Not reviewed. 7 8 * wtf/SegmentedVector.h: 9 (WTF::SegmentedVector::last): 10 (WTF::SegmentedVector::first): Deleted. 11 (WTF::SegmentedVector::takeLast): Deleted. 12 1 13 2016-12-16 Mark Lam <mark.lam@apple.com> 2 14 -
trunk/Source/WTF/wtf/SegmentedVector.h
r209952 r210010 128 128 } 129 129 130 T& first() { return at(0); } 131 const T& first() const { return at(0); } 132 T& last() { return at(size() - 1); } 133 const T& last() const { return at(size() - 1); } 134 135 T takeLast() 136 { 137 ASSERT_WITH_SECURITY_IMPLICATION(!isEmpty()); 138 T result = WTFMove(last()); 139 --m_size; 140 return result; 130 T& last() 131 { 132 return at(size() - 1); 141 133 } 142 134
Note:
See TracChangeset
for help on using the changeset viewer.