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 |