@@ -337,6 +337,12 @@ ParserError BytecodeGenerator::generate(unsigned& size)
337337 RELEASE_ASSERT (m_codeBlock->numCalleeLocals () < static_cast <unsigned >(FirstConstantRegisterIndex));
338338 size = instructions ().size ();
339339 m_codeBlock->finalize (m_writer.finalize ());
340+
341+ // We limit total bytecode sequence size to int32_t so that we can use int32_t jump offsets.
342+ // Also, this allows us to use one bit of bytecode for some flag, including "ignore-result-flag".
343+ if (size > static_cast <unsigned >(INT32_MAX ))
344+ return ParserError (ParserError::OutOfMemory);
345+
340346 if (m_expressionTooDeep)
341347 return ParserError (ParserError::OutOfMemory);
342348 return ParserError (ParserError::ErrorNone);
@@ -353,7 +359,8 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedP
353359 , m_expressionTooDeep(false )
354360 , m_isBuiltinFunction(false )
355361 , m_usesSloppyEval(false )
356- , m_inTailPosition(false )
362+ , m_allowTailCallOptimization(false )
363+ , m_allowCallIgnoreResultOptimization(false )
357364 , m_needsToUpdateArrowFunctionContext(programNode->usesArrowFunction () || programNode->usesEval())
358365 , m_ecmaMode(ECMAMode::fromBool(programNode->isStrictMode ()))
359366{
@@ -405,7 +412,10 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
405412 // https://bugs.webkit.org/show_bug.cgi?id=148819
406413 //
407414 // Note that we intentionally enable tail call for naked constructors since it does not have special code for "return".
408- , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && functionNode->isStrictMode())
415+ , m_allowTailCallOptimization(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && functionNode->isStrictMode())
416+ // Currently, we're only conservatively allowing CallIgnoreResult optimization on tail call results that are
417+ // not in return statements. We're not attempting to eliminate all unused call results.
418+ , m_allowCallIgnoreResultOptimization(true )
409419 , m_needsToUpdateArrowFunctionContext(functionNode->usesArrowFunction () || functionNode->usesEval())
410420 , m_ecmaMode(ECMAMode::fromBool(functionNode->isStrictMode ()))
411421 , m_derivedContextType(codeBlock->derivedContextType ())
@@ -902,7 +912,8 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod
902912 , m_expressionTooDeep(false )
903913 , m_isBuiltinFunction(false )
904914 , m_usesSloppyEval(evalNode->usesEval () && !evalNode->isStrictMode())
905- , m_inTailPosition(false )
915+ , m_allowTailCallOptimization(false )
916+ , m_allowCallIgnoreResultOptimization(false )
906917 , m_needsToUpdateArrowFunctionContext(evalNode->usesArrowFunction () || evalNode->usesEval())
907918 , m_ecmaMode(ECMAMode::fromBool(evalNode->isStrictMode ()))
908919 , m_derivedContextType(codeBlock->derivedContextType ())
@@ -965,7 +976,8 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNod
965976 , m_expressionTooDeep(false )
966977 , m_isBuiltinFunction(false )
967978 , m_usesSloppyEval(false )
968- , m_inTailPosition(false )
979+ , m_allowTailCallOptimization(false )
980+ , m_allowCallIgnoreResultOptimization(false )
969981 , m_needsToUpdateArrowFunctionContext(moduleProgramNode->usesArrowFunction () || moduleProgramNode->usesEval())
970982 , m_ecmaMode(ECMAMode::strict())
971983{
@@ -3472,10 +3484,12 @@ RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, Expec
34723484
34733485RegisterID* BytecodeGenerator::emitCallInTailPosition (RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
34743486{
3475- if (m_inTailPosition ) {
3487+ if (m_allowTailCallOptimization ) {
34763488 m_codeBlock->setHasTailCalls ();
34773489 return emitCall<OpTailCall>(dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
34783490 }
3491+ if (m_allowCallIgnoreResultOptimization)
3492+ return emitCall<OpCallIgnoreResult>(dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
34793493 return emitCall<OpCall>(dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
34803494}
34813495
@@ -3546,7 +3560,7 @@ template<typename CallOp>
35463560RegisterID* BytecodeGenerator::emitCall (RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
35473561{
35483562 constexpr auto opcodeID = CallOp::opcodeID;
3549- ASSERT (opcodeID == op_call || opcodeID == op_call_direct_eval || opcodeID == op_tail_call);
3563+ ASSERT (opcodeID == op_call || opcodeID == op_call_direct_eval || opcodeID == op_tail_call || opcodeID == op_call_ignore_result );
35503564 ASSERT (func->refCount ());
35513565
35523566 // Generate code for arguments.
@@ -3596,7 +3610,11 @@ RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, Expec
35963610 ASSERT (dst != ignoredResult ());
35973611 if constexpr (opcodeID == op_call_direct_eval)
35983612 CallOp::emit (this , dst, func, callArguments.argumentCountIncludingThis (), callArguments.stackOffset (), thisRegister (), scopeRegister (), ecmaMode ());
3599- else
3613+ else if constexpr (opcodeID == op_call_ignore_result) {
3614+ CallOp::emit (this , func, callArguments.argumentCountIncludingThis (), callArguments.stackOffset ());
3615+ if (shouldEmitTypeProfilerHooks ())
3616+ emitLoad (dst, jsUndefined ());
3617+ } else
36003618 CallOp::emit (this , dst, func, callArguments.argumentCountIncludingThis (), callArguments.stackOffset ());
36013619
36023620 if (expectedFunction != NoExpectedFunction)
@@ -3612,7 +3630,7 @@ RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func
36123630
36133631RegisterID* BytecodeGenerator::emitCallVarargsInTailPosition (RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
36143632{
3615- if (m_inTailPosition )
3633+ if (m_allowTailCallOptimization )
36163634 return emitCallVarargs<OpTailCallVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
36173635 return emitCallVarargs<OpCallVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
36183636}
@@ -3625,7 +3643,7 @@ RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID*
36253643RegisterID* BytecodeGenerator::emitCallForwardArgumentsInTailPosition (RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
36263644{
36273645 // We must emit a tail call here because we did not allocate an arguments object thus we would otherwise have no way to correctly make this call.
3628- ASSERT (m_inTailPosition || !Options::useTailCalls ());
3646+ ASSERT (m_allowTailCallOptimization || !Options::useTailCalls ());
36293647 return emitCallVarargs<OpTailCallForwardArguments>(dst, func, thisRegister, nullptr , firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
36303648}
36313649
0 commit comments