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(StubCompiler* stub_compiler, | 648 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
649 const ParameterCount& arguments, | 649 const ParameterCount& arguments, |
650 Register name, | 650 Register name, |
651 Code::ExtraICState extra_state) | 651 Code::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 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 759 Handle<JSFunction> fun = optimization.constant_function(); |
760 ? CALL_AS_FUNCTION | 760 stub_compiler_->GenerateCallFunction(object, fun); |
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); | |
766 } | 761 } |
767 | 762 |
768 // Deferred code for fast API call case---clean preallocated space. | 763 // Deferred code for fast API call case---clean preallocated space. |
769 if (can_do_fast_api_call) { | 764 if (can_do_fast_api_call) { |
770 __ bind(&miss_cleanup); | 765 __ bind(&miss_cleanup); |
771 FreeSpaceForFastApiCall(masm, scratch1); | 766 FreeSpaceForFastApiCall(masm, scratch1); |
772 __ jmp(miss_label); | 767 __ jmp(miss_label); |
773 } | 768 } |
774 | 769 |
775 // Invoke a regular function. | 770 // Invoke a regular function. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 | 823 |
829 __ pop(name_); // Restore the name. | 824 __ pop(name_); // Restore the name. |
830 __ pop(receiver); // Restore the holder. | 825 __ pop(receiver); // Restore the holder. |
831 // Leave the internal frame. | 826 // Leave the internal frame. |
832 } | 827 } |
833 | 828 |
834 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); | 829 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); |
835 __ j(not_equal, interceptor_succeeded); | 830 __ j(not_equal, interceptor_succeeded); |
836 } | 831 } |
837 | 832 |
838 StubCompiler* stub_compiler_; | 833 CallStubCompiler* stub_compiler_; |
839 const ParameterCount& arguments_; | 834 const ParameterCount& arguments_; |
840 Register name_; | 835 Register name_; |
841 Code::ExtraICState extra_state_; | 836 Code::ExtraICState extra_state_; |
842 }; | 837 }; |
843 | 838 |
844 | 839 |
845 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 840 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
846 Label* label, | 841 Label* label, |
847 Handle<Name> name) { | 842 Handle<Name> name) { |
848 if (!label->is_unused()) { | 843 if (!label->is_unused()) { |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1602 | 1597 |
1603 | 1598 |
1604 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1599 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
1605 if (kind_ == Code::KEYED_CALL_IC) { | 1600 if (kind_ == Code::KEYED_CALL_IC) { |
1606 __ cmp(ecx, Immediate(name)); | 1601 __ cmp(ecx, Immediate(name)); |
1607 __ j(not_equal, miss); | 1602 __ j(not_equal, miss); |
1608 } | 1603 } |
1609 } | 1604 } |
1610 | 1605 |
1611 | 1606 |
| 1607 void CallStubCompiler::GenerateFunctionCheck(Register function, |
| 1608 Register scratch, |
| 1609 Label* miss) { |
| 1610 __ JumpIfSmi(function, miss); |
| 1611 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
| 1612 __ j(not_equal, miss); |
| 1613 } |
| 1614 |
| 1615 |
1612 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1616 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1613 Handle<Cell> cell, | 1617 Handle<Cell> cell, |
1614 Handle<JSFunction> function, | 1618 Handle<JSFunction> function, |
1615 Label* miss) { | 1619 Label* miss) { |
1616 // Get the value from the cell. | 1620 // Get the value from the cell. |
1617 if (Serializer::enabled()) { | 1621 if (Serializer::enabled()) { |
1618 __ mov(edi, Immediate(cell)); | 1622 __ mov(edi, Immediate(cell)); |
1619 __ mov(edi, FieldOperand(edi, Cell::kValueOffset)); | 1623 __ mov(edi, FieldOperand(edi, Cell::kValueOffset)); |
1620 } else { | 1624 } else { |
1621 __ mov(edi, Operand::ForCell(cell)); | 1625 __ mov(edi, Operand::ForCell(cell)); |
1622 } | 1626 } |
1623 | 1627 |
1624 // Check that the cell contains the same function. | 1628 // Check that the cell contains the same function. |
1625 if (isolate()->heap()->InNewSpace(*function)) { | 1629 if (isolate()->heap()->InNewSpace(*function)) { |
1626 // We can't embed a pointer to a function in new space so we have | 1630 // We can't embed a pointer to a function in new space so we have |
1627 // to verify that the shared function info is unchanged. This has | 1631 // to verify that the shared function info is unchanged. This has |
1628 // the nice side effect that multiple closures based on the same | 1632 // the nice side effect that multiple closures based on the same |
1629 // function can all use this call IC. Before we load through the | 1633 // function can all use this call IC. Before we load through the |
1630 // function, we have to verify that it still is a function. | 1634 // function, we have to verify that it still is a function. |
1631 __ JumpIfSmi(edi, miss); | 1635 GenerateFunctionCheck(edi, ebx, miss); |
1632 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | |
1633 __ j(not_equal, miss); | |
1634 | 1636 |
1635 // Check the shared function info. Make sure it hasn't changed. | 1637 // Check the shared function info. Make sure it hasn't changed. |
1636 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1638 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
1637 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1639 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
1638 } else { | 1640 } else { |
1639 __ cmp(edi, Immediate(function)); | 1641 __ cmp(edi, Immediate(function)); |
1640 } | 1642 } |
1641 __ j(not_equal, miss); | 1643 __ j(not_equal, miss); |
1642 } | 1644 } |
1643 | 1645 |
(...skipping 12 matching lines...) Expand all Loading... |
1656 PropertyIndex index, | 1658 PropertyIndex index, |
1657 Handle<Name> name) { | 1659 Handle<Name> name) { |
1658 Label miss; | 1660 Label miss; |
1659 | 1661 |
1660 Register reg = HandlerFrontendHeader( | 1662 Register reg = HandlerFrontendHeader( |
1661 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1663 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1662 | 1664 |
1663 GenerateFastPropertyLoad( | 1665 GenerateFastPropertyLoad( |
1664 masm(), edi, reg, index.is_inobject(holder), | 1666 masm(), edi, reg, index.is_inobject(holder), |
1665 index.translate(holder), Representation::Tagged()); | 1667 index.translate(holder), Representation::Tagged()); |
1666 | 1668 GenerateCallFunction(object, edi, &miss); |
1667 // Check that the function really is a function. | |
1668 __ JumpIfSmi(edi, &miss); | |
1669 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | |
1670 __ j(not_equal, &miss); | |
1671 | |
1672 PatchGlobalProxy(object); | |
1673 | |
1674 // Invoke the function. | |
1675 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
1676 ? CALL_AS_FUNCTION | |
1677 : CALL_AS_METHOD; | |
1678 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | |
1679 NullCallWrapper(), call_kind); | |
1680 | 1669 |
1681 HandlerFrontendFooter(&miss); | 1670 HandlerFrontendFooter(&miss); |
1682 | 1671 |
1683 // Return the generated code. | 1672 // Return the generated code. |
1684 return GetCode(Code::FAST, name); | 1673 return GetCode(Code::FAST, name); |
1685 } | 1674 } |
1686 | 1675 |
1687 | 1676 |
1688 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1677 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
1689 Handle<Object> object, | 1678 Handle<Object> object, |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2081 | 2070 |
2082 if (index_out_of_range.is_linked()) { | 2071 if (index_out_of_range.is_linked()) { |
2083 __ bind(&index_out_of_range); | 2072 __ bind(&index_out_of_range); |
2084 __ Set(eax, Immediate(factory()->nan_value())); | 2073 __ Set(eax, Immediate(factory()->nan_value())); |
2085 __ ret((argc + 1) * kPointerSize); | 2074 __ ret((argc + 1) * kPointerSize); |
2086 } | 2075 } |
2087 | 2076 |
2088 __ bind(&miss); | 2077 __ bind(&miss); |
2089 // Restore function name in ecx. | 2078 // Restore function name in ecx. |
2090 __ Set(ecx, Immediate(name)); | 2079 __ Set(ecx, Immediate(name)); |
2091 __ bind(&name_miss); | 2080 HandlerFrontendFooter(&name_miss); |
2092 GenerateMissBranch(); | |
2093 | 2081 |
2094 // Return the generated code. | 2082 // Return the generated code. |
2095 return GetCode(type, name); | 2083 return GetCode(type, name); |
2096 } | 2084 } |
2097 | 2085 |
2098 | 2086 |
2099 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2087 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
2100 Handle<Object> object, | 2088 Handle<Object> object, |
2101 Handle<JSObject> holder, | 2089 Handle<JSObject> holder, |
2102 Handle<Cell> cell, | 2090 Handle<Cell> cell, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2150 | 2138 |
2151 if (index_out_of_range.is_linked()) { | 2139 if (index_out_of_range.is_linked()) { |
2152 __ bind(&index_out_of_range); | 2140 __ bind(&index_out_of_range); |
2153 __ Set(eax, Immediate(factory()->empty_string())); | 2141 __ Set(eax, Immediate(factory()->empty_string())); |
2154 __ ret((argc + 1) * kPointerSize); | 2142 __ ret((argc + 1) * kPointerSize); |
2155 } | 2143 } |
2156 | 2144 |
2157 __ bind(&miss); | 2145 __ bind(&miss); |
2158 // Restore function name in ecx. | 2146 // Restore function name in ecx. |
2159 __ Set(ecx, Immediate(name)); | 2147 __ Set(ecx, Immediate(name)); |
2160 __ bind(&name_miss); | 2148 HandlerFrontendFooter(&name_miss); |
2161 GenerateMissBranch(); | |
2162 | 2149 |
2163 // Return the generated code. | 2150 // Return the generated code. |
2164 return GetCode(type, name); | 2151 return GetCode(type, name); |
2165 } | 2152 } |
2166 | 2153 |
2167 | 2154 |
2168 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2155 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2169 Handle<Object> object, | 2156 Handle<Object> object, |
2170 Handle<JSObject> holder, | 2157 Handle<JSObject> holder, |
2171 Handle<Cell> cell, | 2158 Handle<Cell> cell, |
(...skipping 28 matching lines...) Expand all Loading... |
2200 // Convert the smi code to uint16. | 2187 // Convert the smi code to uint16. |
2201 __ and_(code, Immediate(Smi::FromInt(0xffff))); | 2188 __ and_(code, Immediate(Smi::FromInt(0xffff))); |
2202 | 2189 |
2203 StringCharFromCodeGenerator generator(code, eax); | 2190 StringCharFromCodeGenerator generator(code, eax); |
2204 generator.GenerateFast(masm()); | 2191 generator.GenerateFast(masm()); |
2205 __ ret(2 * kPointerSize); | 2192 __ ret(2 * kPointerSize); |
2206 | 2193 |
2207 StubRuntimeCallHelper call_helper; | 2194 StubRuntimeCallHelper call_helper; |
2208 generator.GenerateSlow(masm(), call_helper); | 2195 generator.GenerateSlow(masm(), call_helper); |
2209 | 2196 |
2210 // Tail call the full function. We do not have to patch the receiver | |
2211 // because the function makes no use of it. | |
2212 __ bind(&slow); | 2197 __ bind(&slow); |
2213 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2198 // We do not have to patch the receiver because the function makes no use of |
2214 ? CALL_AS_FUNCTION | 2199 // it. |
2215 : CALL_AS_METHOD; | 2200 GenerateCallFunction(Handle<Object>::null(), function); |
2216 ParameterCount expected(function); | |
2217 __ InvokeFunction(function, expected, arguments(), | |
2218 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
2219 | 2201 |
2220 HandlerFrontendFooter(&miss); | 2202 HandlerFrontendFooter(&miss); |
2221 | 2203 |
2222 // Return the generated code. | 2204 // Return the generated code. |
2223 return GetCode(type, name); | 2205 return GetCode(type, name); |
2224 } | 2206 } |
2225 | 2207 |
2226 | 2208 |
2227 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2209 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2228 Handle<Object> object, | 2210 Handle<Object> object, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2315 // Return a new heap number. | 2297 // Return a new heap number. |
2316 __ AllocateHeapNumber(eax, ebx, edx, &slow); | 2298 __ AllocateHeapNumber(eax, ebx, edx, &slow); |
2317 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 2299 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
2318 __ ret(2 * kPointerSize); | 2300 __ ret(2 * kPointerSize); |
2319 | 2301 |
2320 // Return the argument (when it's an already round heap number). | 2302 // Return the argument (when it's an already round heap number). |
2321 __ bind(&already_round); | 2303 __ bind(&already_round); |
2322 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2304 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
2323 __ ret(2 * kPointerSize); | 2305 __ ret(2 * kPointerSize); |
2324 | 2306 |
2325 // Tail call the full function. We do not have to patch the receiver | |
2326 // because the function makes no use of it. | |
2327 __ bind(&slow); | 2307 __ bind(&slow); |
2328 ParameterCount expected(function); | 2308 // We do not have to patch the receiver because the function makes no use of |
2329 __ InvokeFunction(function, expected, arguments(), | 2309 // it. |
2330 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2310 GenerateCallFunction(Handle<Object>::null(), function); |
2331 | 2311 |
2332 HandlerFrontendFooter(&miss); | 2312 HandlerFrontendFooter(&miss); |
2333 | 2313 |
2334 // Return the generated code. | 2314 // Return the generated code. |
2335 return GetCode(type, name); | 2315 return GetCode(type, name); |
2336 } | 2316 } |
2337 | 2317 |
2338 | 2318 |
2339 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2319 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2340 Handle<Object> object, | 2320 Handle<Object> object, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2404 // If the argument is negative, clear the sign, and return a new | 2384 // If the argument is negative, clear the sign, and return a new |
2405 // number. | 2385 // number. |
2406 __ bind(&negative_sign); | 2386 __ bind(&negative_sign); |
2407 __ and_(ebx, ~HeapNumber::kSignMask); | 2387 __ and_(ebx, ~HeapNumber::kSignMask); |
2408 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); | 2388 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); |
2409 __ AllocateHeapNumber(eax, edi, edx, &slow); | 2389 __ AllocateHeapNumber(eax, edi, edx, &slow); |
2410 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); | 2390 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); |
2411 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 2391 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); |
2412 __ ret(2 * kPointerSize); | 2392 __ ret(2 * kPointerSize); |
2413 | 2393 |
2414 // Tail call the full function. We do not have to patch the receiver | |
2415 // because the function makes no use of it. | |
2416 __ bind(&slow); | 2394 __ bind(&slow); |
2417 ParameterCount expected(function); | 2395 // We do not have to patch the receiver because the function makes no use of |
2418 __ InvokeFunction(function, expected, arguments(), | 2396 // it. |
2419 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2397 GenerateCallFunction(Handle<Object>::null(), function); |
2420 | 2398 |
2421 HandlerFrontendFooter(&miss); | 2399 HandlerFrontendFooter(&miss); |
2422 | 2400 |
2423 // Return the generated code. | 2401 // Return the generated code. |
2424 return GetCode(type, name); | 2402 return GetCode(type, name); |
2425 } | 2403 } |
2426 | 2404 |
2427 | 2405 |
2428 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2406 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2429 const CallOptimization& optimization, | 2407 const CallOptimization& optimization, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2469 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); | 2447 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
2470 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2448 __ mov(Operand(esp, 0 * kPointerSize), eax); |
2471 | 2449 |
2472 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2450 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
2473 // duplicate of return address and will be overwritten. | 2451 // duplicate of return address and will be overwritten. |
2474 GenerateFastApiCall(masm(), optimization, argc); | 2452 GenerateFastApiCall(masm(), optimization, argc); |
2475 | 2453 |
2476 __ bind(&miss); | 2454 __ bind(&miss); |
2477 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2455 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2478 | 2456 |
2479 __ bind(&miss_before_stack_reserved); | 2457 HandlerFrontendFooter(&miss_before_stack_reserved); |
2480 GenerateMissBranch(); | |
2481 | 2458 |
2482 // Return the generated code. | 2459 // Return the generated code. |
2483 return GetCode(function); | 2460 return GetCode(function); |
2484 } | 2461 } |
2485 | 2462 |
2486 | 2463 |
2487 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2464 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
2488 Label success; | 2465 Label success; |
2489 // Check that the object is a boolean. | 2466 // Check that the object is a boolean. |
2490 __ cmp(object, factory()->true_value()); | 2467 __ cmp(object, factory()->true_value()); |
2491 __ j(equal, &success); | 2468 __ j(equal, &success); |
2492 __ cmp(object, factory()->false_value()); | 2469 __ cmp(object, factory()->false_value()); |
2493 __ j(not_equal, miss); | 2470 __ j(not_equal, miss); |
2494 __ bind(&success); | 2471 __ bind(&success); |
2495 } | 2472 } |
2496 | 2473 |
2497 | 2474 |
2498 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { | 2475 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
2499 if (object->IsGlobalObject()) { | 2476 if (!object.is_null() && object->IsGlobalObject()) { |
2500 const int argc = arguments().immediate(); | 2477 const int argc = arguments().immediate(); |
2501 const int receiver_offset = (argc + 1) * kPointerSize; | 2478 const int receiver_offset = (argc + 1) * kPointerSize; |
2502 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2479 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2503 __ mov(Operand(esp, receiver_offset), edx); | 2480 __ mov(Operand(esp, receiver_offset), edx); |
2504 } | 2481 } |
2505 } | 2482 } |
2506 | 2483 |
2507 | 2484 |
2508 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | 2485 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
2509 Handle<JSObject> holder, | 2486 Handle<JSObject> holder, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2579 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2556 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
2580 reg = CheckPrototypes( | 2557 reg = CheckPrototypes( |
2581 IC::CurrentTypeOf(prototype, isolate()), | 2558 IC::CurrentTypeOf(prototype, isolate()), |
2582 eax, holder, ebx, edx, edi, name, miss); | 2559 eax, holder, ebx, edx, edi, name, miss); |
2583 } | 2560 } |
2584 | 2561 |
2585 return reg; | 2562 return reg; |
2586 } | 2563 } |
2587 | 2564 |
2588 | 2565 |
2589 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2566 void CallStubCompiler::GenerateCallFunction(Handle<Object> object, |
2590 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2567 Register function, |
2591 ? CALL_AS_FUNCTION | 2568 Label* miss) { |
2592 : CALL_AS_METHOD; | 2569 // Check that the function really is a function. |
2593 ParameterCount expected(function); | 2570 GenerateFunctionCheck(function, ebx, miss); |
2594 __ InvokeFunction(function, expected, arguments(), | 2571 |
2595 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2572 if (!function.is(edi)) __ mov(edi, function); |
| 2573 PatchGlobalProxy(object); |
| 2574 |
| 2575 // Invoke the function. |
| 2576 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
| 2577 NullCallWrapper(), call_kind()); |
2596 } | 2578 } |
2597 | 2579 |
2598 | 2580 |
2599 Handle<Code> CallStubCompiler::CompileCallConstant( | |
2600 Handle<Object> object, | |
2601 Handle<JSObject> holder, | |
2602 Handle<Name> name, | |
2603 CheckType check, | |
2604 Handle<JSFunction> function) { | |
2605 | |
2606 if (HasCustomCallGenerator(function)) { | |
2607 Handle<Code> code = CompileCustomCall(object, holder, | |
2608 Handle<Cell>::null(), | |
2609 function, Handle<String>::cast(name), | |
2610 Code::FAST); | |
2611 // A null handle means bail out to the regular compiler code below. | |
2612 if (!code.is_null()) return code; | |
2613 } | |
2614 | |
2615 Label miss; | |
2616 HandlerFrontendHeader(object, holder, name, check, &miss); | |
2617 PatchGlobalProxy(object); | |
2618 CompileHandlerBackend(function); | |
2619 HandlerFrontendFooter(&miss); | |
2620 | |
2621 // Return the generated code. | |
2622 return GetCode(function); | |
2623 } | |
2624 | |
2625 | |
2626 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2581 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2627 Handle<JSObject> holder, | 2582 Handle<JSObject> holder, |
2628 Handle<Name> name) { | 2583 Handle<Name> name) { |
2629 Label miss; | 2584 Label miss; |
2630 | 2585 |
2631 GenerateNameCheck(name, &miss); | 2586 GenerateNameCheck(name, &miss); |
2632 | 2587 |
2633 // Get the number of arguments. | 2588 // Get the number of arguments. |
2634 const int argc = arguments().immediate(); | 2589 const int argc = arguments().immediate(); |
2635 | 2590 |
2636 LookupResult lookup(isolate()); | 2591 LookupResult lookup(isolate()); |
2637 LookupPostInterceptor(holder, name, &lookup); | 2592 LookupPostInterceptor(holder, name, &lookup); |
2638 | 2593 |
2639 // Get the receiver from the stack. | 2594 // Get the receiver from the stack. |
2640 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2595 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2641 | 2596 |
2642 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); | 2597 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); |
2643 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, | 2598 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, |
2644 &miss); | 2599 &miss); |
2645 | 2600 |
2646 // Restore receiver. | 2601 // Restore receiver. |
2647 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2602 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2648 | 2603 |
2649 // Check that the function really is a function. | 2604 GenerateCallFunction(object, eax, &miss); |
2650 __ JumpIfSmi(eax, &miss); | |
2651 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | |
2652 __ j(not_equal, &miss); | |
2653 | 2605 |
2654 // Patch the receiver on the stack with the global proxy if | 2606 HandlerFrontendFooter(&miss); |
2655 // necessary. | |
2656 if (object->IsGlobalObject()) { | |
2657 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | |
2658 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | |
2659 } | |
2660 | |
2661 // Invoke the function. | |
2662 __ mov(edi, eax); | |
2663 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
2664 ? CALL_AS_FUNCTION | |
2665 : CALL_AS_METHOD; | |
2666 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | |
2667 NullCallWrapper(), call_kind); | |
2668 | |
2669 // Handle load cache miss. | |
2670 __ bind(&miss); | |
2671 GenerateMissBranch(); | |
2672 | 2607 |
2673 // Return the generated code. | 2608 // Return the generated code. |
2674 return GetCode(Code::FAST, name); | 2609 return GetCode(Code::FAST, name); |
2675 } | 2610 } |
2676 | 2611 |
2677 | 2612 |
2678 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2613 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2679 Handle<JSObject> object, | 2614 Handle<JSObject> object, |
2680 Handle<GlobalObject> holder, | 2615 Handle<GlobalObject> holder, |
2681 Handle<PropertyCell> cell, | 2616 Handle<PropertyCell> cell, |
2682 Handle<JSFunction> function, | 2617 Handle<JSFunction> function, |
2683 Handle<Name> name) { | 2618 Handle<Name> name) { |
2684 if (HasCustomCallGenerator(function)) { | 2619 if (HasCustomCallGenerator(function)) { |
2685 Handle<Code> code = CompileCustomCall( | 2620 Handle<Code> code = CompileCustomCall( |
2686 object, holder, cell, function, Handle<String>::cast(name), | 2621 object, holder, cell, function, Handle<String>::cast(name), |
2687 Code::NORMAL); | 2622 Code::NORMAL); |
2688 // A null handle means bail out to the regular compiler code below. | 2623 // A null handle means bail out to the regular compiler code below. |
2689 if (!code.is_null()) return code; | 2624 if (!code.is_null()) return code; |
2690 } | 2625 } |
2691 | 2626 |
2692 Label miss; | 2627 Label miss; |
2693 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2628 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2629 // Potentially loads a closure that matches the shared function info of the |
| 2630 // function, rather than function. |
2694 GenerateLoadFunctionFromCell(cell, function, &miss); | 2631 GenerateLoadFunctionFromCell(cell, function, &miss); |
2695 PatchGlobalProxy(object); | 2632 GenerateCallFunction(object, edi, function); |
2696 | |
2697 // Set up the context (function already in edi). | |
2698 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | |
2699 | |
2700 // Jump to the cached code (tail call). | |
2701 Counters* counters = isolate()->counters(); | |
2702 __ IncrementCounter(counters->call_global_inline(), 1); | |
2703 ParameterCount expected(function->shared()->formal_parameter_count()); | |
2704 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
2705 ? CALL_AS_FUNCTION | |
2706 : CALL_AS_METHOD; | |
2707 // We call indirectly through the code field in the function to | |
2708 // allow recompilation to take effect without changing any of the | |
2709 // call sites. | |
2710 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | |
2711 expected, arguments(), JUMP_FUNCTION, | |
2712 NullCallWrapper(), call_kind); | |
2713 | 2633 |
2714 HandlerFrontendFooter(&miss); | 2634 HandlerFrontendFooter(&miss); |
2715 | 2635 |
2716 // Return the generated code. | 2636 // Return the generated code. |
2717 return GetCode(Code::NORMAL, name); | 2637 return GetCode(Code::NORMAL, name); |
2718 } | 2638 } |
2719 | 2639 |
2720 | 2640 |
2721 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2641 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2722 Handle<JSObject> object, | 2642 Handle<JSObject> object, |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3078 // ----------------------------------- | 2998 // ----------------------------------- |
3079 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2999 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
3080 } | 3000 } |
3081 | 3001 |
3082 | 3002 |
3083 #undef __ | 3003 #undef __ |
3084 | 3004 |
3085 } } // namespace v8::internal | 3005 } } // namespace v8::internal |
3086 | 3006 |
3087 #endif // V8_TARGET_ARCH_IA32 | 3007 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |