Changeset 210010 in webkit


Ignore:
Timestamp:
Dec 19, 2016 6:03:02 PM (7 years ago)
Author:
mark.lam@apple.com
Message:

Rolling out r209974 and r209952. They break some websites in mysterious ways. Step 2: Rollout r209952.
https://bugs.webkit.org/show_bug.cgi?id=166049

Not reviewed.

JSTests:

  • stress/deeply-nested-finallys.js: Removed.
  • stress/test-finally.js: Removed.

Source/JavaScriptCore:

  • bytecode/HandlerInfo.h:

(JSC::HandlerInfoBase::typeName):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitReturn):
(JSC::BytecodeGenerator::pushFinallyControlFlowScope):
(JSC::BytecodeGenerator::pushIteratorCloseControlFlowScope):
(JSC::BytecodeGenerator::popFinallyControlFlowScope):
(JSC::BytecodeGenerator::popIteratorCloseControlFlowScope):
(JSC::BytecodeGenerator::emitComplexPopScopes):
(JSC::BytecodeGenerator::emitPopScopes):
(JSC::BytecodeGenerator::pushTry):
(JSC::BytecodeGenerator::popTryAndEmitCatch):
(JSC::BytecodeGenerator::labelScopeDepth):
(JSC::BytecodeGenerator::pushLocalControlFlowScope):
(JSC::BytecodeGenerator::popLocalControlFlowScope):
(JSC::BytecodeGenerator::emitEnumeration):
(JSC::BytecodeGenerator::emitYield):
(JSC::BytecodeGenerator::emitDelegateYield):
(JSC::BytecodeGenerator::popTry): Deleted.
(JSC::BytecodeGenerator::emitCatch): Deleted.
(JSC::BytecodeGenerator::restoreScopeRegister): Deleted.
(JSC::BytecodeGenerator::labelScopeDepthToLexicalScopeIndex): Deleted.
(JSC::BytecodeGenerator::emitIsNumber): Deleted.
(JSC::BytecodeGenerator::emitJumpViaFinallyIfNeeded): Deleted.
(JSC::BytecodeGenerator::emitReturnViaFinallyIfNeeded): Deleted.
(JSC::BytecodeGenerator::emitFinallyCompletion): Deleted.
(JSC::BytecodeGenerator::allocateFinallyRegisters): Deleted.
(JSC::BytecodeGenerator::releaseFinallyRegisters): Deleted.
(JSC::BytecodeGenerator::emitCompareFinallyActionAndJumpIf): Deleted.

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::isInFinallyBlock):
(JSC::FinallyJump::FinallyJump): Deleted.
(JSC::FinallyContext::FinallyContext): Deleted.
(JSC::FinallyContext::outerContext): Deleted.
(JSC::FinallyContext::finallyLabel): Deleted.
(JSC::FinallyContext::depth): Deleted.
(JSC::FinallyContext::numberOfBreaksOrContinues): Deleted.
(JSC::FinallyContext::incNumberOfBreaksOrContinues): Deleted.
(JSC::FinallyContext::handlesReturns): Deleted.
(JSC::FinallyContext::setHandlesReturns): Deleted.
(JSC::FinallyContext::registerJump): Deleted.
(JSC::FinallyContext::numberOfJumps): Deleted.
(JSC::FinallyContext::jumps): Deleted.
(JSC::ControlFlowScope::ControlFlowScope): Deleted.
(JSC::ControlFlowScope::isLabelScope): Deleted.
(JSC::ControlFlowScope::isFinallyScope): Deleted.
(JSC::BytecodeGenerator::currentLexicalScopeIndex): Deleted.
(JSC::BytecodeGenerator::FinallyRegistersScope::FinallyRegistersScope): Deleted.
(JSC::BytecodeGenerator::FinallyRegistersScope::~FinallyRegistersScope): Deleted.
(JSC::BytecodeGenerator::finallyActionRegister): Deleted.
(JSC::BytecodeGenerator::finallyReturnValueRegister): Deleted.
(JSC::BytecodeGenerator::emitSetFinallyActionToNormalCompletion): Deleted.
(JSC::BytecodeGenerator::emitSetFinallyActionToReturnCompletion): Deleted.
(JSC::BytecodeGenerator::emitSetFinallyActionToJumpID): Deleted.
(JSC::BytecodeGenerator::emitSetFinallyReturnValueRegister): Deleted.
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNormalCompletion): Deleted.
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotJump): Deleted.
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsReturnCompletion): Deleted.
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotReturnCompletion): Deleted.
(JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotThrowCompletion): Deleted.
(JSC::BytecodeGenerator::emitJumpIfCompletionTypeIsThrow): Deleted.
(JSC::BytecodeGenerator::bytecodeOffsetToJumpID): Deleted.

  • bytecompiler/NodesCodegen.cpp:

(JSC::ContinueNode::emitBytecode):
(JSC::BreakNode::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::TryNode::emitBytecode):

Source/WTF:

  • wtf/SegmentedVector.h:

(WTF::SegmentedVector::last):
(WTF::SegmentedVector::first): Deleted.
(WTF::SegmentedVector::takeLast): Deleted.

Location:
trunk
Files:
2 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r209980 r210010  
     12016-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
    1112016-12-19  Saam Barati  <sbarati@apple.com>
    212
  • trunk/Source/JavaScriptCore/ChangeLog

    r210007 r210010  
     12016-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
    1782016-12-19  Mark Lam  <mark.lam@apple.com>
    279
  • trunk/Source/JavaScriptCore/bytecode/HandlerInfo.h

    r209952 r210010  
    3232
    3333enum class HandlerType {
    34     Catch = 0,
    35     Finally = 1,
    36     SynthesizedCatch = 2,
     34    Illegal = 0,
     35    Catch = 1,
     36    Finally = 2,
    3737    SynthesizedFinally = 3
    3838};
     
    5454        case HandlerType::Finally:
    5555            return "finally";
    56         case HandlerType::SynthesizedCatch:
    57             return "synthesized catch";
    5856        case HandlerType::SynthesizedFinally:
    5957            return "synthesized finally";
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r210007 r210010  
    157157            continue;
    158158       
     159        ASSERT(range.tryData->handlerType != HandlerType::Illegal);
    159160        UnlinkedHandlerInfo info(static_cast<uint32_t>(start), static_cast<uint32_t>(end),
    160161            static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->handlerType);
     
    680681    pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ);
    681682
    682     RefPtr<Label> catchLabel = newLabel();
    683683    TryData* tryFormalParametersData = nullptr;
    684     bool needTryCatch = isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList;
    685     if (needTryCatch) {
     684    if (isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList) {
    686685        RefPtr<Label> tryFormalParametersStart = emitLabel(newLabel().get());
    687         tryFormalParametersData = pushTry(tryFormalParametersStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
     686        tryFormalParametersData = pushTry(tryFormalParametersStart.get());
    688687    }
    689688
    690689    initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures, shouldCreateArgumentsVariableInParameterScope);
    691690
    692     if (needTryCatch) {
     691    if (isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList) {
    693692        RefPtr<Label> didNotThrow = newLabel();
    694693        emitJump(didNotThrow.get());
    695         emitLabel(catchLabel.get());
    696         popTry(tryFormalParametersData, catchLabel.get());
    697 
     694        RefPtr<RegisterID> exception = newTemporary();
    698695        RefPtr<RegisterID> thrownValue = newTemporary();
    699         RegisterID* 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);
    701698
    702699        // return promiseCapability.@reject(thrownValue)
     
    34973494}
    34983495
    3499 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src, ReturnFrom from)
     3496RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
    35003497{
    35013498    if (isConstructor()) {
     
    35033500        bool srcIsThis = src->index() == m_thisRegister.index();
    35043501
    3505         if (mightBeDerived && (srcIsThis || from == ReturnFrom::Finally))
     3502        if (mightBeDerived && srcIsThis)
    35063503            emitTDZCheck(src);
    35073504
    3508         if (!srcIsThis || from == ReturnFrom::Finally) {
     3505        if (!srcIsThis) {
    35093506            RefPtr<Label> isObjectLabel = newLabel();
    35103507            emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
     
    36843681}
    36853682
    3686 FinallyContext* BytecodeGenerator::pushFinallyControlFlowScope(Label* finallyLabel)
     3683void BytecodeGenerator::pushFinallyControlFlowScope(StatementNode* finallyBlock)
    36873684{
    36883685    // Reclaim free label scopes.
     
    36903687        m_labelScopes.removeLast();
    36913688
    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);
    36953706    m_finallyDepth++;
    3696     m_currentFinallyContext = &m_controlFlowScopeStack.last().finallyContext;
    3697     return m_currentFinallyContext;
    3698 }
    3699 
    3700 FinallyContext BytecodeGenerator::popFinallyControlFlowScope()
     3707}
     3708
     3709void 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
     3735void BytecodeGenerator::popFinallyControlFlowScope()
    37013736{
    37023737    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);
    37043742    ASSERT(m_finallyDepth > 0);
    3705     ASSERT(m_currentFinallyContext);
    3706     m_currentFinallyContext = m_currentFinallyContext->outerContext();
     3743    m_controlFlowScopeStack.removeLast();
    37073744    m_finallyDepth--;
    3708     return m_controlFlowScopeStack.takeLast().finallyContext;
     3745}
     3746
     3747void 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--;
    37093757}
    37103758
     
    38063854    emitMove(m_topMostScope, scopeRegister());
    38073855}
    3808 
    3809 TryData* BytecodeGenerator::pushTry(Label* start, Label* handlerLabel, HandlerType handlerType)
     3856   
     3857void 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
     3986void 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
     4007TryData* BytecodeGenerator::pushTry(Label* start)
    38104008{
    38114009    TryData tryData;
    3812     tryData.target = handlerLabel;
    3813     tryData.handlerType = handlerType;
     4010    tryData.target = newLabel();
     4011    tryData.handlerType = HandlerType::Illegal;
    38144012    m_tryData.append(tryData);
    38154013    TryData* result = &m_tryData.last();
     
    38244022}
    38254023
    3826 void BytecodeGenerator::popTry(TryData* tryData, Label* end)
     4024void BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType handlerType)
    38274025{
    38284026    m_usesExceptions = true;
     
    38364034    m_tryRanges.append(tryRange);
    38374035    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
    38424040    emitOpcode(op_catch);
    38434041    instructions().append(exceptionRegister->index());
    38444042    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);
    38824056}
    38834057
     
    38884062
    38894063int 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;
    38944066}
    38954067
     
    39614133void BytecodeGenerator::pushLocalControlFlowScope()
    39624134{
    3963     ControlFlowScope scope(ControlFlowScope::Label, currentLexicalScopeIndex());
    3964     m_controlFlowScopeStack.append(WTFMove(scope));
     4135    ControlFlowScope scope;
     4136    scope.isFinallyBlock = false;
     4137    m_controlFlowScopeStack.append(scope);
    39654138    m_localScopeDepth++;
    39664139}
     
    39694142{
    39704143    ASSERT(m_controlFlowScopeStack.size());
    3971     ASSERT(!m_controlFlowScopeStack.last().isFinallyScope());
     4144    ASSERT(!m_controlFlowScopeStack.last().isFinallyBlock);
    39724145    m_controlFlowScopeStack.removeLast();
    39734146    m_localScopeDepth--;
     
    41244297    return false;
    41254298}
    4126 
     4299   
    41274300void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable)
    41284301{
    4129     FinallyRegistersScope finallyRegistersScope(*this);
    4130 
    41314302    RefPtr<RegisterID> subject = newTemporary();
    41324303    emitNode(subject.get(), subjectNode);
     
    41394310
    41404311    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 
    41474312    // RefPtr<Register> iterator's lifetime must be longer than IteratorCloseContext.
    4148     FinallyContext* finallyContext = pushFinallyControlFlowScope(finallyLabel.get());
    4149 
     4313    pushIteratorCloseControlFlowScope(iterator.get(), node);
    41504314    {
    41514315        LabelScopePtr scope = newLabelScope(LabelScope::Loop);
     
    41594323        emitLoopHint();
    41604324
     4325        RefPtr<Label> tryStartLabel = newLabel();
    41614326        emitLabel(tryStartLabel.get());
    4162         TryData* tryData = pushTry(tryStartLabel.get(), finallyViaThrowLabel.get(), HandlerType::SynthesizedFinally);
     4327        TryData* tryData = pushTry(tryStartLabel.get());
    41634328        callBack(*this, value.get());
    41644329        emitJump(scope->continueTarget());
    41654330
    4166         // IteratorClose sequence for abrupt completions.
     4331        // IteratorClose sequence for throw-ed control flow.
    41674332        {
    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();
    41804340
    41814341            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());
    41864343
    41874344            RefPtr<Label> returnCallTryStart = newLabel();
    41884345            emitLabel(returnCallTryStart.get());
    4189             TryData* returnCallTryData = pushTry(returnCallTryStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
     4346            TryData* returnCallTryData = pushTry(returnCallTryStart.get());
    41904347
    41914348            CallArguments returnArguments(*this, nullptr);
    41924349            emitMove(returnArguments.thisRegister(), iterator.get());
    41934350            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());
    42234359        }
    42244360
     
    42414377
    42424378    // IteratorClose sequence for break-ed control flow.
    4243     popFinallyControlFlowScope();
     4379    popIteratorCloseControlFlowScope();
    42444380    emitIteratorClose(iterator.get(), node);
    42454381    emitLabel(loopDone.get());
     
    43574493{
    43584494    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);
    43674495    instructions().append(dst->index());
    43684496    instructions().append(src->index());
     
    46574785    {
    46584786        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());
    46624792    }
    46634793
     
    47624892
    47634893                    emitLabel(returnSequence.get());
    4764                     bool hasFinally = emitReturnViaFinallyIfNeeded(value.get());
    4765                     if (!hasFinally)
    4766                         emitReturn(value.get());
     4894                    if (isInFinallyBlock())
     4895                        emitPopScopes(scopeRegister(), 0);
     4896                    emitReturn(value.get());
    47674897                }
    47684898
     
    47924922    RegisterID* completedState = emitLoad(nullptr, jsNumber(state));
    47934923    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=165979
    4862     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);
    49454924}
    49464925
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r210007 r210010  
    8181    };
    8282
    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 
    9583    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;
    13695    };
    13796
    13897    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;
    15599        FinallyContext finallyContext;
    156100    };
     
    662606        RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
    663607
    664         enum class ReturnFrom { Normal, Finally };
    665         RegisterID* emitReturn(RegisterID* src, ReturnFrom = ReturnFrom::Normal);
     608        RegisterID* emitReturn(RegisterID* src);
    666609        RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
    667610
     
    684627        PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
    685628        PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
     629        void emitPopScopes(RegisterID* srcDst, int targetScopeDepth);
    686630
    687631        void emitEnter();
     
    706650        RegisterID* emitIsSet(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSSetType); }
    707651        RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
    708         RegisterID* emitIsNumber(RegisterID* dst, RegisterID* src);
    709652        RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
    710653        RegisterID* emitIsEmpty(RegisterID* dst, RegisterID* src);
     
    721664
    722665        // Start a try block. 'start' must have been emitted.
    723         TryData* pushTry(Label* start, Label* handlerLabel, HandlerType);
     666        TryData* pushTry(Label* start);
    724667        // 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);
    746669
    747670        void emitThrow(RegisterID* exc)
     
    776699        void emitWillLeaveCallFrameDebugHook();
    777700
    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();
    873707
    874708        void pushIndexedForInScope(RegisterID* local, RegisterID* index);
     
    964798        void allocateCalleeSaveSpace();
    965799        void allocateAndEmitScope();
     800        void emitComplexPopScopes(RegisterID*, ControlFlowScope* topScope, ControlFlowScope* bottomScope);
    966801
    967802        typedef HashMap<double, JSValue> NumberMap;
     
    1101936        RegisterID* m_promiseCapabilityRegister { nullptr };
    1102937
    1103         // The spec at https://tc39.github.io/ecma262/#sec-completion-record-specification-type says
    1104         // that there are 5 types of completions. Conceptually, we'll set m_finallyActionRegister
    1105         // to one of these completion types. However, to optimize our implementation, we'll encode
    1106         // 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 in
    1115         // 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             NumberOfTypes
    1125         };
    1126 
    1127         RefPtr<RegisterID> m_finallyActionRegister;
    1128         RefPtr<RegisterID> m_finallyReturnValueRegister;
    1129 
    1130         FinallyContext* m_currentFinallyContext { nullptr };
    1131 
    1132938        SegmentedVector<RegisterID*, 16> m_localRegistersForCalleeSaveRegisters;
    1133939        SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
     
    1144950        void popLocalControlFlowScope();
    1145951
    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;
    1149953        Vector<SwitchInfo> m_switchContextStack;
    1150954        Vector<RefPtr<ForInContext>> m_forInContextStack;
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r210007 r210010  
    29992999    ASSERT(scope);
    30003000
    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());
    30073003
    30083004    generator.emitProfileControlFlow(endOffset());
     
    30303026    ASSERT(scope);
    30313027
    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());
    30383030
    30393031    generator.emitProfileControlFlow(endOffset());
     
    30523044
    30533045    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()); 
    30623054    // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
    30633055    // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
     
    32883280
    32893281    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;
    32973282
    32983283    RefPtr<Label> tryStartLabel = generator.newLabel();
    32993284    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
    33083292    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.
    33233296        generator.emitJump(catchEndLabel.get());
    33243297
    3325     RefPtr<Label> endTryLabel = generator.emitLabel(generator.newLabel().get());
    3326     generator.popTry(tryData, endTryLabel.get());
    3327 
    3328     if (m_catchBlock) {
    33293298        // 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();
    33313301        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       
    33373304        if (m_finallyBlock) {
    33383305            // If the catch block throws an exception and we have a finally block, then the finally
    33393306            // block should "catch" that exception.
    3340             tryData = generator.pushTry(catchLabel.get(), finallyViaThrowLabel.get(), HandlerType::Finally);
     3307            tryData = generator.pushTry(here.get());
    33413308        }
    33423309
     
    33503317        generator.emitLoad(thrownValueRegister.get(), jsUndefined());
    33513318        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 
    33593319        generator.emitLabel(catchEndLabel.get());
    3360         generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
    33613320    }
    33623321
    33633322    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();
    33753328
    33763329        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.
    33773332        generator.emitProfileControlFlow(finallyStartOffset);
    33783333        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
    33813345        generator.emitLabel(finallyEndLabel.get());
    33823346        generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
    3383     }
     3347    } else
     3348        generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
     3349
    33843350}
    33853351
  • trunk/Source/WTF/ChangeLog

    r209952 r210010  
     12016-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
    1132016-12-16  Mark Lam  <mark.lam@apple.com>
    214
  • trunk/Source/WTF/wtf/SegmentedVector.h

    r209952 r210010  
    128128        }
    129129
    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);
    141133        }
    142134
Note: See TracChangeset for help on using the changeset viewer.