Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (189335 => 189336)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-09-04 02:43:41 UTC (rev 189335)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-09-04 03:05:46 UTC (rev 189336)
@@ -191,6 +191,7 @@
, m_vm(&vm)
, m_isBuiltinFunction(codeBlock->isBuiltinFunction())
, m_usesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode())
+ , m_inTailPosition(Options::enableTailCalls() && constructorKind() == ConstructorKind::None && isStrictMode())
{
for (auto& constantRegister : m_linkTimeConstantRegisters)
constantRegister = nullptr;
@@ -2480,6 +2481,14 @@
return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
}
+RegisterID* BytecodeGenerator::emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+{
+ // FIXME: We should be emitting a new op_tail_call here when
+ // m_inTailPosition is false
+ // https://bugs.webkit.org/show_bug.cgi?id=148661
+ return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
+}
+
RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
{
return emitCall(op_call_eval, dst, func, NoExpectedFunction, callArguments, divot, divotStart, divotEnd);
@@ -2629,6 +2638,14 @@
return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
}
+RegisterID* BytecodeGenerator::emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+{
+ // FIXME: We should be emitting a new op_tail_call here when
+ // m_inTailPosition is false
+ // https://bugs.webkit.org/show_bug.cgi?id=148661
+ return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
+}
+
RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
{
return emitCallVarargs(op_construct_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (189335 => 189336)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-09-04 02:43:41 UTC (rev 189335)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-09-04 03:05:46 UTC (rev 189336)
@@ -39,6 +39,7 @@
#include "Interpreter.h"
#include "ParserError.h"
#include "RegisterID.h"
+#include "SetForScope.h"
#include "SymbolTable.h"
#include "Debugger.h"
#include "Nodes.h"
@@ -359,6 +360,12 @@
void emitNode(RegisterID* dst, StatementNode* n)
{
+ SetForScope<bool> tailPositionPoisoner(m_inTailPosition, false);
+ return emitNodeInTailPosition(dst, n);
+ }
+
+ void emitNodeInTailPosition(RegisterID* dst, StatementNode* n)
+ {
// Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
if (!m_vm->isSafeToRecurse()) {
@@ -370,11 +377,22 @@
void emitNode(StatementNode* n)
{
- emitNode(0, n);
+ emitNode(nullptr, n);
}
+ void emitNodeInTailPosition(StatementNode* n)
+ {
+ emitNodeInTailPosition(nullptr, n);
+ }
+
RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
{
+ SetForScope<bool> tailPositionPoisoner(m_inTailPosition, false);
+ return emitNodeInTailPosition(dst, n);
+ }
+
+ RegisterID* emitNodeInTailPosition(RegisterID* dst, ExpressionNode* n)
+ {
// Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
if (!m_vm->isSafeToRecurse())
@@ -384,9 +402,14 @@
RegisterID* emitNode(ExpressionNode* n)
{
- return emitNode(0, n);
+ return emitNode(nullptr, n);
}
+ RegisterID* emitNodeInTailPosition(ExpressionNode* n)
+ {
+ return emitNodeInTailPosition(nullptr, n);
+ }
+
void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
{
if (!m_vm->isSafeToRecurse()) {
@@ -518,8 +541,10 @@
ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+ RegisterID* emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+ RegisterID* emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
enum PropertyDescriptorOption {
PropertyConfigurable = 1,
@@ -833,6 +858,7 @@
bool m_expressionTooDeep { false };
bool m_isBuiltinFunction { false };
bool m_usesNonStrictEval { false };
+ bool m_inTailPosition { false };
};
}
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (189335 => 189336)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-09-04 02:43:41 UTC (rev 189335)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-09-04 03:05:46 UTC (rev 189336)
@@ -713,7 +713,7 @@
return ret;
}
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
- RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -733,7 +733,7 @@
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
// This passes NoExpectedFunction because we expect that if the function is in a
// local variable, then it's not one of our built-in constructors.
- RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -749,7 +749,7 @@
generator.emitResolveScope(callArguments.thisRegister(), var));
generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
- RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -817,7 +817,7 @@
generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
else
generator.emitMove(callArguments.thisRegister(), base.get());
- RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -836,7 +836,7 @@
generator.emitNode(callArguments.thisRegister(), m_base);
generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
- RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -865,7 +865,7 @@
argumentsRegister = generator.emitNode(subject);
generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
- generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
+ generator.emitCallVarargsInTailPosition(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
} else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
ArgumentListNode* oldList = m_args->m_listNode;
m_args->m_listNode = m_args->m_listNode->m_next;
@@ -873,13 +873,13 @@
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
m_args->m_listNode = oldList;
} else {
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
}
}
if (emitCallCheck) {
@@ -888,7 +888,7 @@
{
CallArguments callArguments(generator, m_args);
generator.emitMove(callArguments.thisRegister(), base.get());
- generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
}
generator.emitLabel(end.get());
}
@@ -951,7 +951,7 @@
generator.emitLabel(end.get());
};
generator.emitEnumeration(this, spread->_expression_(), extractor);
- generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
+ generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
} else if (m_args->m_listNode->m_next) {
ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
ASSERT(!m_args->m_listNode->m_next->m_next);
@@ -959,20 +959,20 @@
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
} else {
m_args->m_listNode = m_args->m_listNode->m_next;
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
}
m_args->m_listNode = oldList;
} else {
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
CallArguments callArguments(generator, m_args);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
- generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
}
} else {
ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
@@ -990,14 +990,14 @@
while ((args = args->m_next))
generator.emitNode(args->m_expr);
- generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
+ generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
}
if (emitCallCheck) {
generator.emitJump(end.get());
generator.emitLabel(realCall.get());
CallArguments callArguments(generator, m_args);
generator.emitMove(callArguments.thisRegister(), base.get());
- generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+ generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
generator.emitLabel(end.get());
}
generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
@@ -1632,7 +1632,7 @@
generator.emitJumpIfFalse(temp.get(), target.get());
else
generator.emitJumpIfTrue(temp.get(), target.get());
- generator.emitNode(temp.get(), m_expr2);
+ generator.emitNodeInTailPosition(temp.get(), m_expr2);
generator.emitLabel(target.get());
return generator.moveToDestinationIfNeeded(dst, temp.get());
@@ -1663,12 +1663,12 @@
generator.emitLabel(beforeThen.get());
generator.emitProfileControlFlow(m_expr1->startOffset());
- generator.emitNode(newDst.get(), m_expr1);
+ generator.emitNodeInTailPosition(newDst.get(), m_expr1);
generator.emitJump(afterElse.get());
generator.emitLabel(beforeElse.get());
generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
- generator.emitNode(newDst.get(), m_expr2);
+ generator.emitNodeInTailPosition(newDst.get(), m_expr2);
generator.emitLabel(afterElse.get());
@@ -1927,7 +1927,7 @@
CommaNode* node = this;
for (; node && node->next(); node = node->next())
generator.emitNode(generator.ignoredResult(), node->m_expr);
- return generator.emitNode(dst, node->m_expr);
+ return generator.emitNodeInTailPosition(dst, node->m_expr);
}
// ------------------------------ SourceElements -------------------------------
@@ -1941,7 +1941,7 @@
inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
for (StatementNode* statement = m_head; statement; statement = statement->next())
- generator.emitNode(dst, statement);
+ generator.emitNodeInTailPosition(dst, statement);
}
// ------------------------------ BlockNode ------------------------------------
@@ -2095,7 +2095,7 @@
generator.emitProfileControlFlow(m_ifBlock->startOffset());
if (!didFoldIfBlock) {
- generator.emitNode(dst, m_ifBlock);
+ generator.emitNodeInTailPosition(dst, m_ifBlock);
if (m_elseBlock)
generator.emitJump(afterElse.get());
}
@@ -2104,7 +2104,7 @@
if (m_elseBlock) {
generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
- generator.emitNode(dst, m_elseBlock);
+ generator.emitNodeInTailPosition(dst, m_elseBlock);
}
generator.emitLabel(afterElse.get());
@@ -2123,7 +2123,7 @@
generator.emitLoopHint();
generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
- generator.emitNode(dst, m_statement);
+ generator.emitNodeInTailPosition(dst, m_statement);
generator.emitLabel(scope->continueTarget());
generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
@@ -2146,7 +2146,7 @@
generator.emitLoopHint();
generator.emitProfileControlFlow(m_statement->startOffset());
- generator.emitNode(dst, m_statement);
+ generator.emitNodeInTailPosition(dst, m_statement);
generator.emitLabel(scope->continueTarget());
generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
@@ -2180,7 +2180,7 @@
generator.emitLoopHint();
generator.emitProfileControlFlow(m_statement->startOffset());
- generator.emitNode(dst, m_statement);
+ generator.emitNodeInTailPosition(dst, m_statement);
generator.emitLabel(scope->continueTarget());
generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
@@ -2557,7 +2557,7 @@
if (dst == generator.ignoredResult())
dst = 0;
- RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
+ RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
if (generator.isInFinallyBlock()) {
returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
@@ -2582,7 +2582,7 @@
RefPtr<RegisterID> scope = generator.emitNode(m_expr);
generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
generator.emitPushWithScope(scope.get());
- generator.emitNode(dst, m_statement);
+ generator.emitNodeInTailPosition(dst, m_statement);
generator.emitPopWithScope();
}
@@ -2835,7 +2835,10 @@
generator.emitPushCatchScope(m_thrownValueIdent, thrownValueRegister.get(), m_catchEnvironment);
generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
- generator.emitNode(dst, m_catchBlock);
+ if (m_finallyBlock)
+ generator.emitNode(dst, m_catchBlock);
+ else
+ generator.emitNodeInTailPosition(dst, m_catchBlock);
generator.emitPopCatchScope(m_catchEnvironment);
generator.emitLabel(catchEndLabel.get());
}
@@ -2851,7 +2854,7 @@
// Normal path: run the finally code, and jump to the end.
generator.emitProfileControlFlow(finallyStartOffset);
- generator.emitNode(dst, m_finallyBlock);
+ generator.emitNodeInTailPosition(dst, m_finallyBlock);
generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
generator.emitJump(finallyEndLabel.get());
@@ -2860,7 +2863,7 @@
RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), preFinallyLabel.get(), HandlerType::Finally);
generator.emitProfileControlFlow(finallyStartOffset);
- generator.emitNode(dst, m_finallyBlock);
+ generator.emitNodeInTailPosition(dst, m_finallyBlock);
generator.emitThrow(exceptionRegister.get());
generator.emitLabel(finallyEndLabel.get());