Ignore:
Timestamp:
Jul 24, 2013, 9:01:45 PM (12 years ago)
Author:
[email protected]
Message:

fourthTier: get rid of op_call_put_result
https://bugs.webkit.org/show_bug.cgi?id=117047

Reviewed by Gavin Barraclough.

Work in progress. This still makes like 20 tests crash.

op_call_put_result is an oddball. Its semantics are that it takes the return
value of a call instruction, which is set aside in regT0/regT1, and places them
into some stack slot. This is weird since there is an implicit contract with the
preceding bytecode instruction, and it's even weirder since it means that it
doesn't make sense to jump to it; for example OSR exit from the preceding call
instruction must make sure to jump over the op_call_put_result.

So this patch gets rid of op_call_put_result:

  • In bytecode, all calls return a value and we always allocate a temporary for that value even if it isn't used.
  • The LLInt does the return value saving as part of dispatchAfterCall().
  • The JIT and DFG do the return value saving as part of normal code generation. The DFG already did the right thing.
  • DFG->JIT OSR exit in the case of inlining will make the return PC's point at the CallLinkInfo::callReturnLocation, rather than the machine PC associated with the op_call_put_result instruction.
  • Tons of code gets removed. The DFG had to track whether or not a call had a return value in a bunch of places. It had to track the fact that we would exit to after the op_call_put_result. It was a mess. That mess is now gone.
  • bytecode/CallLinkStatus.cpp:

(JSC::CallLinkStatus::computeFromLLInt):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::printCallOp):
(JSC::CodeBlock::dumpArrayProfiling):
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):

  • bytecode/CodeBlock.h:
  • bytecode/Opcode.h:

(JSC):
(JSC::padOpcodeName):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitCall):
(JSC::BytecodeGenerator::emitCallVarargs):
(JSC::BytecodeGenerator::emitConstruct):

  • bytecompiler/NodesCodegen.cpp:

(JSC::NewExprNode::emitBytecode):
(JSC::FunctionCallValueNode::emitBytecode):
(JSC::FunctionCallResolveNode::emitBytecode):
(JSC::FunctionCallBracketNode::emitBytecode):
(JSC::FunctionCallDotNode::emitBytecode):
(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::ByteCodeParser):
(ByteCodeParser):
(JSC::DFG::ByteCodeParser::currentCodeOrigin):
(JSC::DFG::ByteCodeParser::addCall):
(JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
(JSC::DFG::ByteCodeParser::getPrediction):
(JSC::DFG::ByteCodeParser::handleCall):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::handleMinMax):
(JSC::DFG::ByteCodeParser::handleIntrinsic):
(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGOSRExitCompiler.cpp:
  • dfg/DFGOSRExitCompilerCommon.cpp:

(JSC::DFG::reifyInlinedCallFrames):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:

(JIT):

  • jit/JITCall.cpp:

(JSC::JIT::emitPutCallResult):
(JSC::JIT::compileLoadVarargs):
(JSC::JIT::compileCallEval):
(JSC::JIT::compileCallEvalSlowCase):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
(JSC::JIT::emit_op_call):
(JSC):
(JSC::JIT::emit_op_call_eval):
(JSC::JIT::emit_op_call_varargs):
(JSC::JIT::emit_op_construct):
(JSC::JIT::emitSlow_op_call):
(JSC::JIT::emitSlow_op_call_eval):
(JSC::JIT::emitSlow_op_call_varargs):
(JSC::JIT::emitSlow_op_construct):

  • jit/JITCall32_64.cpp:

(JSC::JIT::emitPutCallResult):
(JSC::JIT::compileLoadVarargs):
(JSC::JIT::compileCallEval):
(JSC::JIT::compileCallEvalSlowCase):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):

  • jit/JITOpcodes.cpp:

(JSC):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::genericCall):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • llint/LowLevelInterpreter.cpp:

(JSC::CLoop::execute):

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
Location:
trunk/Source/JavaScriptCore/bytecompiler
Files:
2 edited

Legend:

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

    r153199 r153200  
    18461846    // Emit call.
    18471847    UnlinkedArrayProfile arrayProfile = newArrayProfile();
    1848     emitOpcode(opcodeID);
     1848    UnlinkedValueProfile profile = emitProfiledOpcode(opcodeID);
     1849    ASSERT(dst);
     1850    ASSERT(dst != ignoredResult());
     1851    instructions().append(dst->index()); // result
    18491852    instructions().append(func->index()); // func
    18501853    instructions().append(callArguments.argumentCountIncludingThis()); // argCount
     
    18561859#endif
    18571860    instructions().append(arrayProfile);
    1858     if (dst != ignoredResult()) {
    1859         UnlinkedValueProfile profile = emitProfiledOpcode(op_call_put_result);
    1860         instructions().append(kill(dst));
    1861         instructions().append(profile);
    1862     }
     1861    instructions().append(profile);
    18631862   
    18641863    if (expectedFunction != NoExpectedFunction)
     
    18841883
    18851884    // Emit call.
    1886     emitOpcode(op_call_varargs);
     1885    UnlinkedValueProfile profile = emitProfiledOpcode(op_call_varargs);
     1886    ASSERT(dst != ignoredResult());
     1887    instructions().append(dst->index());
    18871888    instructions().append(func->index());
    18881889    instructions().append(thisRegister->index());
     
    18901891    instructions().append(firstFreeRegister->index());
    18911892    instructions().append(0); // Pad to make it as big as an op_call.
    1892     if (dst != ignoredResult()) {
    1893         UnlinkedValueProfile profile = emitProfiledOpcode(op_call_put_result);
    1894         instructions().append(kill(dst));
    1895         instructions().append(profile);
    1896     }
     1893    instructions().append(profile);
    18971894    if (m_shouldEmitProfileHooks) {
    18981895        emitOpcode(op_profile_did_call);
     
    19631960    expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
    19641961
    1965     emitOpcode(op_construct);
     1962    UnlinkedValueProfile profile = emitProfiledOpcode(op_construct);
     1963    ASSERT(dst != ignoredResult());
     1964    instructions().append(dst->index());
    19661965    instructions().append(func->index()); // func
    19671966    instructions().append(callArguments.argumentCountIncludingThis()); // argCount
     
    19731972#endif
    19741973    instructions().append(0);
    1975     if (dst != ignoredResult()) {
    1976         UnlinkedValueProfile profile = emitProfiledOpcode(op_call_put_result);
    1977         instructions().append(kill(dst));
    1978         instructions().append(profile);
    1979     }
     1974    instructions().append(profile);
    19801975
    19811976    if (expectedFunction != NoExpectedFunction)
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r153074 r153200  
    374374        expectedFunction = NoExpectedFunction;
    375375    RefPtr<RegisterID> func = generator.emitNode(m_expr);
     376    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
    376377    CallArguments callArguments(generator, m_args);
    377     return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     378    return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    378379}
    379380
     
    420421{
    421422    RefPtr<RegisterID> func = generator.emitNode(m_expr);
     423    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
    422424    CallArguments callArguments(generator, m_args);
    423425    generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    424     return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     426    return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    425427}
    426428
     
    434436    if (RegisterID* local = resolveResult.local()) {
    435437        RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
     438        RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
    436439        CallArguments callArguments(generator, m_args);
    437440        generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    438441        // This passes NoExpectedFunction because we expect that if the function is in a
    439442        // local variable, then it's not one of our built-in constructors.
    440         return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), func.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     443        return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    441444    }
    442445
    443446    if (resolveResult.isStatic()) {
    444447        RefPtr<RegisterID> func = generator.newTemporary();
     448        RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
    445449        CallArguments callArguments(generator, m_args);
    446450        generator.emitGetStaticVar(func.get(), resolveResult, m_ident);
    447451        generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    448         return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     452        return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    449453    }
    450454
    451455    RefPtr<RegisterID> func = generator.newTemporary();
     456    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
    452457    CallArguments callArguments(generator, m_args);
    453458    int identifierStart = divot() - divotStartOffset();
     
    455460    generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0, divotLine(), divotLineStart());
    456461    generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), resolveResult, m_ident);
    457     return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     462    return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    458463}
    459464
     
    466471    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
    467472    RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
     473    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
    468474    CallArguments callArguments(generator, m_args);
    469475    generator.emitMove(callArguments.thisRegister(), base.get());
    470     return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     476    return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    471477}
    472478
     
    476482{
    477483    RefPtr<RegisterID> function = generator.tempDestination(dst);
     484    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
    478485    CallArguments callArguments(generator, m_args);
    479486    generator.emitNode(callArguments.thisRegister(), m_base);
    480487    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
    481488    generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
    482     return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     489    return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    483490}
    484491
     
    490497    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
    491498    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
    492     RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
     499    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
    493500    generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
    494501    {
     
    500507            CallArguments callArguments(generator, m_args);
    501508            generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
    502             generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     509            generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    503510            generator.emitJump(end.get());
    504511
     
    508515            CallArguments callArguments(generator, m_args);
    509516            generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    510             generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     517            generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    511518            generator.emitJump(end.get());
    512519        }
     
    516523        CallArguments callArguments(generator, m_args);
    517524        generator.emitMove(callArguments.thisRegister(), base.get());
    518         generator.emitCall(finalDestinationOrIgnored.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     525        generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    519526    }
    520527    generator.emitLabel(end.get());
    521     return finalDestinationOrIgnored.get();
     528    return returnValue.get();
    522529}
    523530
     
    540547    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
    541548    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
    542     RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
     549    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
    543550    generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
    544551    {
     
    553560                    CallArguments callArguments(generator, m_args);
    554561                    generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
    555                     generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     562                    generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    556563                } else {
    557564                    m_args->m_listNode = m_args->m_listNode->m_next;
     
    559566                    CallArguments callArguments(generator, m_args);
    560567                    generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
    561                     generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     568                    generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    562569                }
    563570                m_args->m_listNode = oldList;
     
    566573                CallArguments callArguments(generator, m_args);
    567574                generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    568                 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     575                generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    569576            }
    570577        } else {
     
    587594                generator.emitNode(args->m_expr);
    588595
    589             generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     596            generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    590597        }
    591598        generator.emitJump(end.get());
     
    595602        CallArguments callArguments(generator, m_args);
    596603        generator.emitMove(callArguments.thisRegister(), base.get());
    597         generator.emitCall(finalDestinationOrIgnored.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
     604        generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
    598605    }
    599606    generator.emitLabel(end.get());
    600     return finalDestinationOrIgnored.get();
     607    return returnValue.get();
    601608}
    602609
Note: See TracChangeset for help on using the changeset viewer.