Ignore:
Timestamp:
Sep 3, 2015, 8:05:46 PM (10 years ago)
Author:
[email protected]
Message:

[ES6] Recognize calls in tail position
https://bugs.webkit.org/show_bug.cgi?id=148665

Reviewed by Saam Barati.

This patch adds the capability for the bytecode generator to recognize
and dispatch tail calls, as per ES6 spec:
http://www.ecma-international.org/ecma-262/6.0/#sec-isintailposition

This does not change the generated bytecode, but merely provides the
hook for generating tail calls in subsequent patches toward
https://bugs.webkit.org/show_bug.cgi?id=146477

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitCallInTailPosition):
(JSC::BytecodeGenerator::emitCallVarargsInTailPosition):

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::emitNode):
(JSC::BytecodeGenerator::emitNodeInTailPosition):

  • bytecompiler/NodesCodegen.cpp:

(JSC::FunctionCallValueNode::emitBytecode):
(JSC::FunctionCallResolveNode::emitBytecode):
(JSC::FunctionCallBracketNode::emitBytecode):
(JSC::FunctionCallDotNode::emitBytecode):
(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):
(JSC::LogicalOpNode::emitBytecode):
(JSC::ConditionalNode::emitBytecode):
(JSC::CommaNode::emitBytecode):
(JSC::SourceElements::emitBytecode):
(JSC::IfElseNode::emitBytecode):
(JSC::DoWhileNode::emitBytecode):
(JSC::WhileNode::emitBytecode):
(JSC::ForNode::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::WithNode::emitBytecode):
(JSC::TryNode::emitBytecode):

  • bytecompiler/SetForScope.h: Added.

(JSC::SetForScope::SetForScope):
(JSC::SetForScope::~SetForScope):

  • runtime/Options.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r189279 r189336  
    714714    }
    715715    generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    716     RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     716    RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    717717    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
    718718    return ret;
     
    734734        // This passes NoExpectedFunction because we expect that if the function is in a
    735735        // local variable, then it's not one of our built-in constructors.
    736         RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     736        RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    737737        generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
    738738        return ret;
     
    750750    generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
    751751    generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
    752     RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
     752    RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
    753753    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
    754754    return ret;
     
    818818    else
    819819        generator.emitMove(callArguments.thisRegister(), base.get());
    820     RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     820    RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    821821    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
    822822    return ret;
     
    837837    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
    838838    generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
    839     RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     839    RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    840840    generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
    841841    return ret;
     
    866866            generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
    867867            RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
    868             generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
     868            generator.emitCallVarargsInTailPosition(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
    869869        } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
    870870            ArgumentListNode* oldList = m_args->m_listNode;
     
    874874            CallArguments callArguments(generator, m_args);
    875875            generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
    876             generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     876            generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    877877            m_args->m_listNode = oldList;
    878878        } else {
     
    880880            CallArguments callArguments(generator, m_args);
    881881            generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    882             generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     882            generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    883883        }
    884884    }
     
    889889            CallArguments callArguments(generator, m_args);
    890890            generator.emitMove(callArguments.thisRegister(), base.get());
    891             generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     891            generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    892892        }
    893893        generator.emitLabel(end.get());
     
    952952                };
    953953                generator.emitEnumeration(this, spread->expression(), extractor);
    954                 generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
     954                generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
    955955            } else if (m_args->m_listNode->m_next) {
    956956                ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
     
    960960                CallArguments callArguments(generator, m_args);
    961961                generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
    962                 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     962                generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    963963            } else {
    964964                m_args->m_listNode = m_args->m_listNode->m_next;
     
    966966                CallArguments callArguments(generator, m_args);
    967967                generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
    968                 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     968                generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    969969            }
    970970            m_args->m_listNode = oldList;
     
    973973            CallArguments callArguments(generator, m_args);
    974974            generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    975             generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     975            generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    976976        }
    977977    } else {
     
    991991            generator.emitNode(args->m_expr);
    992992
    993         generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
     993        generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
    994994    }
    995995    if (emitCallCheck) {
     
    998998        CallArguments callArguments(generator, m_args);
    999999        generator.emitMove(callArguments.thisRegister(), base.get());
    1000         generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     1000        generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    10011001        generator.emitLabel(end.get());
    10021002    }
     
    16331633    else
    16341634        generator.emitJumpIfTrue(temp.get(), target.get());
    1635     generator.emitNode(temp.get(), m_expr2);
     1635    generator.emitNodeInTailPosition(temp.get(), m_expr2);
    16361636    generator.emitLabel(target.get());
    16371637
     
    16641664
    16651665    generator.emitProfileControlFlow(m_expr1->startOffset());
    1666     generator.emitNode(newDst.get(), m_expr1);
     1666    generator.emitNodeInTailPosition(newDst.get(), m_expr1);
    16671667    generator.emitJump(afterElse.get());
    16681668
    16691669    generator.emitLabel(beforeElse.get());
    16701670    generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
    1671     generator.emitNode(newDst.get(), m_expr2);
     1671    generator.emitNodeInTailPosition(newDst.get(), m_expr2);
    16721672
    16731673    generator.emitLabel(afterElse.get());
     
    19281928    for (; node && node->next(); node = node->next())
    19291929        generator.emitNode(generator.ignoredResult(), node->m_expr);
    1930     return generator.emitNode(dst, node->m_expr);
     1930    return generator.emitNodeInTailPosition(dst, node->m_expr);
    19311931}
    19321932
     
    19421942{
    19431943    for (StatementNode* statement = m_head; statement; statement = statement->next())
    1944         generator.emitNode(dst, statement);
     1944        generator.emitNodeInTailPosition(dst, statement);
    19451945}
    19461946
     
    20962096
    20972097    if (!didFoldIfBlock) {
    2098         generator.emitNode(dst, m_ifBlock);
     2098        generator.emitNodeInTailPosition(dst, m_ifBlock);
    20992099        if (m_elseBlock)
    21002100            generator.emitJump(afterElse.get());
     
    21052105    if (m_elseBlock) {
    21062106        generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
    2107         generator.emitNode(dst, m_elseBlock);
     2107        generator.emitNodeInTailPosition(dst, m_elseBlock);
    21082108    }
    21092109
     
    21242124    generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
    21252125
    2126     generator.emitNode(dst, m_statement);
     2126    generator.emitNodeInTailPosition(dst, m_statement);
    21272127
    21282128    generator.emitLabel(scope->continueTarget());
     
    21472147   
    21482148    generator.emitProfileControlFlow(m_statement->startOffset());
    2149     generator.emitNode(dst, m_statement);
     2149    generator.emitNodeInTailPosition(dst, m_statement);
    21502150
    21512151    generator.emitLabel(scope->continueTarget());
     
    21812181    generator.emitProfileControlFlow(m_statement->startOffset());
    21822182
    2183     generator.emitNode(dst, m_statement);
     2183    generator.emitNodeInTailPosition(dst, m_statement);
    21842184
    21852185    generator.emitLabel(scope->continueTarget());
     
    25582558        dst = 0;
    25592559
    2560     RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
     2560    RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
    25612561    generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
    25622562    if (generator.isInFinallyBlock()) {
     
    25832583    generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
    25842584    generator.emitPushWithScope(scope.get());
    2585     generator.emitNode(dst, m_statement);
     2585    generator.emitNodeInTailPosition(dst, m_statement);
    25862586    generator.emitPopWithScope();
    25872587}
     
    28362836        generator.emitPushCatchScope(m_thrownValueIdent, thrownValueRegister.get(), m_catchEnvironment);
    28372837        generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
    2838         generator.emitNode(dst, m_catchBlock);
     2838        if (m_finallyBlock)
     2839            generator.emitNode(dst, m_catchBlock);
     2840        else
     2841            generator.emitNodeInTailPosition(dst, m_catchBlock);
    28392842        generator.emitPopCatchScope(m_catchEnvironment);
    28402843        generator.emitLabel(catchEndLabel.get());
     
    28522855        // Normal path: run the finally code, and jump to the end.
    28532856        generator.emitProfileControlFlow(finallyStartOffset);
    2854         generator.emitNode(dst, m_finallyBlock);
     2857        generator.emitNodeInTailPosition(dst, m_finallyBlock);
    28552858        generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
    28562859        generator.emitJump(finallyEndLabel.get());
     
    28612864        generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), preFinallyLabel.get(), HandlerType::Finally);
    28622865        generator.emitProfileControlFlow(finallyStartOffset);
    2863         generator.emitNode(dst, m_finallyBlock);
     2866        generator.emitNodeInTailPosition(dst, m_finallyBlock);
    28642867        generator.emitThrow(exceptionRegister.get());
    28652868
Note: See TracChangeset for help on using the changeset viewer.