Index: third_party/WebKit/JavaScriptCore/VM/CTI.cpp |
=================================================================== |
--- third_party/WebKit/JavaScriptCore/VM/CTI.cpp (revision 5302) |
+++ third_party/WebKit/JavaScriptCore/VM/CTI.cpp (working copy) |
@@ -587,47 +587,58 @@ |
m_jit.movl_rm(X86::ebx, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)), X86::edi); |
} |
-void CTI::compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval) |
+void CTI::compileOpCallSetupArgs(Instruction* instruction) |
{ |
- int firstArg = instruction[4].u.operand; |
- int argCount = instruction[5].u.operand; |
- int registerOffset = instruction[6].u.operand; |
+ int argCount = instruction[3].u.operand; |
+ int registerOffset = instruction[4].u.operand; |
+ // ecx holds func |
emitPutArg(X86::ecx, 0); |
emitPutArgConstant(registerOffset, 4); |
emitPutArgConstant(argCount, 8); |
emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12); |
- if (isConstruct) { |
- emitGetPutArg(instruction[3].u.operand, 16, X86::eax); |
- emitPutArgConstant(firstArg, 20); |
- } else if (isEval) |
- emitGetPutArg(instruction[3].u.operand, 16, X86::eax); |
} |
+void CTI::compileOpCallEvalSetupArgs(Instruction* instruction) |
+{ |
+ int argCount = instruction[3].u.operand; |
+ int registerOffset = instruction[4].u.operand; |
+ |
+ // ecx holds func |
+ emitPutArg(X86::ecx, 0); |
+ emitPutArgConstant(registerOffset, 4); |
+ emitPutArgConstant(argCount, 8); |
+ emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12); |
+} |
+ |
+void CTI::compileOpConstructSetupArgs(Instruction* instruction) |
+{ |
+ int argCount = instruction[3].u.operand; |
+ int registerOffset = instruction[4].u.operand; |
+ int proto = instruction[5].u.operand; |
+ int thisRegister = instruction[6].u.operand; |
+ |
+ // ecx holds func |
+ emitPutArg(X86::ecx, 0); |
+ emitPutArgConstant(registerOffset, 4); |
+ emitPutArgConstant(argCount, 8); |
+ emitGetPutArg(proto, 12, X86::eax); |
+ emitPutArgConstant(thisRegister, 16); |
+ emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 20); |
+} |
+ |
void CTI::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned i, unsigned callLinkInfoIndex) |
{ |
int dst = instruction[1].u.operand; |
int callee = instruction[2].u.operand; |
- int firstArg = instruction[4].u.operand; |
- int argCount = instruction[5].u.operand; |
- int registerOffset = instruction[6].u.operand; |
+ int argCount = instruction[3].u.operand; |
+ int registerOffset = instruction[4].u.operand; |
- // Setup this value as the first argument (does not apply to constructors) |
- if (opcodeID != op_construct) { |
- int thisVal = instruction[3].u.operand; |
- if (thisVal == missingThisObjectMarker()) |
- m_jit.movl_i32m(asInteger(jsNull()), firstArg * sizeof(Register), X86::edi); |
- else { |
- emitGetArg(thisVal, X86::eax); |
- emitPutResult(firstArg); |
- } |
- } |
- |
// Handle eval |
X86Assembler::JmpSrc wasEval; |
if (opcodeID == op_call_eval) { |
emitGetArg(callee, X86::ecx); |
- compileOpCallSetupArgs(instruction, false, true); |
+ compileOpCallEvalSetupArgs(instruction); |
emitCTICall(instruction, i, Machine::cti_op_call_eval); |
m_jit.cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::eax); |
@@ -647,10 +658,13 @@ |
// In the case of OpConstruct, call out to a cti_ function to create the new object. |
if (opcodeID == op_construct) { |
+ int proto = instruction[5].u.operand; |
+ int thisRegister = instruction[6].u.operand; |
+ |
emitPutArg(X86::ecx, 0); |
- emitGetPutArg(instruction[3].u.operand, 16, X86::eax); |
+ emitGetPutArg(proto, 12, X86::eax); |
emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); |
- emitPutResult(firstArg); |
+ emitPutResult(thisRegister); |
emitGetArg(callee, X86::ecx); |
} |
@@ -1285,9 +1299,11 @@ |
i += 3; |
break; |
} |
- case op_call: { |
+ case op_call: |
+ case op_call_eval: |
+ case op_construct: { |
compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); |
- i += 7; |
+ i += (opcodeID == op_construct ? 7 : 5); |
break; |
} |
case op_get_global_var: { |
@@ -1381,11 +1397,6 @@ |
i += 3; |
break; |
} |
- case op_construct: { |
- compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); |
- i += 7; |
- break; |
- } |
case op_construct_verify: { |
emitGetArg(instruction[i + 1].u.operand, X86::eax); |
@@ -1913,11 +1924,6 @@ |
i += 5; |
break; |
} |
- case op_call_eval: { |
- compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); |
- i += 7; |
- break; |
- } |
case op_throw: { |
emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx); |
emitCTICall(instruction + i, i, Machine::cti_op_throw); |
@@ -2767,15 +2773,16 @@ |
case op_construct: { |
int dst = instruction[i + 1].u.operand; |
int callee = instruction[i + 2].u.operand; |
- int firstArg = instruction[i + 4].u.operand; |
- int argCount = instruction[i + 5].u.operand; |
- int registerOffset = instruction[i + 6].u.operand; |
+ int argCount = instruction[i + 3].u.operand; |
+ int registerOffset = instruction[i + 4].u.operand; |
m_jit.link(iter->from, m_jit.label()); |
// The arguments have been set up on the hot path for op_call_eval |
- if (opcodeID != op_call_eval) |
- compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false); |
+ if (opcodeID == op_call) |
+ compileOpCallSetupArgs(instruction + i); |
+ else if (opcodeID == op_construct) |
+ compileOpConstructSetupArgs(instruction + i); |
// Fast check for JS function. |
m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx); |
@@ -2783,10 +2790,10 @@ |
m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVptr), X86::ecx); |
X86Assembler::JmpSrc callLinkFailNotJSFunction = m_jit.emitUnlinkedJne(); |
- // First, in the cale of a construct, allocate the new object. |
+ // First, in the case of a construct, allocate the new object. |
if (opcodeID == op_construct) { |
emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); |
- emitPutResult(firstArg); |
+ emitPutResult(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); |
emitGetArg(callee, X86::ecx); |
} |
@@ -2827,8 +2834,10 @@ |
m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther = m_jit.label(); |
// The arguments have been set up on the hot path for op_call_eval |
- if (opcodeID != op_call_eval) |
- compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false); |
+ if (opcodeID == op_call) |
+ compileOpCallSetupArgs(instruction + i); |
+ else if (opcodeID == op_construct) |
+ compileOpConstructSetupArgs(instruction + i); |
// Check for JSFunctions. |
m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx); |
@@ -2847,10 +2856,10 @@ |
// Next, handle JSFunctions... |
m_jit.link(isJSFunction, m_jit.label()); |
- // First, in the cale of a construct, allocate the new object. |
+ // First, in the case of a construct, allocate the new object. |
if (opcodeID == op_construct) { |
emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); |
- emitPutResult(firstArg); |
+ emitPutResult(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); |
emitGetArg(callee, X86::ecx); |
} |
@@ -2895,7 +2904,7 @@ |
#endif |
++callLinkInfoIndex; |
- i += 7; |
+ i += (opcodeID == op_construct ? 7 : 5); |
break; |
} |
case op_to_jsnumber: { |