OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 ApiParameterOperand(1), | 638 ApiParameterOperand(1), |
639 argc + kFastApiCallArguments + 1, | 639 argc + kFastApiCallArguments + 1, |
640 return_value_operand, | 640 return_value_operand, |
641 restore_context ? | 641 restore_context ? |
642 &context_restore_operand : NULL); | 642 &context_restore_operand : NULL); |
643 } | 643 } |
644 | 644 |
645 | 645 |
646 class CallInterceptorCompiler BASE_EMBEDDED { | 646 class CallInterceptorCompiler BASE_EMBEDDED { |
647 public: | 647 public: |
648 CallInterceptorCompiler(CallStubCompiler* stub_compiler, | 648 CallInterceptorCompiler(StubCompiler* stub_compiler, |
649 const ParameterCount& arguments, | 649 const ParameterCount& arguments, |
650 Register name, | 650 Register name, |
651 ExtraICState extra_state) | 651 ExtraICState extra_state) |
652 : stub_compiler_(stub_compiler), | 652 : stub_compiler_(stub_compiler), |
653 arguments_(arguments), | 653 arguments_(arguments), |
654 name_(name), | 654 name_(name), |
655 extra_state_(extra_state) {} | 655 extra_state_(extra_state) {} |
656 | 656 |
657 void Compile(MacroAssembler* masm, | 657 void Compile(MacroAssembler* masm, |
658 Handle<JSObject> object, | 658 Handle<JSObject> object, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 // for API (object which is instanceof for the signature). It's | 749 // for API (object which is instanceof for the signature). It's |
750 // safe to omit it here, as if present, it should be fetched | 750 // safe to omit it here, as if present, it should be fetched |
751 // by the previous CheckPrototypes. | 751 // by the previous CheckPrototypes. |
752 ASSERT(depth2 == kInvalidProtoDepth); | 752 ASSERT(depth2 == kInvalidProtoDepth); |
753 } | 753 } |
754 | 754 |
755 // Invoke function. | 755 // Invoke function. |
756 if (can_do_fast_api_call) { | 756 if (can_do_fast_api_call) { |
757 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 757 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
758 } else { | 758 } else { |
759 Handle<JSFunction> fun = optimization.constant_function(); | 759 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
760 stub_compiler_->GenerateJumpFunction(object, fun); | 760 ? CALL_AS_FUNCTION |
| 761 : CALL_AS_METHOD; |
| 762 Handle<JSFunction> function = optimization.constant_function(); |
| 763 ParameterCount expected(function); |
| 764 __ InvokeFunction(function, expected, arguments_, |
| 765 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
761 } | 766 } |
762 | 767 |
763 // Deferred code for fast API call case---clean preallocated space. | 768 // Deferred code for fast API call case---clean preallocated space. |
764 if (can_do_fast_api_call) { | 769 if (can_do_fast_api_call) { |
765 __ bind(&miss_cleanup); | 770 __ bind(&miss_cleanup); |
766 FreeSpaceForFastApiCall(masm, scratch1); | 771 FreeSpaceForFastApiCall(masm, scratch1); |
767 __ jmp(miss_label); | 772 __ jmp(miss_label); |
768 } | 773 } |
769 | 774 |
770 // Invoke a regular function. | 775 // Invoke a regular function. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 | 823 |
819 __ pop(name_); // Restore the name. | 824 __ pop(name_); // Restore the name. |
820 __ pop(receiver); // Restore the holder. | 825 __ pop(receiver); // Restore the holder. |
821 // Leave the internal frame. | 826 // Leave the internal frame. |
822 } | 827 } |
823 | 828 |
824 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); | 829 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); |
825 __ j(not_equal, interceptor_succeeded); | 830 __ j(not_equal, interceptor_succeeded); |
826 } | 831 } |
827 | 832 |
828 CallStubCompiler* stub_compiler_; | 833 StubCompiler* stub_compiler_; |
829 const ParameterCount& arguments_; | 834 const ParameterCount& arguments_; |
830 Register name_; | 835 Register name_; |
831 ExtraICState extra_state_; | 836 ExtraICState extra_state_; |
832 }; | 837 }; |
833 | 838 |
834 | 839 |
835 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 840 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
836 Label* label, | 841 Label* label, |
837 Handle<Name> name) { | 842 Handle<Name> name) { |
838 if (!label->is_unused()) { | 843 if (!label->is_unused()) { |
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1590 | 1595 |
1591 | 1596 |
1592 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1597 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
1593 if (kind_ == Code::KEYED_CALL_IC) { | 1598 if (kind_ == Code::KEYED_CALL_IC) { |
1594 __ cmp(ecx, Immediate(name)); | 1599 __ cmp(ecx, Immediate(name)); |
1595 __ j(not_equal, miss); | 1600 __ j(not_equal, miss); |
1596 } | 1601 } |
1597 } | 1602 } |
1598 | 1603 |
1599 | 1604 |
1600 void CallStubCompiler::GenerateFunctionCheck(Register function, | |
1601 Register scratch, | |
1602 Label* miss) { | |
1603 __ JumpIfSmi(function, miss); | |
1604 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); | |
1605 __ j(not_equal, miss); | |
1606 } | |
1607 | |
1608 | |
1609 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1605 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1610 Handle<Cell> cell, | 1606 Handle<Cell> cell, |
1611 Handle<JSFunction> function, | 1607 Handle<JSFunction> function, |
1612 Label* miss) { | 1608 Label* miss) { |
1613 // Get the value from the cell. | 1609 // Get the value from the cell. |
1614 if (Serializer::enabled()) { | 1610 if (Serializer::enabled()) { |
1615 __ mov(edi, Immediate(cell)); | 1611 __ mov(edi, Immediate(cell)); |
1616 __ mov(edi, FieldOperand(edi, Cell::kValueOffset)); | 1612 __ mov(edi, FieldOperand(edi, Cell::kValueOffset)); |
1617 } else { | 1613 } else { |
1618 __ mov(edi, Operand::ForCell(cell)); | 1614 __ mov(edi, Operand::ForCell(cell)); |
1619 } | 1615 } |
1620 | 1616 |
1621 // Check that the cell contains the same function. | 1617 // Check that the cell contains the same function. |
1622 if (isolate()->heap()->InNewSpace(*function)) { | 1618 if (isolate()->heap()->InNewSpace(*function)) { |
1623 // We can't embed a pointer to a function in new space so we have | 1619 // We can't embed a pointer to a function in new space so we have |
1624 // to verify that the shared function info is unchanged. This has | 1620 // to verify that the shared function info is unchanged. This has |
1625 // the nice side effect that multiple closures based on the same | 1621 // the nice side effect that multiple closures based on the same |
1626 // function can all use this call IC. Before we load through the | 1622 // function can all use this call IC. Before we load through the |
1627 // function, we have to verify that it still is a function. | 1623 // function, we have to verify that it still is a function. |
1628 GenerateFunctionCheck(edi, ebx, miss); | 1624 __ JumpIfSmi(edi, miss); |
| 1625 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1626 __ j(not_equal, miss); |
1629 | 1627 |
1630 // Check the shared function info. Make sure it hasn't changed. | 1628 // Check the shared function info. Make sure it hasn't changed. |
1631 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1629 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
1632 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1630 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
1633 } else { | 1631 } else { |
1634 __ cmp(edi, Immediate(function)); | 1632 __ cmp(edi, Immediate(function)); |
1635 } | 1633 } |
1636 __ j(not_equal, miss); | 1634 __ j(not_equal, miss); |
1637 } | 1635 } |
1638 | 1636 |
(...skipping 12 matching lines...) Expand all Loading... |
1651 PropertyIndex index, | 1649 PropertyIndex index, |
1652 Handle<Name> name) { | 1650 Handle<Name> name) { |
1653 Label miss; | 1651 Label miss; |
1654 | 1652 |
1655 Register reg = HandlerFrontendHeader( | 1653 Register reg = HandlerFrontendHeader( |
1656 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1654 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1657 | 1655 |
1658 GenerateFastPropertyLoad( | 1656 GenerateFastPropertyLoad( |
1659 masm(), edi, reg, index.is_inobject(holder), | 1657 masm(), edi, reg, index.is_inobject(holder), |
1660 index.translate(holder), Representation::Tagged()); | 1658 index.translate(holder), Representation::Tagged()); |
1661 GenerateJumpFunction(object, edi, &miss); | 1659 |
| 1660 // Check that the function really is a function. |
| 1661 __ JumpIfSmi(edi, &miss); |
| 1662 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1663 __ j(not_equal, &miss); |
| 1664 |
| 1665 PatchGlobalProxy(object); |
| 1666 |
| 1667 // Invoke the function. |
| 1668 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1669 ? CALL_AS_FUNCTION |
| 1670 : CALL_AS_METHOD; |
| 1671 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 1672 NullCallWrapper(), call_kind); |
1662 | 1673 |
1663 HandlerFrontendFooter(&miss); | 1674 HandlerFrontendFooter(&miss); |
1664 | 1675 |
1665 // Return the generated code. | 1676 // Return the generated code. |
1666 return GetCode(Code::FAST, name); | 1677 return GetCode(Code::FAST, name); |
1667 } | 1678 } |
1668 | 1679 |
1669 | 1680 |
1670 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1681 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
1671 Handle<Object> object, | 1682 Handle<Object> object, |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2063 | 2074 |
2064 if (index_out_of_range.is_linked()) { | 2075 if (index_out_of_range.is_linked()) { |
2065 __ bind(&index_out_of_range); | 2076 __ bind(&index_out_of_range); |
2066 __ Set(eax, Immediate(factory()->nan_value())); | 2077 __ Set(eax, Immediate(factory()->nan_value())); |
2067 __ ret((argc + 1) * kPointerSize); | 2078 __ ret((argc + 1) * kPointerSize); |
2068 } | 2079 } |
2069 | 2080 |
2070 __ bind(&miss); | 2081 __ bind(&miss); |
2071 // Restore function name in ecx. | 2082 // Restore function name in ecx. |
2072 __ Set(ecx, Immediate(name)); | 2083 __ Set(ecx, Immediate(name)); |
2073 HandlerFrontendFooter(&name_miss); | 2084 __ bind(&name_miss); |
| 2085 GenerateMissBranch(); |
2074 | 2086 |
2075 // Return the generated code. | 2087 // Return the generated code. |
2076 return GetCode(type, name); | 2088 return GetCode(type, name); |
2077 } | 2089 } |
2078 | 2090 |
2079 | 2091 |
2080 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2092 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
2081 Handle<Object> object, | 2093 Handle<Object> object, |
2082 Handle<JSObject> holder, | 2094 Handle<JSObject> holder, |
2083 Handle<Cell> cell, | 2095 Handle<Cell> cell, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2131 | 2143 |
2132 if (index_out_of_range.is_linked()) { | 2144 if (index_out_of_range.is_linked()) { |
2133 __ bind(&index_out_of_range); | 2145 __ bind(&index_out_of_range); |
2134 __ Set(eax, Immediate(factory()->empty_string())); | 2146 __ Set(eax, Immediate(factory()->empty_string())); |
2135 __ ret((argc + 1) * kPointerSize); | 2147 __ ret((argc + 1) * kPointerSize); |
2136 } | 2148 } |
2137 | 2149 |
2138 __ bind(&miss); | 2150 __ bind(&miss); |
2139 // Restore function name in ecx. | 2151 // Restore function name in ecx. |
2140 __ Set(ecx, Immediate(name)); | 2152 __ Set(ecx, Immediate(name)); |
2141 HandlerFrontendFooter(&name_miss); | 2153 __ bind(&name_miss); |
| 2154 GenerateMissBranch(); |
2142 | 2155 |
2143 // Return the generated code. | 2156 // Return the generated code. |
2144 return GetCode(type, name); | 2157 return GetCode(type, name); |
2145 } | 2158 } |
2146 | 2159 |
2147 | 2160 |
2148 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2161 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2149 Handle<Object> object, | 2162 Handle<Object> object, |
2150 Handle<JSObject> holder, | 2163 Handle<JSObject> holder, |
2151 Handle<Cell> cell, | 2164 Handle<Cell> cell, |
(...skipping 28 matching lines...) Expand all Loading... |
2180 // Convert the smi code to uint16. | 2193 // Convert the smi code to uint16. |
2181 __ and_(code, Immediate(Smi::FromInt(0xffff))); | 2194 __ and_(code, Immediate(Smi::FromInt(0xffff))); |
2182 | 2195 |
2183 StringCharFromCodeGenerator generator(code, eax); | 2196 StringCharFromCodeGenerator generator(code, eax); |
2184 generator.GenerateFast(masm()); | 2197 generator.GenerateFast(masm()); |
2185 __ ret(2 * kPointerSize); | 2198 __ ret(2 * kPointerSize); |
2186 | 2199 |
2187 StubRuntimeCallHelper call_helper; | 2200 StubRuntimeCallHelper call_helper; |
2188 generator.GenerateSlow(masm(), call_helper); | 2201 generator.GenerateSlow(masm(), call_helper); |
2189 | 2202 |
| 2203 // Tail call the full function. We do not have to patch the receiver |
| 2204 // because the function makes no use of it. |
2190 __ bind(&slow); | 2205 __ bind(&slow); |
2191 // We do not have to patch the receiver because the function makes no use of | 2206 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2192 // it. | 2207 ? CALL_AS_FUNCTION |
2193 GenerateJumpFunctionIgnoreReceiver(function); | 2208 : CALL_AS_METHOD; |
| 2209 ParameterCount expected(function); |
| 2210 __ InvokeFunction(function, expected, arguments(), |
| 2211 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
2194 | 2212 |
2195 HandlerFrontendFooter(&miss); | 2213 HandlerFrontendFooter(&miss); |
2196 | 2214 |
2197 // Return the generated code. | 2215 // Return the generated code. |
2198 return GetCode(type, name); | 2216 return GetCode(type, name); |
2199 } | 2217 } |
2200 | 2218 |
2201 | 2219 |
2202 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2220 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2203 Handle<Object> object, | 2221 Handle<Object> object, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2290 // Return a new heap number. | 2308 // Return a new heap number. |
2291 __ AllocateHeapNumber(eax, ebx, edx, &slow); | 2309 __ AllocateHeapNumber(eax, ebx, edx, &slow); |
2292 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 2310 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
2293 __ ret(2 * kPointerSize); | 2311 __ ret(2 * kPointerSize); |
2294 | 2312 |
2295 // Return the argument (when it's an already round heap number). | 2313 // Return the argument (when it's an already round heap number). |
2296 __ bind(&already_round); | 2314 __ bind(&already_round); |
2297 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2315 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
2298 __ ret(2 * kPointerSize); | 2316 __ ret(2 * kPointerSize); |
2299 | 2317 |
| 2318 // Tail call the full function. We do not have to patch the receiver |
| 2319 // because the function makes no use of it. |
2300 __ bind(&slow); | 2320 __ bind(&slow); |
2301 // We do not have to patch the receiver because the function makes no use of | 2321 ParameterCount expected(function); |
2302 // it. | 2322 __ InvokeFunction(function, expected, arguments(), |
2303 GenerateJumpFunctionIgnoreReceiver(function); | 2323 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2304 | 2324 |
2305 HandlerFrontendFooter(&miss); | 2325 HandlerFrontendFooter(&miss); |
2306 | 2326 |
2307 // Return the generated code. | 2327 // Return the generated code. |
2308 return GetCode(type, name); | 2328 return GetCode(type, name); |
2309 } | 2329 } |
2310 | 2330 |
2311 | 2331 |
2312 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2332 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2313 Handle<Object> object, | 2333 Handle<Object> object, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2377 // If the argument is negative, clear the sign, and return a new | 2397 // If the argument is negative, clear the sign, and return a new |
2378 // number. | 2398 // number. |
2379 __ bind(&negative_sign); | 2399 __ bind(&negative_sign); |
2380 __ and_(ebx, ~HeapNumber::kSignMask); | 2400 __ and_(ebx, ~HeapNumber::kSignMask); |
2381 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); | 2401 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); |
2382 __ AllocateHeapNumber(eax, edi, edx, &slow); | 2402 __ AllocateHeapNumber(eax, edi, edx, &slow); |
2383 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); | 2403 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); |
2384 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 2404 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); |
2385 __ ret(2 * kPointerSize); | 2405 __ ret(2 * kPointerSize); |
2386 | 2406 |
| 2407 // Tail call the full function. We do not have to patch the receiver |
| 2408 // because the function makes no use of it. |
2387 __ bind(&slow); | 2409 __ bind(&slow); |
2388 // We do not have to patch the receiver because the function makes no use of | 2410 ParameterCount expected(function); |
2389 // it. | 2411 __ InvokeFunction(function, expected, arguments(), |
2390 GenerateJumpFunctionIgnoreReceiver(function); | 2412 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2391 | 2413 |
2392 HandlerFrontendFooter(&miss); | 2414 HandlerFrontendFooter(&miss); |
2393 | 2415 |
2394 // Return the generated code. | 2416 // Return the generated code. |
2395 return GetCode(type, name); | 2417 return GetCode(type, name); |
2396 } | 2418 } |
2397 | 2419 |
2398 | 2420 |
2399 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2421 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2400 const CallOptimization& optimization, | 2422 const CallOptimization& optimization, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2440 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); | 2462 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
2441 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2463 __ mov(Operand(esp, 0 * kPointerSize), eax); |
2442 | 2464 |
2443 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2465 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
2444 // duplicate of return address and will be overwritten. | 2466 // duplicate of return address and will be overwritten. |
2445 GenerateFastApiCall(masm(), optimization, argc); | 2467 GenerateFastApiCall(masm(), optimization, argc); |
2446 | 2468 |
2447 __ bind(&miss); | 2469 __ bind(&miss); |
2448 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2470 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2449 | 2471 |
2450 HandlerFrontendFooter(&miss_before_stack_reserved); | 2472 __ bind(&miss_before_stack_reserved); |
| 2473 GenerateMissBranch(); |
2451 | 2474 |
2452 // Return the generated code. | 2475 // Return the generated code. |
2453 return GetCode(function); | 2476 return GetCode(function); |
2454 } | 2477 } |
2455 | 2478 |
2456 | 2479 |
2457 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2480 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
2458 Label success; | 2481 Label success; |
2459 // Check that the object is a boolean. | 2482 // Check that the object is a boolean. |
2460 __ cmp(object, factory()->true_value()); | 2483 __ cmp(object, factory()->true_value()); |
2461 __ j(equal, &success); | 2484 __ j(equal, &success); |
2462 __ cmp(object, factory()->false_value()); | 2485 __ cmp(object, factory()->false_value()); |
2463 __ j(not_equal, miss); | 2486 __ j(not_equal, miss); |
2464 __ bind(&success); | 2487 __ bind(&success); |
2465 } | 2488 } |
2466 | 2489 |
2467 | 2490 |
2468 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { | 2491 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
2469 if (!object.is_null() && object->IsGlobalObject()) { | 2492 if (object->IsGlobalObject()) { |
2470 const int argc = arguments().immediate(); | 2493 const int argc = arguments().immediate(); |
2471 const int receiver_offset = (argc + 1) * kPointerSize; | 2494 const int receiver_offset = (argc + 1) * kPointerSize; |
2472 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2495 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2473 __ mov(Operand(esp, receiver_offset), edx); | 2496 __ mov(Operand(esp, receiver_offset), edx); |
2474 } | 2497 } |
2475 } | 2498 } |
2476 | 2499 |
2477 | 2500 |
2478 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | 2501 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
2479 Handle<JSObject> holder, | 2502 Handle<JSObject> holder, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2549 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2572 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
2550 reg = CheckPrototypes( | 2573 reg = CheckPrototypes( |
2551 IC::CurrentTypeOf(prototype, isolate()), | 2574 IC::CurrentTypeOf(prototype, isolate()), |
2552 eax, holder, ebx, edx, edi, name, miss); | 2575 eax, holder, ebx, edx, edi, name, miss); |
2553 } | 2576 } |
2554 | 2577 |
2555 return reg; | 2578 return reg; |
2556 } | 2579 } |
2557 | 2580 |
2558 | 2581 |
2559 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | 2582 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
2560 Register function, | 2583 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2561 Label* miss) { | 2584 ? CALL_AS_FUNCTION |
2562 // Check that the function really is a function. | 2585 : CALL_AS_METHOD; |
2563 GenerateFunctionCheck(function, ebx, miss); | 2586 ParameterCount expected(function); |
2564 | 2587 __ InvokeFunction(function, expected, arguments(), |
2565 if (!function.is(edi)) __ mov(edi, function); | 2588 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
2566 PatchGlobalProxy(object); | |
2567 | |
2568 // Invoke the function. | |
2569 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | |
2570 NullCallWrapper(), call_kind()); | |
2571 } | 2589 } |
2572 | 2590 |
2573 | 2591 |
| 2592 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 2593 Handle<Object> object, |
| 2594 Handle<JSObject> holder, |
| 2595 Handle<Name> name, |
| 2596 CheckType check, |
| 2597 Handle<JSFunction> function) { |
| 2598 |
| 2599 if (HasCustomCallGenerator(function)) { |
| 2600 Handle<Code> code = CompileCustomCall(object, holder, |
| 2601 Handle<Cell>::null(), |
| 2602 function, Handle<String>::cast(name), |
| 2603 Code::FAST); |
| 2604 // A null handle means bail out to the regular compiler code below. |
| 2605 if (!code.is_null()) return code; |
| 2606 } |
| 2607 |
| 2608 Label miss; |
| 2609 HandlerFrontendHeader(object, holder, name, check, &miss); |
| 2610 PatchGlobalProxy(object); |
| 2611 CompileHandlerBackend(function); |
| 2612 HandlerFrontendFooter(&miss); |
| 2613 |
| 2614 // Return the generated code. |
| 2615 return GetCode(function); |
| 2616 } |
| 2617 |
| 2618 |
2574 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2619 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2575 Handle<JSObject> holder, | 2620 Handle<JSObject> holder, |
2576 Handle<Name> name) { | 2621 Handle<Name> name) { |
2577 Label miss; | 2622 Label miss; |
2578 | 2623 |
2579 GenerateNameCheck(name, &miss); | 2624 GenerateNameCheck(name, &miss); |
2580 | 2625 |
2581 // Get the number of arguments. | 2626 // Get the number of arguments. |
2582 const int argc = arguments().immediate(); | 2627 const int argc = arguments().immediate(); |
2583 | 2628 |
2584 LookupResult lookup(isolate()); | 2629 LookupResult lookup(isolate()); |
2585 LookupPostInterceptor(holder, name, &lookup); | 2630 LookupPostInterceptor(holder, name, &lookup); |
2586 | 2631 |
2587 // Get the receiver from the stack. | 2632 // Get the receiver from the stack. |
2588 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2633 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2589 | 2634 |
2590 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); | 2635 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); |
2591 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, | 2636 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, |
2592 &miss); | 2637 &miss); |
2593 | 2638 |
2594 // Restore receiver. | 2639 // Restore receiver. |
2595 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2640 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2596 | 2641 |
2597 GenerateJumpFunction(object, eax, &miss); | 2642 // Check that the function really is a function. |
| 2643 __ JumpIfSmi(eax, &miss); |
| 2644 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
| 2645 __ j(not_equal, &miss); |
2598 | 2646 |
2599 HandlerFrontendFooter(&miss); | 2647 // Patch the receiver on the stack with the global proxy if |
| 2648 // necessary. |
| 2649 if (object->IsGlobalObject()) { |
| 2650 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2651 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2652 } |
| 2653 |
| 2654 // Invoke the function. |
| 2655 __ mov(edi, eax); |
| 2656 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2657 ? CALL_AS_FUNCTION |
| 2658 : CALL_AS_METHOD; |
| 2659 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 2660 NullCallWrapper(), call_kind); |
| 2661 |
| 2662 // Handle load cache miss. |
| 2663 __ bind(&miss); |
| 2664 GenerateMissBranch(); |
2600 | 2665 |
2601 // Return the generated code. | 2666 // Return the generated code. |
2602 return GetCode(Code::FAST, name); | 2667 return GetCode(Code::FAST, name); |
2603 } | 2668 } |
2604 | 2669 |
2605 | 2670 |
2606 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2671 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2607 Handle<JSObject> object, | 2672 Handle<JSObject> object, |
2608 Handle<GlobalObject> holder, | 2673 Handle<GlobalObject> holder, |
2609 Handle<PropertyCell> cell, | 2674 Handle<PropertyCell> cell, |
2610 Handle<JSFunction> function, | 2675 Handle<JSFunction> function, |
2611 Handle<Name> name) { | 2676 Handle<Name> name) { |
2612 if (HasCustomCallGenerator(function)) { | 2677 if (HasCustomCallGenerator(function)) { |
2613 Handle<Code> code = CompileCustomCall( | 2678 Handle<Code> code = CompileCustomCall( |
2614 object, holder, cell, function, Handle<String>::cast(name), | 2679 object, holder, cell, function, Handle<String>::cast(name), |
2615 Code::NORMAL); | 2680 Code::NORMAL); |
2616 // A null handle means bail out to the regular compiler code below. | 2681 // A null handle means bail out to the regular compiler code below. |
2617 if (!code.is_null()) return code; | 2682 if (!code.is_null()) return code; |
2618 } | 2683 } |
2619 | 2684 |
2620 Label miss; | 2685 Label miss; |
2621 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2686 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2622 // Potentially loads a closure that matches the shared function info of the | |
2623 // function, rather than function. | |
2624 GenerateLoadFunctionFromCell(cell, function, &miss); | 2687 GenerateLoadFunctionFromCell(cell, function, &miss); |
2625 GenerateJumpFunction(object, edi, function); | 2688 PatchGlobalProxy(object); |
| 2689 |
| 2690 // Set up the context (function already in edi). |
| 2691 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 2692 |
| 2693 // Jump to the cached code (tail call). |
| 2694 Counters* counters = isolate()->counters(); |
| 2695 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2696 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2697 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2698 ? CALL_AS_FUNCTION |
| 2699 : CALL_AS_METHOD; |
| 2700 // We call indirectly through the code field in the function to |
| 2701 // allow recompilation to take effect without changing any of the |
| 2702 // call sites. |
| 2703 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
| 2704 expected, arguments(), JUMP_FUNCTION, |
| 2705 NullCallWrapper(), call_kind); |
2626 | 2706 |
2627 HandlerFrontendFooter(&miss); | 2707 HandlerFrontendFooter(&miss); |
2628 | 2708 |
2629 // Return the generated code. | 2709 // Return the generated code. |
2630 return GetCode(Code::NORMAL, name); | 2710 return GetCode(Code::NORMAL, name); |
2631 } | 2711 } |
2632 | 2712 |
2633 | 2713 |
2634 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2714 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2635 Handle<JSObject> object, | 2715 Handle<JSObject> object, |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2990 // ----------------------------------- | 3070 // ----------------------------------- |
2991 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 3071 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
2992 } | 3072 } |
2993 | 3073 |
2994 | 3074 |
2995 #undef __ | 3075 #undef __ |
2996 | 3076 |
2997 } } // namespace v8::internal | 3077 } } // namespace v8::internal |
2998 | 3078 |
2999 #endif // V8_TARGET_ARCH_IA32 | 3079 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |