| 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 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 thunk_address, | 635 thunk_address, |
| 636 callback_arg, | 636 callback_arg, |
| 637 argc + kFastApiCallArguments + 1, | 637 argc + kFastApiCallArguments + 1, |
| 638 return_value_operand, | 638 return_value_operand, |
| 639 restore_context ? &context_restore_operand : NULL); | 639 restore_context ? &context_restore_operand : NULL); |
| 640 } | 640 } |
| 641 | 641 |
| 642 | 642 |
| 643 class CallInterceptorCompiler BASE_EMBEDDED { | 643 class CallInterceptorCompiler BASE_EMBEDDED { |
| 644 public: | 644 public: |
| 645 CallInterceptorCompiler(StubCompiler* stub_compiler, | 645 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| 646 const ParameterCount& arguments, | 646 const ParameterCount& arguments, |
| 647 Register name, | 647 Register name, |
| 648 Code::ExtraICState extra_ic_state) | 648 Code::ExtraICState extra_ic_state) |
| 649 : stub_compiler_(stub_compiler), | 649 : stub_compiler_(stub_compiler), |
| 650 arguments_(arguments), | 650 arguments_(arguments), |
| 651 name_(name), | 651 name_(name), |
| 652 extra_ic_state_(extra_ic_state) {} | 652 extra_ic_state_(extra_ic_state) {} |
| 653 | 653 |
| 654 void Compile(MacroAssembler* masm, | 654 void Compile(MacroAssembler* masm, |
| 655 Handle<JSObject> object, | 655 Handle<JSObject> object, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 // for API (object which is instanceof for the signature). It's | 746 // for API (object which is instanceof for the signature). It's |
| 747 // safe to omit it here, as if present, it should be fetched | 747 // safe to omit it here, as if present, it should be fetched |
| 748 // by the previous CheckPrototypes. | 748 // by the previous CheckPrototypes. |
| 749 ASSERT(depth2 == kInvalidProtoDepth); | 749 ASSERT(depth2 == kInvalidProtoDepth); |
| 750 } | 750 } |
| 751 | 751 |
| 752 // Invoke function. | 752 // Invoke function. |
| 753 if (can_do_fast_api_call) { | 753 if (can_do_fast_api_call) { |
| 754 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 754 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| 755 } else { | 755 } else { |
| 756 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | |
| 757 ? CALL_AS_FUNCTION | |
| 758 : CALL_AS_METHOD; | |
| 759 Handle<JSFunction> fun = optimization.constant_function(); | 756 Handle<JSFunction> fun = optimization.constant_function(); |
| 760 ParameterCount expected(fun); | 757 stub_compiler_->GenerateCallFunction(object, fun); |
| 761 __ InvokeFunction(fun, expected, arguments_, | |
| 762 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 763 } | 758 } |
| 764 | 759 |
| 765 // Deferred code for fast API call case---clean preallocated space. | 760 // Deferred code for fast API call case---clean preallocated space. |
| 766 if (can_do_fast_api_call) { | 761 if (can_do_fast_api_call) { |
| 767 __ bind(&miss_cleanup); | 762 __ bind(&miss_cleanup); |
| 768 FreeSpaceForFastApiCall(masm, scratch1); | 763 FreeSpaceForFastApiCall(masm, scratch1); |
| 769 __ jmp(miss_label); | 764 __ jmp(miss_label); |
| 770 } | 765 } |
| 771 | 766 |
| 772 // Invoke a regular function. | 767 // Invoke a regular function. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 | 820 |
| 826 __ pop(name_); // Restore the name. | 821 __ pop(name_); // Restore the name. |
| 827 __ pop(receiver); // Restore the holder. | 822 __ pop(receiver); // Restore the holder. |
| 828 // Leave the internal frame. | 823 // Leave the internal frame. |
| 829 } | 824 } |
| 830 | 825 |
| 831 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 826 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 832 __ j(not_equal, interceptor_succeeded); | 827 __ j(not_equal, interceptor_succeeded); |
| 833 } | 828 } |
| 834 | 829 |
| 835 StubCompiler* stub_compiler_; | 830 CallStubCompiler* stub_compiler_; |
| 836 const ParameterCount& arguments_; | 831 const ParameterCount& arguments_; |
| 837 Register name_; | 832 Register name_; |
| 838 Code::ExtraICState extra_ic_state_; | 833 Code::ExtraICState extra_ic_state_; |
| 839 }; | 834 }; |
| 840 | 835 |
| 841 | 836 |
| 842 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 837 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 843 Label* label, | 838 Label* label, |
| 844 Handle<Name> name) { | 839 Handle<Name> name) { |
| 845 if (!label->is_unused()) { | 840 if (!label->is_unused()) { |
| (...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1542 | 1537 |
| 1543 | 1538 |
| 1544 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1539 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1545 if (kind_ == Code::KEYED_CALL_IC) { | 1540 if (kind_ == Code::KEYED_CALL_IC) { |
| 1546 __ Cmp(rcx, name); | 1541 __ Cmp(rcx, name); |
| 1547 __ j(not_equal, miss); | 1542 __ j(not_equal, miss); |
| 1548 } | 1543 } |
| 1549 } | 1544 } |
| 1550 | 1545 |
| 1551 | 1546 |
| 1547 void CallStubCompiler::GenerateFunctionCheck(Register function, |
| 1548 Register scratch, |
| 1549 Label* miss) { |
| 1550 __ JumpIfSmi(function, miss); |
| 1551 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
| 1552 __ j(not_equal, miss); |
| 1553 } |
| 1554 |
| 1555 |
| 1552 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1556 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1553 Handle<Cell> cell, | 1557 Handle<Cell> cell, |
| 1554 Handle<JSFunction> function, | 1558 Handle<JSFunction> function, |
| 1555 Label* miss) { | 1559 Label* miss) { |
| 1556 // Get the value from the cell. | 1560 // Get the value from the cell. |
| 1557 __ Move(rdi, cell); | 1561 __ Move(rdi, cell); |
| 1558 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); | 1562 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); |
| 1559 | 1563 |
| 1560 // Check that the cell contains the same function. | 1564 // Check that the cell contains the same function. |
| 1561 if (heap()->InNewSpace(*function)) { | 1565 if (heap()->InNewSpace(*function)) { |
| 1562 // We can't embed a pointer to a function in new space so we have | 1566 // We can't embed a pointer to a function in new space so we have |
| 1563 // to verify that the shared function info is unchanged. This has | 1567 // to verify that the shared function info is unchanged. This has |
| 1564 // the nice side effect that multiple closures based on the same | 1568 // the nice side effect that multiple closures based on the same |
| 1565 // function can all use this call IC. Before we load through the | 1569 // function can all use this call IC. Before we load through the |
| 1566 // function, we have to verify that it still is a function. | 1570 // function, we have to verify that it still is a function. |
| 1567 __ JumpIfSmi(rdi, miss); | 1571 GenerateFunctionCheck(rdi, rax, miss); |
| 1568 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); | |
| 1569 __ j(not_equal, miss); | |
| 1570 | 1572 |
| 1571 // Check the shared function info. Make sure it hasn't changed. | 1573 // Check the shared function info. Make sure it hasn't changed. |
| 1572 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); | 1574 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); |
| 1573 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); | 1575 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); |
| 1574 } else { | 1576 } else { |
| 1575 __ Cmp(rdi, function); | 1577 __ Cmp(rdi, function); |
| 1576 } | 1578 } |
| 1577 __ j(not_equal, miss); | 1579 __ j(not_equal, miss); |
| 1578 } | 1580 } |
| 1579 | 1581 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1591 Handle<JSObject> holder, | 1593 Handle<JSObject> holder, |
| 1592 PropertyIndex index, | 1594 PropertyIndex index, |
| 1593 Handle<Name> name) { | 1595 Handle<Name> name) { |
| 1594 Label miss; | 1596 Label miss; |
| 1595 | 1597 |
| 1596 Register reg = HandlerFrontendHeader( | 1598 Register reg = HandlerFrontendHeader( |
| 1597 object, holder, name, RECEIVER_MAP_CHECK, &miss); | 1599 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1598 | 1600 |
| 1599 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), | 1601 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), |
| 1600 index.translate(holder), Representation::Tagged()); | 1602 index.translate(holder), Representation::Tagged()); |
| 1601 | 1603 GenerateCallFunction(object, rdi, &miss); |
| 1602 // Check that the function really is a function. | |
| 1603 __ JumpIfSmi(rdi, &miss); | |
| 1604 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); | |
| 1605 __ j(not_equal, &miss); | |
| 1606 | |
| 1607 PatchGlobalProxy(object); | |
| 1608 | |
| 1609 // Invoke the function. | |
| 1610 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 1611 ? CALL_AS_FUNCTION | |
| 1612 : CALL_AS_METHOD; | |
| 1613 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | |
| 1614 NullCallWrapper(), call_kind); | |
| 1615 | 1604 |
| 1616 HandlerFrontendFooter(&miss); | 1605 HandlerFrontendFooter(&miss); |
| 1617 | 1606 |
| 1618 // Return the generated code. | 1607 // Return the generated code. |
| 1619 return GetCode(Code::FAST, name); | 1608 return GetCode(Code::FAST, name); |
| 1620 } | 1609 } |
| 1621 | 1610 |
| 1622 | 1611 |
| 1623 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1612 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1624 Handle<Object> object, | 1613 Handle<Object> object, |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2019 | 2008 |
| 2020 if (index_out_of_range.is_linked()) { | 2009 if (index_out_of_range.is_linked()) { |
| 2021 __ bind(&index_out_of_range); | 2010 __ bind(&index_out_of_range); |
| 2022 __ LoadRoot(rax, Heap::kNanValueRootIndex); | 2011 __ LoadRoot(rax, Heap::kNanValueRootIndex); |
| 2023 __ ret((argc + 1) * kPointerSize); | 2012 __ ret((argc + 1) * kPointerSize); |
| 2024 } | 2013 } |
| 2025 | 2014 |
| 2026 __ bind(&miss); | 2015 __ bind(&miss); |
| 2027 // Restore function name in rcx. | 2016 // Restore function name in rcx. |
| 2028 __ Move(rcx, name); | 2017 __ Move(rcx, name); |
| 2029 __ bind(&name_miss); | 2018 HandlerFrontendFooter(&name_miss); |
| 2030 GenerateMissBranch(); | |
| 2031 | 2019 |
| 2032 // Return the generated code. | 2020 // Return the generated code. |
| 2033 return GetCode(type, name); | 2021 return GetCode(type, name); |
| 2034 } | 2022 } |
| 2035 | 2023 |
| 2036 | 2024 |
| 2037 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 2025 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2038 Handle<Object> object, | 2026 Handle<Object> object, |
| 2039 Handle<JSObject> holder, | 2027 Handle<JSObject> holder, |
| 2040 Handle<Cell> cell, | 2028 Handle<Cell> cell, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2085 generator.GenerateSlow(masm(), call_helper); | 2073 generator.GenerateSlow(masm(), call_helper); |
| 2086 | 2074 |
| 2087 if (index_out_of_range.is_linked()) { | 2075 if (index_out_of_range.is_linked()) { |
| 2088 __ bind(&index_out_of_range); | 2076 __ bind(&index_out_of_range); |
| 2089 __ LoadRoot(rax, Heap::kempty_stringRootIndex); | 2077 __ LoadRoot(rax, Heap::kempty_stringRootIndex); |
| 2090 __ ret((argc + 1) * kPointerSize); | 2078 __ ret((argc + 1) * kPointerSize); |
| 2091 } | 2079 } |
| 2092 __ bind(&miss); | 2080 __ bind(&miss); |
| 2093 // Restore function name in rcx. | 2081 // Restore function name in rcx. |
| 2094 __ Move(rcx, name); | 2082 __ Move(rcx, name); |
| 2095 __ bind(&name_miss); | 2083 HandlerFrontendFooter(&name_miss); |
| 2096 GenerateMissBranch(); | |
| 2097 | 2084 |
| 2098 // Return the generated code. | 2085 // Return the generated code. |
| 2099 return GetCode(type, name); | 2086 return GetCode(type, name); |
| 2100 } | 2087 } |
| 2101 | 2088 |
| 2102 | 2089 |
| 2103 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2090 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2104 Handle<Object> object, | 2091 Handle<Object> object, |
| 2105 Handle<JSObject> holder, | 2092 Handle<JSObject> holder, |
| 2106 Handle<Cell> cell, | 2093 Handle<Cell> cell, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2132 // Convert the smi code to uint16. | 2119 // Convert the smi code to uint16. |
| 2133 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); | 2120 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); |
| 2134 | 2121 |
| 2135 StringCharFromCodeGenerator generator(code, rax); | 2122 StringCharFromCodeGenerator generator(code, rax); |
| 2136 generator.GenerateFast(masm()); | 2123 generator.GenerateFast(masm()); |
| 2137 __ ret(2 * kPointerSize); | 2124 __ ret(2 * kPointerSize); |
| 2138 | 2125 |
| 2139 StubRuntimeCallHelper call_helper; | 2126 StubRuntimeCallHelper call_helper; |
| 2140 generator.GenerateSlow(masm(), call_helper); | 2127 generator.GenerateSlow(masm(), call_helper); |
| 2141 | 2128 |
| 2142 // Tail call the full function. We do not have to patch the receiver | |
| 2143 // because the function makes no use of it. | |
| 2144 __ bind(&slow); | 2129 __ bind(&slow); |
| 2145 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2130 // We do not have to patch the receiver because the function makes no use of |
| 2146 ? CALL_AS_FUNCTION | 2131 // it. |
| 2147 : CALL_AS_METHOD; | 2132 GenerateCallFunction(Handle<Object>::null(), function); |
| 2148 ParameterCount expected(function); | |
| 2149 __ InvokeFunction(function, expected, arguments(), | |
| 2150 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 2151 | 2133 |
| 2152 HandlerFrontendFooter(&miss); | 2134 HandlerFrontendFooter(&miss); |
| 2153 | 2135 |
| 2154 // Return the generated code. | 2136 // Return the generated code. |
| 2155 return GetCode(type, name); | 2137 return GetCode(type, name); |
| 2156 } | 2138 } |
| 2157 | 2139 |
| 2158 | 2140 |
| 2159 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2141 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2160 Handle<Object> object, | 2142 Handle<Object> object, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2243 // Return a new heap number. | 2225 // Return a new heap number. |
| 2244 __ AllocateHeapNumber(rax, rbx, &slow); | 2226 __ AllocateHeapNumber(rax, rbx, &slow); |
| 2245 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); | 2227 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); |
| 2246 __ ret(2 * kPointerSize); | 2228 __ ret(2 * kPointerSize); |
| 2247 | 2229 |
| 2248 // Return the argument (when it's an already round heap number). | 2230 // Return the argument (when it's an already round heap number). |
| 2249 __ bind(&already_round); | 2231 __ bind(&already_round); |
| 2250 __ movq(rax, args.GetArgumentOperand(1)); | 2232 __ movq(rax, args.GetArgumentOperand(1)); |
| 2251 __ ret(2 * kPointerSize); | 2233 __ ret(2 * kPointerSize); |
| 2252 | 2234 |
| 2253 // Tail call the full function. We do not have to patch the receiver | |
| 2254 // because the function makes no use of it. | |
| 2255 __ bind(&slow); | 2235 __ bind(&slow); |
| 2256 ParameterCount expected(function); | 2236 // We do not have to patch the receiver because the function makes no use of |
| 2257 __ InvokeFunction(function, expected, arguments(), | 2237 // it. |
| 2258 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2238 GenerateCallFunction(Handle<Object>::null(), function); |
| 2259 | 2239 |
| 2260 HandlerFrontendFooter(&miss); | 2240 HandlerFrontendFooter(&miss); |
| 2261 | 2241 |
| 2262 // Return the generated code. | 2242 // Return the generated code. |
| 2263 return GetCode(type, name); | 2243 return GetCode(type, name); |
| 2264 } | 2244 } |
| 2265 | 2245 |
| 2266 | 2246 |
| 2267 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2247 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2268 Handle<Object> object, | 2248 Handle<Object> object, |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2329 __ ret(2 * kPointerSize); | 2309 __ ret(2 * kPointerSize); |
| 2330 | 2310 |
| 2331 // If the argument is negative, clear the sign, and return a new | 2311 // If the argument is negative, clear the sign, and return a new |
| 2332 // number. We still have the sign mask in rdi. | 2312 // number. We still have the sign mask in rdi. |
| 2333 __ bind(&negative_sign); | 2313 __ bind(&negative_sign); |
| 2334 __ xor_(rbx, rdi); | 2314 __ xor_(rbx, rdi); |
| 2335 __ AllocateHeapNumber(rax, rdx, &slow); | 2315 __ AllocateHeapNumber(rax, rdx, &slow); |
| 2336 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx); | 2316 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx); |
| 2337 __ ret(2 * kPointerSize); | 2317 __ ret(2 * kPointerSize); |
| 2338 | 2318 |
| 2339 // Tail call the full function. We do not have to patch the receiver | |
| 2340 // because the function makes no use of it. | |
| 2341 __ bind(&slow); | 2319 __ bind(&slow); |
| 2342 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2320 // We do not have to patch the receiver because the function makes no use of |
| 2343 ? CALL_AS_FUNCTION | 2321 // it. |
| 2344 : CALL_AS_METHOD; | 2322 GenerateCallFunction(Handle<Object>::null(), function); |
| 2345 ParameterCount expected(function); | |
| 2346 __ InvokeFunction(function, expected, arguments(), | |
| 2347 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 2348 | 2323 |
| 2349 HandlerFrontendFooter(&miss); | 2324 HandlerFrontendFooter(&miss); |
| 2350 | 2325 |
| 2351 // Return the generated code. | 2326 // Return the generated code. |
| 2352 return GetCode(type, name); | 2327 return GetCode(type, name); |
| 2353 } | 2328 } |
| 2354 | 2329 |
| 2355 | 2330 |
| 2356 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2331 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2357 const CallOptimization& optimization, | 2332 const CallOptimization& optimization, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2395 // Move the return address on top of the stack. | 2370 // Move the return address on top of the stack. |
| 2396 __ movq(rax, | 2371 __ movq(rax, |
| 2397 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); | 2372 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); |
| 2398 __ movq(StackOperandForReturnAddress(0), rax); | 2373 __ movq(StackOperandForReturnAddress(0), rax); |
| 2399 | 2374 |
| 2400 GenerateFastApiCall(masm(), optimization, argc); | 2375 GenerateFastApiCall(masm(), optimization, argc); |
| 2401 | 2376 |
| 2402 __ bind(&miss); | 2377 __ bind(&miss); |
| 2403 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2378 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2404 | 2379 |
| 2405 __ bind(&miss_before_stack_reserved); | 2380 HandlerFrontendFooter(&miss_before_stack_reserved); |
| 2406 GenerateMissBranch(); | |
| 2407 | 2381 |
| 2408 // Return the generated code. | 2382 // Return the generated code. |
| 2409 return GetCode(function); | 2383 return GetCode(function); |
| 2410 } | 2384 } |
| 2411 | 2385 |
| 2412 | 2386 |
| 2413 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2387 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2414 Label success; | 2388 Label success; |
| 2415 // Check that the object is a boolean. | 2389 // Check that the object is a boolean. |
| 2416 __ CompareRoot(object, Heap::kTrueValueRootIndex); | 2390 __ CompareRoot(object, Heap::kTrueValueRootIndex); |
| 2417 __ j(equal, &success); | 2391 __ j(equal, &success); |
| 2418 __ CompareRoot(object, Heap::kFalseValueRootIndex); | 2392 __ CompareRoot(object, Heap::kFalseValueRootIndex); |
| 2419 __ j(not_equal, miss); | 2393 __ j(not_equal, miss); |
| 2420 __ bind(&success); | 2394 __ bind(&success); |
| 2421 } | 2395 } |
| 2422 | 2396 |
| 2423 | 2397 |
| 2424 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { | 2398 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
| 2425 if (object->IsGlobalObject()) { | 2399 if (!object.is_null() && object->IsGlobalObject()) { |
| 2426 StackArgumentsAccessor args(rsp, arguments()); | 2400 StackArgumentsAccessor args(rsp, arguments()); |
| 2427 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2401 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2428 __ movq(args.GetReceiverOperand(), rdx); | 2402 __ movq(args.GetReceiverOperand(), rdx); |
| 2429 } | 2403 } |
| 2430 } | 2404 } |
| 2431 | 2405 |
| 2432 | 2406 |
| 2433 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, | 2407 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
| 2434 Handle<JSObject> holder, | 2408 Handle<JSObject> holder, |
| 2435 Handle<Name> name, | 2409 Handle<Name> name, |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2504 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | 2478 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2505 reg = CheckPrototypes( | 2479 reg = CheckPrototypes( |
| 2506 IC::CurrentTypeOf(prototype, isolate()), | 2480 IC::CurrentTypeOf(prototype, isolate()), |
| 2507 rax, holder, rbx, rdx, rdi, name, miss); | 2481 rax, holder, rbx, rdx, rdi, name, miss); |
| 2508 } | 2482 } |
| 2509 | 2483 |
| 2510 return reg; | 2484 return reg; |
| 2511 } | 2485 } |
| 2512 | 2486 |
| 2513 | 2487 |
| 2514 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2488 void CallStubCompiler::GenerateCallFunction(Handle<Object> object, |
| 2515 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2489 Register function, |
| 2516 ? CALL_AS_FUNCTION | 2490 Label* miss) { |
| 2517 : CALL_AS_METHOD; | 2491 // Check that the function really is a function. |
| 2518 ParameterCount expected(function); | 2492 GenerateFunctionCheck(function, rbx, miss); |
| 2519 __ InvokeFunction(function, expected, arguments(), | 2493 |
| 2520 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2494 if (!function.is(rdi)) __ movq(rdi, function); |
| 2495 PatchGlobalProxy(object); |
| 2496 |
| 2497 // Invoke the function. |
| 2498 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2499 NullCallWrapper(), call_kind()); |
| 2521 } | 2500 } |
| 2522 | 2501 |
| 2523 | 2502 |
| 2524 Handle<Code> CallStubCompiler::CompileCallConstant( | |
| 2525 Handle<Object> object, | |
| 2526 Handle<JSObject> holder, | |
| 2527 Handle<Name> name, | |
| 2528 CheckType check, | |
| 2529 Handle<JSFunction> function) { | |
| 2530 if (HasCustomCallGenerator(function)) { | |
| 2531 Handle<Code> code = CompileCustomCall(object, holder, | |
| 2532 Handle<PropertyCell>::null(), | |
| 2533 function, Handle<String>::cast(name), | |
| 2534 Code::FAST); | |
| 2535 // A null handle means bail out to the regular compiler code below. | |
| 2536 if (!code.is_null()) return code; | |
| 2537 } | |
| 2538 | |
| 2539 Label miss; | |
| 2540 HandlerFrontendHeader(object, holder, name, check, &miss); | |
| 2541 PatchGlobalProxy(object); | |
| 2542 CompileHandlerBackend(function); | |
| 2543 HandlerFrontendFooter(&miss); | |
| 2544 | |
| 2545 // Return the generated code. | |
| 2546 return GetCode(function); | |
| 2547 } | |
| 2548 | |
| 2549 | |
| 2550 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2503 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2551 Handle<JSObject> holder, | 2504 Handle<JSObject> holder, |
| 2552 Handle<Name> name) { | 2505 Handle<Name> name) { |
| 2553 Label miss; | 2506 Label miss; |
| 2554 GenerateNameCheck(name, &miss); | 2507 GenerateNameCheck(name, &miss); |
| 2555 | 2508 |
| 2556 LookupResult lookup(isolate()); | 2509 LookupResult lookup(isolate()); |
| 2557 LookupPostInterceptor(holder, name, &lookup); | 2510 LookupPostInterceptor(holder, name, &lookup); |
| 2558 | 2511 |
| 2559 // Get the receiver from the stack. | 2512 // Get the receiver from the stack. |
| 2560 StackArgumentsAccessor args(rsp, arguments()); | 2513 StackArgumentsAccessor args(rsp, arguments()); |
| 2561 __ movq(rdx, args.GetReceiverOperand()); | 2514 __ movq(rdx, args.GetReceiverOperand()); |
| 2562 | 2515 |
| 2563 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); | 2516 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); |
| 2564 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, | 2517 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, |
| 2565 &miss); | 2518 &miss); |
| 2566 | 2519 |
| 2567 // Restore receiver. | 2520 // Restore receiver. |
| 2568 __ movq(rdx, args.GetReceiverOperand()); | 2521 __ movq(rdx, args.GetReceiverOperand()); |
| 2569 | 2522 |
| 2570 // Check that the function really is a function. | 2523 GenerateCallFunction(object, rax, &miss); |
| 2571 __ JumpIfSmi(rax, &miss); | |
| 2572 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | |
| 2573 __ j(not_equal, &miss); | |
| 2574 | 2524 |
| 2575 // Patch the receiver on the stack with the global proxy if | 2525 HandlerFrontendFooter(&miss); |
| 2576 // necessary. | |
| 2577 if (object->IsGlobalObject()) { | |
| 2578 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 2579 __ movq(args.GetReceiverOperand(), rdx); | |
| 2580 } | |
| 2581 | |
| 2582 // Invoke the function. | |
| 2583 __ movq(rdi, rax); | |
| 2584 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 2585 ? CALL_AS_FUNCTION | |
| 2586 : CALL_AS_METHOD; | |
| 2587 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | |
| 2588 NullCallWrapper(), call_kind); | |
| 2589 | |
| 2590 // Handle load cache miss. | |
| 2591 __ bind(&miss); | |
| 2592 GenerateMissBranch(); | |
| 2593 | 2526 |
| 2594 // Return the generated code. | 2527 // Return the generated code. |
| 2595 return GetCode(Code::FAST, name); | 2528 return GetCode(Code::FAST, name); |
| 2596 } | 2529 } |
| 2597 | 2530 |
| 2598 | 2531 |
| 2599 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2532 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2600 Handle<JSObject> object, | 2533 Handle<JSObject> object, |
| 2601 Handle<GlobalObject> holder, | 2534 Handle<GlobalObject> holder, |
| 2602 Handle<PropertyCell> cell, | 2535 Handle<PropertyCell> cell, |
| 2603 Handle<JSFunction> function, | 2536 Handle<JSFunction> function, |
| 2604 Handle<Name> name) { | 2537 Handle<Name> name) { |
| 2605 if (HasCustomCallGenerator(function)) { | 2538 if (HasCustomCallGenerator(function)) { |
| 2606 Handle<Code> code = CompileCustomCall( | 2539 Handle<Code> code = CompileCustomCall( |
| 2607 object, holder, cell, function, Handle<String>::cast(name), | 2540 object, holder, cell, function, Handle<String>::cast(name), |
| 2608 Code::NORMAL); | 2541 Code::NORMAL); |
| 2609 // A null handle means bail out to the regular compiler code below. | 2542 // A null handle means bail out to the regular compiler code below. |
| 2610 if (!code.is_null()) return code; | 2543 if (!code.is_null()) return code; |
| 2611 } | 2544 } |
| 2612 | 2545 |
| 2613 Label miss; | 2546 Label miss; |
| 2614 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); | 2547 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2548 // Potentially loads a closure that matches the shared function info of the |
| 2549 // function, rather than function. |
| 2615 GenerateLoadFunctionFromCell(cell, function, &miss); | 2550 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2616 PatchGlobalProxy(object); | |
| 2617 | |
| 2618 // Set up the context (function already in rdi). | |
| 2619 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | |
| 2620 | |
| 2621 // Jump to the cached code (tail call). | |
| 2622 Counters* counters = isolate()->counters(); | 2551 Counters* counters = isolate()->counters(); |
| 2623 __ IncrementCounter(counters->call_global_inline(), 1); | 2552 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2624 ParameterCount expected(function->shared()->formal_parameter_count()); | 2553 GenerateCallFunction(object, rdi, function); |
| 2625 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | |
| 2626 ? CALL_AS_FUNCTION | |
| 2627 : CALL_AS_METHOD; | |
| 2628 // We call indirectly through the code field in the function to | |
| 2629 // allow recompilation to take effect without changing any of the | |
| 2630 // call sites. | |
| 2631 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | |
| 2632 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, | |
| 2633 NullCallWrapper(), call_kind); | |
| 2634 | |
| 2635 HandlerFrontendFooter(&miss); | 2554 HandlerFrontendFooter(&miss); |
| 2636 | 2555 |
| 2637 // Return the generated code. | 2556 // Return the generated code. |
| 2638 return GetCode(Code::NORMAL, name); | 2557 return GetCode(Code::NORMAL, name); |
| 2639 } | 2558 } |
| 2640 | 2559 |
| 2641 | 2560 |
| 2642 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2561 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2643 Handle<JSObject> object, | 2562 Handle<JSObject> object, |
| 2644 Handle<JSObject> holder, | 2563 Handle<JSObject> holder, |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3009 // ----------------------------------- | 2928 // ----------------------------------- |
| 3010 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2929 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3011 } | 2930 } |
| 3012 | 2931 |
| 3013 | 2932 |
| 3014 #undef __ | 2933 #undef __ |
| 3015 | 2934 |
| 3016 } } // namespace v8::internal | 2935 } } // namespace v8::internal |
| 3017 | 2936 |
| 3018 #endif // V8_TARGET_ARCH_X64 | 2937 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |