| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 void CTI::compileOpCallInitializeCallFrame(unsigned, unsigned argCount) | 580 void CTI::compileOpCallInitializeCallFrame(unsigned, unsigned argCount) |
| 581 { | 581 { |
| 582 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeC
hain, m_node), X86::ecx, X86::ebx); // newScopeChain | 582 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeC
hain, m_node), X86::ecx, X86::ebx); // newScopeChain |
| 583 | 583 |
| 584 m_jit.movl_i32m(asInteger(noValue()), RegisterFile::OptionalCalleeArguments
* static_cast<int>(sizeof(Register)), X86::edi); | 584 m_jit.movl_i32m(asInteger(noValue()), RegisterFile::OptionalCalleeArguments
* static_cast<int>(sizeof(Register)), X86::edi); |
| 585 m_jit.movl_rm(X86::ecx, RegisterFile::Callee * static_cast<int>(sizeof(Regis
ter)), X86::edi); | 585 m_jit.movl_rm(X86::ecx, RegisterFile::Callee * static_cast<int>(sizeof(Regis
ter)), X86::edi); |
| 586 m_jit.movl_i32m(argCount, RegisterFile::ArgumentCount * static_cast<int>(siz
eof(Register)), X86::edi); | 586 m_jit.movl_i32m(argCount, RegisterFile::ArgumentCount * static_cast<int>(siz
eof(Register)), X86::edi); |
| 587 m_jit.movl_rm(X86::ebx, RegisterFile::ScopeChain * static_cast<int>(sizeof(R
egister)), X86::edi); | 587 m_jit.movl_rm(X86::ebx, RegisterFile::ScopeChain * static_cast<int>(sizeof(R
egister)), X86::edi); |
| 588 } | 588 } |
| 589 | 589 |
| 590 void CTI::compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, boo
l isEval) | 590 void CTI::compileOpCallSetupArgs(Instruction* instruction) |
| 591 { | 591 { |
| 592 int firstArg = instruction[4].u.operand; | 592 int argCount = instruction[3].u.operand; |
| 593 int argCount = instruction[5].u.operand; | 593 int registerOffset = instruction[4].u.operand; |
| 594 int registerOffset = instruction[6].u.operand; | |
| 595 | 594 |
| 595 // ecx holds func |
| 596 emitPutArg(X86::ecx, 0); | 596 emitPutArg(X86::ecx, 0); |
| 597 emitPutArgConstant(registerOffset, 4); | 597 emitPutArgConstant(registerOffset, 4); |
| 598 emitPutArgConstant(argCount, 8); | 598 emitPutArgConstant(argCount, 8); |
| 599 emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12); | 599 emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12); |
| 600 if (isConstruct) { | 600 } |
| 601 emitGetPutArg(instruction[3].u.operand, 16, X86::eax); | 601 |
| 602 emitPutArgConstant(firstArg, 20); | 602 void CTI::compileOpCallEvalSetupArgs(Instruction* instruction) |
| 603 } else if (isEval) | 603 { |
| 604 emitGetPutArg(instruction[3].u.operand, 16, X86::eax); | 604 int argCount = instruction[3].u.operand; |
| 605 int registerOffset = instruction[4].u.operand; |
| 606 |
| 607 // ecx holds func |
| 608 emitPutArg(X86::ecx, 0); |
| 609 emitPutArgConstant(registerOffset, 4); |
| 610 emitPutArgConstant(argCount, 8); |
| 611 emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12); |
| 612 } |
| 613 |
| 614 void CTI::compileOpConstructSetupArgs(Instruction* instruction) |
| 615 { |
| 616 int argCount = instruction[3].u.operand; |
| 617 int registerOffset = instruction[4].u.operand; |
| 618 int proto = instruction[5].u.operand; |
| 619 int thisRegister = instruction[6].u.operand; |
| 620 |
| 621 // ecx holds func |
| 622 emitPutArg(X86::ecx, 0); |
| 623 emitPutArgConstant(registerOffset, 4); |
| 624 emitPutArgConstant(argCount, 8); |
| 625 emitGetPutArg(proto, 12, X86::eax); |
| 626 emitPutArgConstant(thisRegister, 16); |
| 627 emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 20); |
| 605 } | 628 } |
| 606 | 629 |
| 607 void CTI::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned i,
unsigned callLinkInfoIndex) | 630 void CTI::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned i,
unsigned callLinkInfoIndex) |
| 608 { | 631 { |
| 609 int dst = instruction[1].u.operand; | 632 int dst = instruction[1].u.operand; |
| 610 int callee = instruction[2].u.operand; | 633 int callee = instruction[2].u.operand; |
| 611 int firstArg = instruction[4].u.operand; | 634 int argCount = instruction[3].u.operand; |
| 612 int argCount = instruction[5].u.operand; | 635 int registerOffset = instruction[4].u.operand; |
| 613 int registerOffset = instruction[6].u.operand; | |
| 614 | |
| 615 // Setup this value as the first argument (does not apply to constructors) | |
| 616 if (opcodeID != op_construct) { | |
| 617 int thisVal = instruction[3].u.operand; | |
| 618 if (thisVal == missingThisObjectMarker()) | |
| 619 m_jit.movl_i32m(asInteger(jsNull()), firstArg * sizeof(Register), X8
6::edi); | |
| 620 else { | |
| 621 emitGetArg(thisVal, X86::eax); | |
| 622 emitPutResult(firstArg); | |
| 623 } | |
| 624 } | |
| 625 | 636 |
| 626 // Handle eval | 637 // Handle eval |
| 627 X86Assembler::JmpSrc wasEval; | 638 X86Assembler::JmpSrc wasEval; |
| 628 if (opcodeID == op_call_eval) { | 639 if (opcodeID == op_call_eval) { |
| 629 emitGetArg(callee, X86::ecx); | 640 emitGetArg(callee, X86::ecx); |
| 630 compileOpCallSetupArgs(instruction, false, true); | 641 compileOpCallEvalSetupArgs(instruction); |
| 631 | 642 |
| 632 emitCTICall(instruction, i, Machine::cti_op_call_eval); | 643 emitCTICall(instruction, i, Machine::cti_op_call_eval); |
| 633 m_jit.cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::eax); | 644 m_jit.cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::eax); |
| 634 wasEval = m_jit.emitUnlinkedJne(); | 645 wasEval = m_jit.emitUnlinkedJne(); |
| 635 } | 646 } |
| 636 | 647 |
| 637 // This plants a check for a cached JSFunction value, so we can plant a fast
link to the callee. | 648 // This plants a check for a cached JSFunction value, so we can plant a fast
link to the callee. |
| 638 // This deliberately leaves the callee in ecx, used when setting up the stac
k frame below | 649 // This deliberately leaves the callee in ecx, used when setting up the stac
k frame below |
| 639 emitGetArg(callee, X86::ecx); | 650 emitGetArg(callee, X86::ecx); |
| 640 m_jit.cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::ecx); | 651 m_jit.cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::ecx); |
| 641 X86Assembler::JmpDst addressOfLinkedFunctionCheck = m_jit.label(); | 652 X86Assembler::JmpDst addressOfLinkedFunctionCheck = m_jit.label(); |
| 642 m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); | 653 m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); |
| 643 ASSERT(X86Assembler::getDifferenceBetweenLabels(addressOfLinkedFunctionCheck
, m_jit.label()) == repatchOffsetOpCallCall); | 654 ASSERT(X86Assembler::getDifferenceBetweenLabels(addressOfLinkedFunctionCheck
, m_jit.label()) == repatchOffsetOpCallCall); |
| 644 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = address
OfLinkedFunctionCheck; | 655 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = address
OfLinkedFunctionCheck; |
| 645 | 656 |
| 646 // The following is the fast case, only used whan a callee can be linked. | 657 // The following is the fast case, only used whan a callee can be linked. |
| 647 | 658 |
| 648 // In the case of OpConstruct, call out to a cti_ function to create the new
object. | 659 // In the case of OpConstruct, call out to a cti_ function to create the new
object. |
| 649 if (opcodeID == op_construct) { | 660 if (opcodeID == op_construct) { |
| 661 int proto = instruction[5].u.operand; |
| 662 int thisRegister = instruction[6].u.operand; |
| 663 |
| 650 emitPutArg(X86::ecx, 0); | 664 emitPutArg(X86::ecx, 0); |
| 651 emitGetPutArg(instruction[3].u.operand, 16, X86::eax); | 665 emitGetPutArg(proto, 12, X86::eax); |
| 652 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); | 666 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); |
| 653 emitPutResult(firstArg); | 667 emitPutResult(thisRegister); |
| 654 emitGetArg(callee, X86::ecx); | 668 emitGetArg(callee, X86::ecx); |
| 655 } | 669 } |
| 656 | 670 |
| 657 // Fast version of stack frame initialization, directly relative to edi. | 671 // Fast version of stack frame initialization, directly relative to edi. |
| 658 // Note that this omits to set up RegisterFile::CodeBlock, which is set in t
he callee | 672 // Note that this omits to set up RegisterFile::CodeBlock, which is set in t
he callee |
| 659 m_jit.movl_i32m(asInteger(noValue()), (registerOffset + RegisterFile::Option
alCalleeArguments) * static_cast<int>(sizeof(Register)), X86::edi); | 673 m_jit.movl_i32m(asInteger(noValue()), (registerOffset + RegisterFile::Option
alCalleeArguments) * static_cast<int>(sizeof(Register)), X86::edi); |
| 660 m_jit.movl_rm(X86::ecx, (registerOffset + RegisterFile::Callee) * static_cas
t<int>(sizeof(Register)), X86::edi); | 674 m_jit.movl_rm(X86::ecx, (registerOffset + RegisterFile::Callee) * static_cas
t<int>(sizeof(Register)), X86::edi); |
| 661 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeC
hain, m_node), X86::ecx, X86::edx); // newScopeChain | 675 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeC
hain, m_node), X86::ecx, X86::edx); // newScopeChain |
| 662 m_jit.movl_i32m(argCount, (registerOffset + RegisterFile::ArgumentCount) * s
tatic_cast<int>(sizeof(Register)), X86::edi); | 676 m_jit.movl_i32m(argCount, (registerOffset + RegisterFile::ArgumentCount) * s
tatic_cast<int>(sizeof(Register)), X86::edi); |
| 663 m_jit.movl_rm(X86::edi, (registerOffset + RegisterFile::CallerFrame) * stati
c_cast<int>(sizeof(Register)), X86::edi); | 677 m_jit.movl_rm(X86::edi, (registerOffset + RegisterFile::CallerFrame) * stati
c_cast<int>(sizeof(Register)), X86::edi); |
| (...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 break; | 1292 break; |
| 1279 } | 1293 } |
| 1280 case op_new_func: { | 1294 case op_new_func: { |
| 1281 FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.op
erand]).get(); | 1295 FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.op
erand]).get(); |
| 1282 emitPutArgConstant(reinterpret_cast<unsigned>(func), 0); | 1296 emitPutArgConstant(reinterpret_cast<unsigned>(func), 0); |
| 1283 emitCTICall(instruction + i, i, Machine::cti_op_new_func); | 1297 emitCTICall(instruction + i, i, Machine::cti_op_new_func); |
| 1284 emitPutResult(instruction[i + 1].u.operand); | 1298 emitPutResult(instruction[i + 1].u.operand); |
| 1285 i += 3; | 1299 i += 3; |
| 1286 break; | 1300 break; |
| 1287 } | 1301 } |
| 1288 case op_call: { | 1302 case op_call: |
| 1303 case op_call_eval: |
| 1304 case op_construct: { |
| 1289 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); | 1305 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); |
| 1290 i += 7; | 1306 i += (opcodeID == op_construct ? 7 : 5); |
| 1291 break; | 1307 break; |
| 1292 } | 1308 } |
| 1293 case op_get_global_var: { | 1309 case op_get_global_var: { |
| 1294 JSVariableObject* globalObject = static_cast<JSVariableObject*>(inst
ruction[i + 2].u.jsCell); | 1310 JSVariableObject* globalObject = static_cast<JSVariableObject*>(inst
ruction[i + 2].u.jsCell); |
| 1295 m_jit.movl_i32r(asInteger(globalObject), X86::eax); | 1311 m_jit.movl_i32r(asInteger(globalObject), X86::eax); |
| 1296 emitGetVariableObjectRegister(X86::eax, instruction[i + 3].u.operand
, X86::eax); | 1312 emitGetVariableObjectRegister(X86::eax, instruction[i + 3].u.operand
, X86::eax); |
| 1297 emitPutResult(instruction[i + 1].u.operand); | 1313 emitPutResult(instruction[i + 1].u.operand); |
| 1298 i += 4; | 1314 i += 4; |
| 1299 break; | 1315 break; |
| 1300 } | 1316 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1374 break; | 1390 break; |
| 1375 } | 1391 } |
| 1376 case op_resolve: { | 1392 case op_resolve: { |
| 1377 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.
operand]); | 1393 Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.
operand]); |
| 1378 emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0); | 1394 emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0); |
| 1379 emitCTICall(instruction + i, i, Machine::cti_op_resolve); | 1395 emitCTICall(instruction + i, i, Machine::cti_op_resolve); |
| 1380 emitPutResult(instruction[i + 1].u.operand); | 1396 emitPutResult(instruction[i + 1].u.operand); |
| 1381 i += 3; | 1397 i += 3; |
| 1382 break; | 1398 break; |
| 1383 } | 1399 } |
| 1384 case op_construct: { | |
| 1385 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); | |
| 1386 i += 7; | |
| 1387 break; | |
| 1388 } | |
| 1389 case op_construct_verify: { | 1400 case op_construct_verify: { |
| 1390 emitGetArg(instruction[i + 1].u.operand, X86::eax); | 1401 emitGetArg(instruction[i + 1].u.operand, X86::eax); |
| 1391 | 1402 |
| 1392 m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); | 1403 m_jit.testl_i32r(JSImmediate::TagMask, X86::eax); |
| 1393 X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJne(); | 1404 X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJne(); |
| 1394 m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::e
cx); | 1405 m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::e
cx); |
| 1395 m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_typeInfo) +
OBJECT_OFFSET(TypeInfo, m_type), X86::ecx); | 1406 m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_typeInfo) +
OBJECT_OFFSET(TypeInfo, m_type), X86::ecx); |
| 1396 X86Assembler::JmpSrc isObject = m_jit.emitUnlinkedJe(); | 1407 X86Assembler::JmpSrc isObject = m_jit.emitUnlinkedJe(); |
| 1397 | 1408 |
| 1398 m_jit.link(isImmediate, m_jit.label()); | 1409 m_jit.link(isImmediate, m_jit.label()); |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1906 } | 1917 } |
| 1907 case op_bitor: { | 1918 case op_bitor: { |
| 1908 emitGetArg(instruction[i + 2].u.operand, X86::eax); | 1919 emitGetArg(instruction[i + 2].u.operand, X86::eax); |
| 1909 emitGetArg(instruction[i + 3].u.operand, X86::edx); | 1920 emitGetArg(instruction[i + 3].u.operand, X86::edx); |
| 1910 emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i); | 1921 emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i); |
| 1911 m_jit.orl_rr(X86::edx, X86::eax); | 1922 m_jit.orl_rr(X86::edx, X86::eax); |
| 1912 emitPutResult(instruction[i + 1].u.operand); | 1923 emitPutResult(instruction[i + 1].u.operand); |
| 1913 i += 5; | 1924 i += 5; |
| 1914 break; | 1925 break; |
| 1915 } | 1926 } |
| 1916 case op_call_eval: { | |
| 1917 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); | |
| 1918 i += 7; | |
| 1919 break; | |
| 1920 } | |
| 1921 case op_throw: { | 1927 case op_throw: { |
| 1922 emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx); | 1928 emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx); |
| 1923 emitCTICall(instruction + i, i, Machine::cti_op_throw); | 1929 emitCTICall(instruction + i, i, Machine::cti_op_throw); |
| 1924 m_jit.addl_i8r(0x20, X86::esp); | 1930 m_jit.addl_i8r(0x20, X86::esp); |
| 1925 m_jit.popl_r(X86::ebx); | 1931 m_jit.popl_r(X86::ebx); |
| 1926 m_jit.popl_r(X86::edi); | 1932 m_jit.popl_r(X86::edi); |
| 1927 m_jit.popl_r(X86::esi); | 1933 m_jit.popl_r(X86::esi); |
| 1928 m_jit.ret(); | 1934 m_jit.ret(); |
| 1929 i += 2; | 1935 i += 2; |
| 1930 break; | 1936 break; |
| (...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2760 compileBinaryArithOpSlowCase(instruction + i, op_mul, iter, dst,
src1, src2, OperandTypes::fromInt(instruction[i + 4].u.operand), i); | 2766 compileBinaryArithOpSlowCase(instruction + i, op_mul, iter, dst,
src1, src2, OperandTypes::fromInt(instruction[i + 4].u.operand), i); |
| 2761 i += 5; | 2767 i += 5; |
| 2762 break; | 2768 break; |
| 2763 } | 2769 } |
| 2764 | 2770 |
| 2765 case op_call: | 2771 case op_call: |
| 2766 case op_call_eval: | 2772 case op_call_eval: |
| 2767 case op_construct: { | 2773 case op_construct: { |
| 2768 int dst = instruction[i + 1].u.operand; | 2774 int dst = instruction[i + 1].u.operand; |
| 2769 int callee = instruction[i + 2].u.operand; | 2775 int callee = instruction[i + 2].u.operand; |
| 2770 int firstArg = instruction[i + 4].u.operand; | 2776 int argCount = instruction[i + 3].u.operand; |
| 2771 int argCount = instruction[i + 5].u.operand; | 2777 int registerOffset = instruction[i + 4].u.operand; |
| 2772 int registerOffset = instruction[i + 6].u.operand; | |
| 2773 | 2778 |
| 2774 m_jit.link(iter->from, m_jit.label()); | 2779 m_jit.link(iter->from, m_jit.label()); |
| 2775 | 2780 |
| 2776 // The arguments have been set up on the hot path for op_call_eval | 2781 // The arguments have been set up on the hot path for op_call_eval |
| 2777 if (opcodeID != op_call_eval) | 2782 if (opcodeID == op_call) |
| 2778 compileOpCallSetupArgs(instruction + i, (opcodeID == op_construc
t), false); | 2783 compileOpCallSetupArgs(instruction + i); |
| 2784 else if (opcodeID == op_construct) |
| 2785 compileOpConstructSetupArgs(instruction + i); |
| 2779 | 2786 |
| 2780 // Fast check for JS function. | 2787 // Fast check for JS function. |
| 2781 m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx); | 2788 m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx); |
| 2782 X86Assembler::JmpSrc callLinkFailNotObject = m_jit.emitUnlinkedJne()
; | 2789 X86Assembler::JmpSrc callLinkFailNotObject = m_jit.emitUnlinkedJne()
; |
| 2783 m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVp
tr), X86::ecx); | 2790 m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVp
tr), X86::ecx); |
| 2784 X86Assembler::JmpSrc callLinkFailNotJSFunction = m_jit.emitUnlinkedJ
ne(); | 2791 X86Assembler::JmpSrc callLinkFailNotJSFunction = m_jit.emitUnlinkedJ
ne(); |
| 2785 | 2792 |
| 2786 // First, in the cale of a construct, allocate the new object. | 2793 // First, in the case of a construct, allocate the new object. |
| 2787 if (opcodeID == op_construct) { | 2794 if (opcodeID == op_construct) { |
| 2788 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruc
t); | 2795 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruc
t); |
| 2789 emitPutResult(firstArg); | 2796 emitPutResult(registerOffset - RegisterFile::CallFrameHeaderSize
- argCount); |
| 2790 emitGetArg(callee, X86::ecx); | 2797 emitGetArg(callee, X86::ecx); |
| 2791 } | 2798 } |
| 2792 | 2799 |
| 2793 // Load the callee CodeBlock* into eax | 2800 // Load the callee CodeBlock* into eax |
| 2794 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_body), X86::ecx, X86::eax)
; | 2801 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_body), X86::ecx, X86::eax)
; |
| 2795 m_jit.movl_mr(OBJECT_OFFSET(FunctionBodyNode, m_code), X86::eax, X86
::eax); | 2802 m_jit.movl_mr(OBJECT_OFFSET(FunctionBodyNode, m_code), X86::eax, X86
::eax); |
| 2796 m_jit.testl_rr(X86::eax, X86::eax); | 2803 m_jit.testl_rr(X86::eax, X86::eax); |
| 2797 X86Assembler::JmpSrc hasCodeBlockForLink = m_jit.emitUnlinkedJne(); | 2804 X86Assembler::JmpSrc hasCodeBlockForLink = m_jit.emitUnlinkedJne(); |
| 2798 emitCTICall(instruction + i, i, Machine::cti_op_call_JSFunction); | 2805 emitCTICall(instruction + i, i, Machine::cti_op_call_JSFunction); |
| 2799 emitGetArg(callee, X86::ecx); | 2806 emitGetArg(callee, X86::ecx); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2820 emitPutArgConstant(reinterpret_cast<unsigned>(info), 4); | 2827 emitPutArgConstant(reinterpret_cast<unsigned>(info), 4); |
| 2821 m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLoca
tion = | 2828 m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLoca
tion = |
| 2822 emitCTICall(instruction + i, i, Machine::cti_vm_lazyLinkCall); | 2829 emitCTICall(instruction + i, i, Machine::cti_vm_lazyLinkCall); |
| 2823 emitNakedCall(i, X86::eax); | 2830 emitNakedCall(i, X86::eax); |
| 2824 X86Assembler::JmpSrc storeResultForFirstRun = m_jit.emitUnlinkedJmp(
); | 2831 X86Assembler::JmpSrc storeResultForFirstRun = m_jit.emitUnlinkedJmp(
); |
| 2825 | 2832 |
| 2826 // This is the address for the cold path *after* the first run (whic
h tries to link the call). | 2833 // This is the address for the cold path *after* the first run (whic
h tries to link the call). |
| 2827 m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther
= m_jit.label(); | 2834 m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther
= m_jit.label(); |
| 2828 | 2835 |
| 2829 // The arguments have been set up on the hot path for op_call_eval | 2836 // The arguments have been set up on the hot path for op_call_eval |
| 2830 if (opcodeID != op_call_eval) | 2837 if (opcodeID == op_call) |
| 2831 compileOpCallSetupArgs(instruction + i, (opcodeID == op_construc
t), false); | 2838 compileOpCallSetupArgs(instruction + i); |
| 2839 else if (opcodeID == op_construct) |
| 2840 compileOpConstructSetupArgs(instruction + i); |
| 2832 | 2841 |
| 2833 // Check for JSFunctions. | 2842 // Check for JSFunctions. |
| 2834 m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx); | 2843 m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx); |
| 2835 X86Assembler::JmpSrc isNotObject = m_jit.emitUnlinkedJne(); | 2844 X86Assembler::JmpSrc isNotObject = m_jit.emitUnlinkedJne(); |
| 2836 m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVp
tr), X86::ecx); | 2845 m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVp
tr), X86::ecx); |
| 2837 X86Assembler::JmpSrc isJSFunction = m_jit.emitUnlinkedJe(); | 2846 X86Assembler::JmpSrc isJSFunction = m_jit.emitUnlinkedJe(); |
| 2838 | 2847 |
| 2839 // This handles host functions | 2848 // This handles host functions |
| 2840 X86Assembler::JmpDst notJSFunctionlabel = m_jit.label(); | 2849 X86Assembler::JmpDst notJSFunctionlabel = m_jit.label(); |
| 2841 m_jit.link(isNotObject, notJSFunctionlabel); | 2850 m_jit.link(isNotObject, notJSFunctionlabel); |
| 2842 m_jit.link(callLinkFailNotObject, notJSFunctionlabel); | 2851 m_jit.link(callLinkFailNotObject, notJSFunctionlabel); |
| 2843 m_jit.link(callLinkFailNotJSFunction, notJSFunctionlabel); | 2852 m_jit.link(callLinkFailNotJSFunction, notJSFunctionlabel); |
| 2844 emitCTICall(instruction + i, i, ((opcodeID == op_construct) ? Machin
e::cti_op_construct_NotJSConstruct : Machine::cti_op_call_NotJSFunction)); | 2853 emitCTICall(instruction + i, i, ((opcodeID == op_construct) ? Machin
e::cti_op_construct_NotJSConstruct : Machine::cti_op_call_NotJSFunction)); |
| 2845 X86Assembler::JmpSrc wasNotJSFunction = m_jit.emitUnlinkedJmp(); | 2854 X86Assembler::JmpSrc wasNotJSFunction = m_jit.emitUnlinkedJmp(); |
| 2846 | 2855 |
| 2847 // Next, handle JSFunctions... | 2856 // Next, handle JSFunctions... |
| 2848 m_jit.link(isJSFunction, m_jit.label()); | 2857 m_jit.link(isJSFunction, m_jit.label()); |
| 2849 | 2858 |
| 2850 // First, in the cale of a construct, allocate the new object. | 2859 // First, in the case of a construct, allocate the new object. |
| 2851 if (opcodeID == op_construct) { | 2860 if (opcodeID == op_construct) { |
| 2852 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruc
t); | 2861 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruc
t); |
| 2853 emitPutResult(firstArg); | 2862 emitPutResult(registerOffset - RegisterFile::CallFrameHeaderSize
- argCount); |
| 2854 emitGetArg(callee, X86::ecx); | 2863 emitGetArg(callee, X86::ecx); |
| 2855 } | 2864 } |
| 2856 | 2865 |
| 2857 // Load the callee CodeBlock* into eax | 2866 // Load the callee CodeBlock* into eax |
| 2858 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_body), X86::ecx, X86::eax)
; | 2867 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_body), X86::ecx, X86::eax)
; |
| 2859 m_jit.movl_mr(OBJECT_OFFSET(FunctionBodyNode, m_code), X86::eax, X86
::eax); | 2868 m_jit.movl_mr(OBJECT_OFFSET(FunctionBodyNode, m_code), X86::eax, X86
::eax); |
| 2860 m_jit.testl_rr(X86::eax, X86::eax); | 2869 m_jit.testl_rr(X86::eax, X86::eax); |
| 2861 X86Assembler::JmpSrc hasCodeBlock = m_jit.emitUnlinkedJne(); | 2870 X86Assembler::JmpSrc hasCodeBlock = m_jit.emitUnlinkedJne(); |
| 2862 emitCTICall(instruction + i, i, Machine::cti_op_call_JSFunction); | 2871 emitCTICall(instruction + i, i, Machine::cti_op_call_JSFunction); |
| 2863 emitGetArg(callee, X86::ecx); | 2872 emitGetArg(callee, X86::ecx); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2888 X86Assembler::JmpDst storeResult = m_jit.label(); | 2897 X86Assembler::JmpDst storeResult = m_jit.label(); |
| 2889 m_jit.link(wasNotJSFunction, storeResult); | 2898 m_jit.link(wasNotJSFunction, storeResult); |
| 2890 m_jit.link(storeResultForFirstRun, storeResult); | 2899 m_jit.link(storeResultForFirstRun, storeResult); |
| 2891 emitPutResult(dst); | 2900 emitPutResult(dst); |
| 2892 | 2901 |
| 2893 #if ENABLE(CODEBLOCK_SAMPLING) | 2902 #if ENABLE(CODEBLOCK_SAMPLING) |
| 2894 m_jit.movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_machine->
sampler()->codeBlockSlot()); | 2903 m_jit.movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_machine->
sampler()->codeBlockSlot()); |
| 2895 #endif | 2904 #endif |
| 2896 ++callLinkInfoIndex; | 2905 ++callLinkInfoIndex; |
| 2897 | 2906 |
| 2898 i += 7; | 2907 i += (opcodeID == op_construct ? 7 : 5); |
| 2899 break; | 2908 break; |
| 2900 } | 2909 } |
| 2901 case op_to_jsnumber: { | 2910 case op_to_jsnumber: { |
| 2902 m_jit.link(iter->from, m_jit.label()); | 2911 m_jit.link(iter->from, m_jit.label()); |
| 2903 m_jit.link(iter->from, m_jit.label()); | 2912 m_jit.link(iter->from, m_jit.label()); |
| 2904 | 2913 |
| 2905 emitPutArg(X86::eax, 0); | 2914 emitPutArg(X86::eax, 0); |
| 2906 emitCTICall(instruction + i, i, Machine::cti_op_to_jsnumber); | 2915 emitCTICall(instruction + i, i, Machine::cti_op_to_jsnumber); |
| 2907 | 2916 |
| 2908 emitPutResult(instruction[i + 1].u.operand); | 2917 emitPutResult(instruction[i + 1].u.operand); |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3561 void* code = jit.copy(); | 3570 void* code = jit.copy(); |
| 3562 ASSERT(code); | 3571 ASSERT(code); |
| 3563 return code; | 3572 return code; |
| 3564 } | 3573 } |
| 3565 | 3574 |
| 3566 #endif // ENABLE(WREC) | 3575 #endif // ENABLE(WREC) |
| 3567 | 3576 |
| 3568 } // namespace JSC | 3577 } // namespace JSC |
| 3569 | 3578 |
| 3570 #endif // ENABLE(CTI) | 3579 #endif // ENABLE(CTI) |
| OLD | NEW |