| 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: {
|
|
|