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 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 thunk_address, | 630 thunk_address, |
631 callback_arg, | 631 callback_arg, |
632 argc + kFastApiCallArguments + 1, | 632 argc + kFastApiCallArguments + 1, |
633 return_value_operand, | 633 return_value_operand, |
634 restore_context ? &context_restore_operand : NULL); | 634 restore_context ? &context_restore_operand : NULL); |
635 } | 635 } |
636 | 636 |
637 | 637 |
638 class CallInterceptorCompiler BASE_EMBEDDED { | 638 class CallInterceptorCompiler BASE_EMBEDDED { |
639 public: | 639 public: |
640 CallInterceptorCompiler(CallStubCompiler* stub_compiler, | 640 CallInterceptorCompiler(StubCompiler* stub_compiler, |
641 const ParameterCount& arguments, | 641 const ParameterCount& arguments, |
642 Register name, | 642 Register name, |
643 ExtraICState extra_ic_state) | 643 ExtraICState extra_ic_state) |
644 : stub_compiler_(stub_compiler), | 644 : stub_compiler_(stub_compiler), |
645 arguments_(arguments), | 645 arguments_(arguments), |
646 name_(name), | 646 name_(name), |
647 extra_ic_state_(extra_ic_state) {} | 647 extra_ic_state_(extra_ic_state) {} |
648 | 648 |
649 void Compile(MacroAssembler* masm, | 649 void Compile(MacroAssembler* masm, |
650 Handle<JSObject> object, | 650 Handle<JSObject> object, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 // for API (object which is instanceof for the signature). It's | 741 // for API (object which is instanceof for the signature). It's |
742 // safe to omit it here, as if present, it should be fetched | 742 // safe to omit it here, as if present, it should be fetched |
743 // by the previous CheckPrototypes. | 743 // by the previous CheckPrototypes. |
744 ASSERT(depth2 == kInvalidProtoDepth); | 744 ASSERT(depth2 == kInvalidProtoDepth); |
745 } | 745 } |
746 | 746 |
747 // Invoke function. | 747 // Invoke function. |
748 if (can_do_fast_api_call) { | 748 if (can_do_fast_api_call) { |
749 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 749 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
750 } else { | 750 } else { |
| 751 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 752 ? CALL_AS_FUNCTION |
| 753 : CALL_AS_METHOD; |
751 Handle<JSFunction> fun = optimization.constant_function(); | 754 Handle<JSFunction> fun = optimization.constant_function(); |
752 stub_compiler_->GenerateJumpFunction(object, fun); | 755 ParameterCount expected(fun); |
| 756 __ InvokeFunction(fun, expected, arguments_, |
| 757 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
753 } | 758 } |
754 | 759 |
755 // Deferred code for fast API call case---clean preallocated space. | 760 // Deferred code for fast API call case---clean preallocated space. |
756 if (can_do_fast_api_call) { | 761 if (can_do_fast_api_call) { |
757 __ bind(&miss_cleanup); | 762 __ bind(&miss_cleanup); |
758 FreeSpaceForFastApiCall(masm, scratch1); | 763 FreeSpaceForFastApiCall(masm, scratch1); |
759 __ jmp(miss_label); | 764 __ jmp(miss_label); |
760 } | 765 } |
761 | 766 |
762 // Invoke a regular function. | 767 // Invoke a regular function. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 | 815 |
811 __ pop(name_); // Restore the name. | 816 __ pop(name_); // Restore the name. |
812 __ pop(receiver); // Restore the holder. | 817 __ pop(receiver); // Restore the holder. |
813 // Leave the internal frame. | 818 // Leave the internal frame. |
814 } | 819 } |
815 | 820 |
816 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 821 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
817 __ j(not_equal, interceptor_succeeded); | 822 __ j(not_equal, interceptor_succeeded); |
818 } | 823 } |
819 | 824 |
820 CallStubCompiler* stub_compiler_; | 825 StubCompiler* stub_compiler_; |
821 const ParameterCount& arguments_; | 826 const ParameterCount& arguments_; |
822 Register name_; | 827 Register name_; |
823 ExtraICState extra_ic_state_; | 828 ExtraICState extra_ic_state_; |
824 }; | 829 }; |
825 | 830 |
826 | 831 |
827 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 832 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
828 Label* label, | 833 Label* label, |
829 Handle<Name> name) { | 834 Handle<Name> name) { |
830 if (!label->is_unused()) { | 835 if (!label->is_unused()) { |
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 | 1530 |
1526 | 1531 |
1527 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1532 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
1528 if (kind_ == Code::KEYED_CALL_IC) { | 1533 if (kind_ == Code::KEYED_CALL_IC) { |
1529 __ Cmp(rcx, name); | 1534 __ Cmp(rcx, name); |
1530 __ j(not_equal, miss); | 1535 __ j(not_equal, miss); |
1531 } | 1536 } |
1532 } | 1537 } |
1533 | 1538 |
1534 | 1539 |
1535 void CallStubCompiler::GenerateFunctionCheck(Register function, | |
1536 Register scratch, | |
1537 Label* miss) { | |
1538 __ JumpIfSmi(function, miss); | |
1539 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); | |
1540 __ j(not_equal, miss); | |
1541 } | |
1542 | |
1543 | |
1544 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1540 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1545 Handle<Cell> cell, | 1541 Handle<Cell> cell, |
1546 Handle<JSFunction> function, | 1542 Handle<JSFunction> function, |
1547 Label* miss) { | 1543 Label* miss) { |
1548 // Get the value from the cell. | 1544 // Get the value from the cell. |
1549 __ Move(rdi, cell); | 1545 __ Move(rdi, cell); |
1550 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); | 1546 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); |
1551 | 1547 |
1552 // Check that the cell contains the same function. | 1548 // Check that the cell contains the same function. |
1553 if (heap()->InNewSpace(*function)) { | 1549 if (heap()->InNewSpace(*function)) { |
1554 // We can't embed a pointer to a function in new space so we have | 1550 // We can't embed a pointer to a function in new space so we have |
1555 // to verify that the shared function info is unchanged. This has | 1551 // to verify that the shared function info is unchanged. This has |
1556 // the nice side effect that multiple closures based on the same | 1552 // the nice side effect that multiple closures based on the same |
1557 // function can all use this call IC. Before we load through the | 1553 // function can all use this call IC. Before we load through the |
1558 // function, we have to verify that it still is a function. | 1554 // function, we have to verify that it still is a function. |
1559 GenerateFunctionCheck(rdi, rax, miss); | 1555 __ JumpIfSmi(rdi, miss); |
| 1556 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); |
| 1557 __ j(not_equal, miss); |
1560 | 1558 |
1561 // Check the shared function info. Make sure it hasn't changed. | 1559 // Check the shared function info. Make sure it hasn't changed. |
1562 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); | 1560 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); |
1563 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); | 1561 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); |
1564 } else { | 1562 } else { |
1565 __ Cmp(rdi, function); | 1563 __ Cmp(rdi, function); |
1566 } | 1564 } |
1567 __ j(not_equal, miss); | 1565 __ j(not_equal, miss); |
1568 } | 1566 } |
1569 | 1567 |
(...skipping 11 matching lines...) Expand all Loading... |
1581 Handle<JSObject> holder, | 1579 Handle<JSObject> holder, |
1582 PropertyIndex index, | 1580 PropertyIndex index, |
1583 Handle<Name> name) { | 1581 Handle<Name> name) { |
1584 Label miss; | 1582 Label miss; |
1585 | 1583 |
1586 Register reg = HandlerFrontendHeader( | 1584 Register reg = HandlerFrontendHeader( |
1587 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1585 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
1588 | 1586 |
1589 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), | 1587 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), |
1590 index.translate(holder), Representation::Tagged()); | 1588 index.translate(holder), Representation::Tagged()); |
1591 GenerateJumpFunction(object, rdi, &miss); | 1589 |
| 1590 // Check that the function really is a function. |
| 1591 __ JumpIfSmi(rdi, &miss); |
| 1592 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); |
| 1593 __ j(not_equal, &miss); |
| 1594 |
| 1595 PatchGlobalProxy(object); |
| 1596 |
| 1597 // Invoke the function. |
| 1598 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1599 ? CALL_AS_FUNCTION |
| 1600 : CALL_AS_METHOD; |
| 1601 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 1602 NullCallWrapper(), call_kind); |
1592 | 1603 |
1593 HandlerFrontendFooter(&miss); | 1604 HandlerFrontendFooter(&miss); |
1594 | 1605 |
1595 // Return the generated code. | 1606 // Return the generated code. |
1596 return GetCode(Code::FAST, name); | 1607 return GetCode(Code::FAST, name); |
1597 } | 1608 } |
1598 | 1609 |
1599 | 1610 |
1600 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1611 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
1601 Handle<Object> object, | 1612 Handle<Object> object, |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1996 | 2007 |
1997 if (index_out_of_range.is_linked()) { | 2008 if (index_out_of_range.is_linked()) { |
1998 __ bind(&index_out_of_range); | 2009 __ bind(&index_out_of_range); |
1999 __ LoadRoot(rax, Heap::kNanValueRootIndex); | 2010 __ LoadRoot(rax, Heap::kNanValueRootIndex); |
2000 __ ret((argc + 1) * kPointerSize); | 2011 __ ret((argc + 1) * kPointerSize); |
2001 } | 2012 } |
2002 | 2013 |
2003 __ bind(&miss); | 2014 __ bind(&miss); |
2004 // Restore function name in rcx. | 2015 // Restore function name in rcx. |
2005 __ Move(rcx, name); | 2016 __ Move(rcx, name); |
2006 HandlerFrontendFooter(&name_miss); | 2017 __ bind(&name_miss); |
| 2018 GenerateMissBranch(); |
2007 | 2019 |
2008 // Return the generated code. | 2020 // Return the generated code. |
2009 return GetCode(type, name); | 2021 return GetCode(type, name); |
2010 } | 2022 } |
2011 | 2023 |
2012 | 2024 |
2013 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2025 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
2014 Handle<Object> object, | 2026 Handle<Object> object, |
2015 Handle<JSObject> holder, | 2027 Handle<JSObject> holder, |
2016 Handle<Cell> cell, | 2028 Handle<Cell> cell, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2061 generator.GenerateSlow(masm(), call_helper); | 2073 generator.GenerateSlow(masm(), call_helper); |
2062 | 2074 |
2063 if (index_out_of_range.is_linked()) { | 2075 if (index_out_of_range.is_linked()) { |
2064 __ bind(&index_out_of_range); | 2076 __ bind(&index_out_of_range); |
2065 __ LoadRoot(rax, Heap::kempty_stringRootIndex); | 2077 __ LoadRoot(rax, Heap::kempty_stringRootIndex); |
2066 __ ret((argc + 1) * kPointerSize); | 2078 __ ret((argc + 1) * kPointerSize); |
2067 } | 2079 } |
2068 __ bind(&miss); | 2080 __ bind(&miss); |
2069 // Restore function name in rcx. | 2081 // Restore function name in rcx. |
2070 __ Move(rcx, name); | 2082 __ Move(rcx, name); |
2071 HandlerFrontendFooter(&name_miss); | 2083 __ bind(&name_miss); |
| 2084 GenerateMissBranch(); |
2072 | 2085 |
2073 // Return the generated code. | 2086 // Return the generated code. |
2074 return GetCode(type, name); | 2087 return GetCode(type, name); |
2075 } | 2088 } |
2076 | 2089 |
2077 | 2090 |
2078 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2091 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2079 Handle<Object> object, | 2092 Handle<Object> object, |
2080 Handle<JSObject> holder, | 2093 Handle<JSObject> holder, |
2081 Handle<Cell> cell, | 2094 Handle<Cell> cell, |
(...skipping 25 matching lines...) Expand all Loading... |
2107 // Convert the smi code to uint16. | 2120 // Convert the smi code to uint16. |
2108 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); | 2121 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); |
2109 | 2122 |
2110 StringCharFromCodeGenerator generator(code, rax); | 2123 StringCharFromCodeGenerator generator(code, rax); |
2111 generator.GenerateFast(masm()); | 2124 generator.GenerateFast(masm()); |
2112 __ ret(2 * kPointerSize); | 2125 __ ret(2 * kPointerSize); |
2113 | 2126 |
2114 StubRuntimeCallHelper call_helper; | 2127 StubRuntimeCallHelper call_helper; |
2115 generator.GenerateSlow(masm(), call_helper); | 2128 generator.GenerateSlow(masm(), call_helper); |
2116 | 2129 |
| 2130 // Tail call the full function. We do not have to patch the receiver |
| 2131 // because the function makes no use of it. |
2117 __ bind(&slow); | 2132 __ bind(&slow); |
2118 // We do not have to patch the receiver because the function makes no use of | 2133 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2119 // it. | 2134 ? CALL_AS_FUNCTION |
2120 GenerateJumpFunctionIgnoreReceiver(function); | 2135 : CALL_AS_METHOD; |
| 2136 ParameterCount expected(function); |
| 2137 __ InvokeFunction(function, expected, arguments(), |
| 2138 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
2121 | 2139 |
2122 HandlerFrontendFooter(&miss); | 2140 HandlerFrontendFooter(&miss); |
2123 | 2141 |
2124 // Return the generated code. | 2142 // Return the generated code. |
2125 return GetCode(type, name); | 2143 return GetCode(type, name); |
2126 } | 2144 } |
2127 | 2145 |
2128 | 2146 |
2129 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2147 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2130 Handle<Object> object, | 2148 Handle<Object> object, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2213 // Return a new heap number. | 2231 // Return a new heap number. |
2214 __ AllocateHeapNumber(rax, rbx, &slow); | 2232 __ AllocateHeapNumber(rax, rbx, &slow); |
2215 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); | 2233 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); |
2216 __ ret(2 * kPointerSize); | 2234 __ ret(2 * kPointerSize); |
2217 | 2235 |
2218 // Return the argument (when it's an already round heap number). | 2236 // Return the argument (when it's an already round heap number). |
2219 __ bind(&already_round); | 2237 __ bind(&already_round); |
2220 __ movq(rax, args.GetArgumentOperand(1)); | 2238 __ movq(rax, args.GetArgumentOperand(1)); |
2221 __ ret(2 * kPointerSize); | 2239 __ ret(2 * kPointerSize); |
2222 | 2240 |
| 2241 // Tail call the full function. We do not have to patch the receiver |
| 2242 // because the function makes no use of it. |
2223 __ bind(&slow); | 2243 __ bind(&slow); |
2224 // We do not have to patch the receiver because the function makes no use of | 2244 ParameterCount expected(function); |
2225 // it. | 2245 __ InvokeFunction(function, expected, arguments(), |
2226 GenerateJumpFunctionIgnoreReceiver(function); | 2246 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); |
2227 | 2247 |
2228 HandlerFrontendFooter(&miss); | 2248 HandlerFrontendFooter(&miss); |
2229 | 2249 |
2230 // Return the generated code. | 2250 // Return the generated code. |
2231 return GetCode(type, name); | 2251 return GetCode(type, name); |
2232 } | 2252 } |
2233 | 2253 |
2234 | 2254 |
2235 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2255 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2236 Handle<Object> object, | 2256 Handle<Object> object, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2297 __ ret(2 * kPointerSize); | 2317 __ ret(2 * kPointerSize); |
2298 | 2318 |
2299 // If the argument is negative, clear the sign, and return a new | 2319 // If the argument is negative, clear the sign, and return a new |
2300 // number. We still have the sign mask in rdi. | 2320 // number. We still have the sign mask in rdi. |
2301 __ bind(&negative_sign); | 2321 __ bind(&negative_sign); |
2302 __ xor_(rbx, rdi); | 2322 __ xor_(rbx, rdi); |
2303 __ AllocateHeapNumber(rax, rdx, &slow); | 2323 __ AllocateHeapNumber(rax, rdx, &slow); |
2304 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx); | 2324 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx); |
2305 __ ret(2 * kPointerSize); | 2325 __ ret(2 * kPointerSize); |
2306 | 2326 |
| 2327 // Tail call the full function. We do not have to patch the receiver |
| 2328 // because the function makes no use of it. |
2307 __ bind(&slow); | 2329 __ bind(&slow); |
2308 // We do not have to patch the receiver because the function makes no use of | 2330 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2309 // it. | 2331 ? CALL_AS_FUNCTION |
2310 GenerateJumpFunctionIgnoreReceiver(function); | 2332 : CALL_AS_METHOD; |
| 2333 ParameterCount expected(function); |
| 2334 __ InvokeFunction(function, expected, arguments(), |
| 2335 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
2311 | 2336 |
2312 HandlerFrontendFooter(&miss); | 2337 HandlerFrontendFooter(&miss); |
2313 | 2338 |
2314 // Return the generated code. | 2339 // Return the generated code. |
2315 return GetCode(type, name); | 2340 return GetCode(type, name); |
2316 } | 2341 } |
2317 | 2342 |
2318 | 2343 |
2319 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2344 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2320 const CallOptimization& optimization, | 2345 const CallOptimization& optimization, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2358 // Move the return address on top of the stack. | 2383 // Move the return address on top of the stack. |
2359 __ movq(rax, | 2384 __ movq(rax, |
2360 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); | 2385 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); |
2361 __ movq(StackOperandForReturnAddress(0), rax); | 2386 __ movq(StackOperandForReturnAddress(0), rax); |
2362 | 2387 |
2363 GenerateFastApiCall(masm(), optimization, argc); | 2388 GenerateFastApiCall(masm(), optimization, argc); |
2364 | 2389 |
2365 __ bind(&miss); | 2390 __ bind(&miss); |
2366 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2391 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
2367 | 2392 |
2368 HandlerFrontendFooter(&miss_before_stack_reserved); | 2393 __ bind(&miss_before_stack_reserved); |
| 2394 GenerateMissBranch(); |
2369 | 2395 |
2370 // Return the generated code. | 2396 // Return the generated code. |
2371 return GetCode(function); | 2397 return GetCode(function); |
2372 } | 2398 } |
2373 | 2399 |
2374 | 2400 |
2375 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2401 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
2376 Label success; | 2402 Label success; |
2377 // Check that the object is a boolean. | 2403 // Check that the object is a boolean. |
2378 __ CompareRoot(object, Heap::kTrueValueRootIndex); | 2404 __ CompareRoot(object, Heap::kTrueValueRootIndex); |
2379 __ j(equal, &success); | 2405 __ j(equal, &success); |
2380 __ CompareRoot(object, Heap::kFalseValueRootIndex); | 2406 __ CompareRoot(object, Heap::kFalseValueRootIndex); |
2381 __ j(not_equal, miss); | 2407 __ j(not_equal, miss); |
2382 __ bind(&success); | 2408 __ bind(&success); |
2383 } | 2409 } |
2384 | 2410 |
2385 | 2411 |
2386 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { | 2412 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
2387 if (!object.is_null() && object->IsGlobalObject()) { | 2413 if (object->IsGlobalObject()) { |
2388 StackArgumentsAccessor args(rsp, arguments()); | 2414 StackArgumentsAccessor args(rsp, arguments()); |
2389 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2415 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
2390 __ movq(args.GetReceiverOperand(), rdx); | 2416 __ movq(args.GetReceiverOperand(), rdx); |
2391 } | 2417 } |
2392 } | 2418 } |
2393 | 2419 |
2394 | 2420 |
2395 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | 2421 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
2396 Handle<JSObject> holder, | 2422 Handle<JSObject> holder, |
2397 Handle<Name> name, | 2423 Handle<Name> name, |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2466 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2492 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
2467 reg = CheckPrototypes( | 2493 reg = CheckPrototypes( |
2468 IC::CurrentTypeOf(prototype, isolate()), | 2494 IC::CurrentTypeOf(prototype, isolate()), |
2469 rax, holder, rbx, rdx, rdi, name, miss); | 2495 rax, holder, rbx, rdx, rdi, name, miss); |
2470 } | 2496 } |
2471 | 2497 |
2472 return reg; | 2498 return reg; |
2473 } | 2499 } |
2474 | 2500 |
2475 | 2501 |
2476 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | 2502 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { |
2477 Register function, | 2503 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2478 Label* miss) { | 2504 ? CALL_AS_FUNCTION |
2479 // Check that the function really is a function. | 2505 : CALL_AS_METHOD; |
2480 GenerateFunctionCheck(function, rbx, miss); | 2506 ParameterCount expected(function); |
2481 | 2507 __ InvokeFunction(function, expected, arguments(), |
2482 if (!function.is(rdi)) __ movq(rdi, function); | 2508 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
2483 PatchGlobalProxy(object); | |
2484 | |
2485 // Invoke the function. | |
2486 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | |
2487 NullCallWrapper(), call_kind()); | |
2488 } | 2509 } |
2489 | 2510 |
2490 | 2511 |
| 2512 Handle<Code> CallStubCompiler::CompileCallConstant( |
| 2513 Handle<Object> object, |
| 2514 Handle<JSObject> holder, |
| 2515 Handle<Name> name, |
| 2516 CheckType check, |
| 2517 Handle<JSFunction> function) { |
| 2518 if (HasCustomCallGenerator(function)) { |
| 2519 Handle<Code> code = CompileCustomCall(object, holder, |
| 2520 Handle<PropertyCell>::null(), |
| 2521 function, Handle<String>::cast(name), |
| 2522 Code::FAST); |
| 2523 // A null handle means bail out to the regular compiler code below. |
| 2524 if (!code.is_null()) return code; |
| 2525 } |
| 2526 |
| 2527 Label miss; |
| 2528 HandlerFrontendHeader(object, holder, name, check, &miss); |
| 2529 PatchGlobalProxy(object); |
| 2530 CompileHandlerBackend(function); |
| 2531 HandlerFrontendFooter(&miss); |
| 2532 |
| 2533 // Return the generated code. |
| 2534 return GetCode(function); |
| 2535 } |
| 2536 |
| 2537 |
2491 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2538 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2492 Handle<JSObject> holder, | 2539 Handle<JSObject> holder, |
2493 Handle<Name> name) { | 2540 Handle<Name> name) { |
2494 Label miss; | 2541 Label miss; |
2495 GenerateNameCheck(name, &miss); | 2542 GenerateNameCheck(name, &miss); |
2496 | 2543 |
2497 LookupResult lookup(isolate()); | 2544 LookupResult lookup(isolate()); |
2498 LookupPostInterceptor(holder, name, &lookup); | 2545 LookupPostInterceptor(holder, name, &lookup); |
2499 | 2546 |
2500 // Get the receiver from the stack. | 2547 // Get the receiver from the stack. |
2501 StackArgumentsAccessor args(rsp, arguments()); | 2548 StackArgumentsAccessor args(rsp, arguments()); |
2502 __ movq(rdx, args.GetReceiverOperand()); | 2549 __ movq(rdx, args.GetReceiverOperand()); |
2503 | 2550 |
2504 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); | 2551 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); |
2505 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, | 2552 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, |
2506 &miss); | 2553 &miss); |
2507 | 2554 |
2508 // Restore receiver. | 2555 // Restore receiver. |
2509 __ movq(rdx, args.GetReceiverOperand()); | 2556 __ movq(rdx, args.GetReceiverOperand()); |
2510 | 2557 |
2511 GenerateJumpFunction(object, rax, &miss); | 2558 // Check that the function really is a function. |
| 2559 __ JumpIfSmi(rax, &miss); |
| 2560 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 2561 __ j(not_equal, &miss); |
2512 | 2562 |
2513 HandlerFrontendFooter(&miss); | 2563 // Patch the receiver on the stack with the global proxy if |
| 2564 // necessary. |
| 2565 if (object->IsGlobalObject()) { |
| 2566 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2567 __ movq(args.GetReceiverOperand(), rdx); |
| 2568 } |
| 2569 |
| 2570 // Invoke the function. |
| 2571 __ movq(rdi, rax); |
| 2572 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2573 ? CALL_AS_FUNCTION |
| 2574 : CALL_AS_METHOD; |
| 2575 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2576 NullCallWrapper(), call_kind); |
| 2577 |
| 2578 // Handle load cache miss. |
| 2579 __ bind(&miss); |
| 2580 GenerateMissBranch(); |
2514 | 2581 |
2515 // Return the generated code. | 2582 // Return the generated code. |
2516 return GetCode(Code::FAST, name); | 2583 return GetCode(Code::FAST, name); |
2517 } | 2584 } |
2518 | 2585 |
2519 | 2586 |
2520 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2587 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2521 Handle<JSObject> object, | 2588 Handle<JSObject> object, |
2522 Handle<GlobalObject> holder, | 2589 Handle<GlobalObject> holder, |
2523 Handle<PropertyCell> cell, | 2590 Handle<PropertyCell> cell, |
2524 Handle<JSFunction> function, | 2591 Handle<JSFunction> function, |
2525 Handle<Name> name) { | 2592 Handle<Name> name) { |
2526 if (HasCustomCallGenerator(function)) { | 2593 if (HasCustomCallGenerator(function)) { |
2527 Handle<Code> code = CompileCustomCall( | 2594 Handle<Code> code = CompileCustomCall( |
2528 object, holder, cell, function, Handle<String>::cast(name), | 2595 object, holder, cell, function, Handle<String>::cast(name), |
2529 Code::NORMAL); | 2596 Code::NORMAL); |
2530 // A null handle means bail out to the regular compiler code below. | 2597 // A null handle means bail out to the regular compiler code below. |
2531 if (!code.is_null()) return code; | 2598 if (!code.is_null()) return code; |
2532 } | 2599 } |
2533 | 2600 |
2534 Label miss; | 2601 Label miss; |
2535 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2602 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
2536 // Potentially loads a closure that matches the shared function info of the | |
2537 // function, rather than function. | |
2538 GenerateLoadFunctionFromCell(cell, function, &miss); | 2603 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2604 PatchGlobalProxy(object); |
| 2605 |
| 2606 // Set up the context (function already in rdi). |
| 2607 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 2608 |
| 2609 // Jump to the cached code (tail call). |
2539 Counters* counters = isolate()->counters(); | 2610 Counters* counters = isolate()->counters(); |
2540 __ IncrementCounter(counters->call_global_inline(), 1); | 2611 __ IncrementCounter(counters->call_global_inline(), 1); |
2541 GenerateJumpFunction(object, rdi, function); | 2612 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2613 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2614 ? CALL_AS_FUNCTION |
| 2615 : CALL_AS_METHOD; |
| 2616 // We call indirectly through the code field in the function to |
| 2617 // allow recompilation to take effect without changing any of the |
| 2618 // call sites. |
| 2619 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2620 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, |
| 2621 NullCallWrapper(), call_kind); |
| 2622 |
2542 HandlerFrontendFooter(&miss); | 2623 HandlerFrontendFooter(&miss); |
2543 | 2624 |
2544 // Return the generated code. | 2625 // Return the generated code. |
2545 return GetCode(Code::NORMAL, name); | 2626 return GetCode(Code::NORMAL, name); |
2546 } | 2627 } |
2547 | 2628 |
2548 | 2629 |
2549 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2630 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
2550 Handle<JSObject> object, | 2631 Handle<JSObject> object, |
2551 Handle<JSObject> holder, | 2632 Handle<JSObject> holder, |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2915 // ----------------------------------- | 2996 // ----------------------------------- |
2916 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2997 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
2917 } | 2998 } |
2918 | 2999 |
2919 | 3000 |
2920 #undef __ | 3001 #undef __ |
2921 | 3002 |
2922 } } // namespace v8::internal | 3003 } } // namespace v8::internal |
2923 | 3004 |
2924 #endif // V8_TARGET_ARCH_X64 | 3005 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |