Ignore:
Timestamp:
May 20, 2010, 1:12:44 PM (15 years ago)
Author:
[email protected]
Message:

Bug 39408 - Unify JIT/interpreter return behaviour.

Reviewed by Oliver Hunt.

Presently the JIT and the interpreter have differing implementations in how
they handle storing the result of a function call back to the register file.
In both cases the op_call ( / _eval / _varargs / op_construct) opcode has an
operand indicating the VM register in which the result should be stored.
The JIT plants code after the call to store the result, so the value will be
stored as soon as the callee has returned. In the interpreter the call
passes the return value register id into the callee via the callee callframe,
and the callee is responsible for writing the result back into its callers
register file after it has restored the parents callframe pointer, but before
returning.

Instead, move the task of writing the call result to the register file into a
new opcode (op_call_put_result), and after returning the callee should leave
the return value in a canonical location. In the case of the interpreter,
this canonical location is a local variable in privateExecute
(functionReturnValue), in the case of the JIT this is the normal return value
registers (regT0, or regT1:regT0 in JSVALUE32_64). op_call_put_result stores
the result from the canonical location to the registerfile.

In addition to unifying JIT & interpreter behaviour this change allows us to
remove a slot from the callframe, omit the write of the result where the
return value from the call is not used, and provides a 2% speedup on sunspider
in the interpreter.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dump):

  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp:

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

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::finalDestinationOrIgnored):

  • bytecompiler/NodesCodegen.cpp:

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

  • interpreter/CallFrame.h:

(JSC::ExecState::init):
(JSC::ExecState::noCaller):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::dumpRegisters):
(JSC::Interpreter::throwException):
(JSC::Interpreter::privateExecute):

  • interpreter/RegisterFile.h:

(JSC::RegisterFile::):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITCall.cpp:

(JSC::JIT::compileOpCallSetupArgs):
(JSC::JIT::compileOpConstructSetupArgs):
(JSC::JIT::emit_op_call_put_result):
(JSC::JIT::compileOpCallVarargs):
(JSC::JIT::compileOpCallVarargsSlowCase):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
(JSC::JIT::compileOpCallVarargsSetupArgs):

File:
1 edited

Legend:

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

    r59820 r59860  
    14751475    // Emit call.
    14761476    emitOpcode(opcodeID);
    1477     instructions().append(dst->index()); // dst
    14781477    instructions().append(func->index()); // func
    14791478    instructions().append(argv.size()); // argCount
    14801479    instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
     1480    if (dst != ignoredResult()) {
     1481        emitOpcode(op_call_put_result);
     1482        instructions().append(dst->index()); // dst
     1483    }
    14811484
    14821485    if (m_shouldEmitProfileHooks) {
     
    15201523    // Emit call.
    15211524    emitOpcode(op_call_varargs);
    1522     instructions().append(dst->index()); // dst
    15231525    instructions().append(func->index()); // func
    15241526    instructions().append(argCountRegister->index()); // arg count
    15251527    instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
     1528    if (dst != ignoredResult()) {
     1529        emitOpcode(op_call_put_result);
     1530        instructions().append(dst->index()); // dst
     1531    }
    15261532    if (m_shouldEmitProfileHooks) {
    15271533        emitOpcode(op_profile_did_call);
     
    16101616
    16111617    emitOpcode(op_construct);
    1612     instructions().append(dst->index()); // dst
    16131618    instructions().append(func->index()); // func
    16141619    instructions().append(argv.size()); // argCount
     
    16161621    instructions().append(funcProto->index()); // proto
    16171622    instructions().append(argv[0]->index()); // thisRegister
     1623    if (dst != ignoredResult()) {
     1624        emitOpcode(op_call_put_result);
     1625        instructions().append(dst->index()); // dst
     1626    }
    16181627
    16191628    if (m_shouldEmitProfileHooks) {
Note: See TracChangeset for help on using the changeset viewer.