| 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 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 Register scratch2, | 563 Register scratch2, |
| 564 Register scratch3, | 564 Register scratch3, |
| 565 Handle<JSObject> interceptor_holder, | 565 Handle<JSObject> interceptor_holder, |
| 566 LookupResult* lookup, | 566 LookupResult* lookup, |
| 567 Handle<String> name, | 567 Handle<String> name, |
| 568 const CallOptimization& optimization, | 568 const CallOptimization& optimization, |
| 569 Label* miss_label) { | 569 Label* miss_label) { |
| 570 ASSERT(optimization.is_constant_call()); | 570 ASSERT(optimization.is_constant_call()); |
| 571 ASSERT(!lookup->holder()->IsGlobalObject()); | 571 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 572 | 572 |
| 573 int depth1 = kInvalidProtoDepth; | 573 bool can_do_fast_api_call = !lookup->holder()->IsGlobalObject() && |
| 574 int depth2 = kInvalidProtoDepth; | 574 optimization.is_simple_api_call() && |
| 575 bool can_do_fast_api_call = false; | 575 optimization.IsCompatibleReceiver(object); |
| 576 if (optimization.is_simple_api_call() && | |
| 577 !lookup->holder()->IsGlobalObject()) { | |
| 578 depth1 = optimization.GetPrototypeDepthOfExpectedType( | |
| 579 object, interceptor_holder); | |
| 580 if (depth1 == kInvalidProtoDepth) { | |
| 581 depth2 = optimization.GetPrototypeDepthOfExpectedType( | |
| 582 interceptor_holder, Handle<JSObject>(lookup->holder())); | |
| 583 } | |
| 584 can_do_fast_api_call = | |
| 585 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; | |
| 586 } | |
| 587 | 576 |
| 588 Counters* counters = masm->isolate()->counters(); | 577 Counters* counters = masm->isolate()->counters(); |
| 589 __ IncrementCounter(counters->call_const_interceptor(), 1); | 578 __ IncrementCounter(counters->call_const_interceptor(), 1); |
| 590 | 579 |
| 591 if (can_do_fast_api_call) { | 580 if (can_do_fast_api_call) { |
| 592 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); | 581 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); |
| 593 ReserveSpaceForFastApiCall(masm, scratch1); | 582 ReserveSpaceForFastApiCall(masm, scratch1); |
| 594 } | 583 } |
| 595 | 584 |
| 596 // Check that the maps from receiver to interceptor's holder | 585 // Check that the maps from receiver to interceptor's holder |
| 597 // haven't changed and thus we can invoke interceptor. | 586 // haven't changed and thus we can invoke interceptor. |
| 598 Label miss_cleanup; | 587 Label miss_cleanup; |
| 599 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 588 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 589 int depth = can_do_fast_api_call ? 0 : kInvalidProtoDepth; |
| 600 Register holder = | 590 Register holder = |
| 601 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 591 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
| 602 scratch1, scratch2, scratch3, | 592 scratch1, scratch2, scratch3, |
| 603 name, depth1, miss); | 593 name, depth, miss); |
| 604 | 594 |
| 605 // Invoke an interceptor and if it provides a value, | 595 // Invoke an interceptor and if it provides a value, |
| 606 // branch to |regular_invoke|. | 596 // branch to |regular_invoke|. |
| 607 Label regular_invoke; | 597 Label regular_invoke; |
| 608 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 598 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
| 609 ®ular_invoke); | 599 ®ular_invoke); |
| 610 | 600 |
| 611 // Interceptor returned nothing for this property. Try to use cached | 601 // Interceptor returned nothing for this property. Try to use cached |
| 612 // constant function. | 602 // constant function. |
| 613 | 603 |
| 614 // Check that the maps from interceptor's holder to constant function's | 604 // Check that the maps from interceptor's holder to constant function's |
| 615 // holder haven't changed and thus we can use cached constant function. | 605 // holder haven't changed and thus we can use cached constant function. |
| 606 // TODO(2268): Switch to return holder once embedders have adapted. |
| 616 if (*interceptor_holder != lookup->holder()) { | 607 if (*interceptor_holder != lookup->holder()) { |
| 617 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 608 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
| 618 Handle<JSObject>(lookup->holder()), | 609 Handle<JSObject>(lookup->holder()), |
| 619 scratch1, scratch2, scratch3, | 610 scratch1, scratch2, scratch3, |
| 620 name, depth2, miss); | 611 name, kInvalidProtoDepth, miss); |
| 621 } else { | |
| 622 // CheckPrototypes has a side effect of fetching a 'holder' | |
| 623 // for API (object which is instanceof for the signature). It's | |
| 624 // safe to omit it here, as if present, it should be fetched | |
| 625 // by the previous CheckPrototypes. | |
| 626 ASSERT(depth2 == kInvalidProtoDepth); | |
| 627 } | 612 } |
| 628 | 613 |
| 629 // Invoke function. | 614 // Invoke function. |
| 630 if (can_do_fast_api_call) { | 615 if (can_do_fast_api_call) { |
| 631 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 616 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| 632 } else { | 617 } else { |
| 633 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 618 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 634 ? CALL_AS_FUNCTION | 619 ? CALL_AS_FUNCTION |
| 635 : CALL_AS_METHOD; | 620 : CALL_AS_METHOD; |
| 636 __ InvokeFunction(optimization.constant_function(), arguments_, | 621 __ InvokeFunction(optimization.constant_function(), arguments_, |
| (...skipping 1488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2125 Handle<JSObject> holder, | 2110 Handle<JSObject> holder, |
| 2126 Handle<JSGlobalPropertyCell> cell, | 2111 Handle<JSGlobalPropertyCell> cell, |
| 2127 Handle<JSFunction> function, | 2112 Handle<JSFunction> function, |
| 2128 Handle<String> name) { | 2113 Handle<String> name) { |
| 2129 ASSERT(optimization.is_simple_api_call()); | 2114 ASSERT(optimization.is_simple_api_call()); |
| 2130 // Bail out if object is a global object as we don't want to | 2115 // Bail out if object is a global object as we don't want to |
| 2131 // repatch it to global receiver. | 2116 // repatch it to global receiver. |
| 2132 if (object->IsGlobalObject()) return Handle<Code>::null(); | 2117 if (object->IsGlobalObject()) return Handle<Code>::null(); |
| 2133 if (!cell.is_null()) return Handle<Code>::null(); | 2118 if (!cell.is_null()) return Handle<Code>::null(); |
| 2134 if (!object->IsJSObject()) return Handle<Code>::null(); | 2119 if (!object->IsJSObject()) return Handle<Code>::null(); |
| 2135 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2120 if (!optimization.IsCompatibleReceiver(object)) return Handle<Code>::null(); |
| 2136 Handle<JSObject>::cast(object), holder); | |
| 2137 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); | |
| 2138 | 2121 |
| 2139 Label miss, miss_before_stack_reserved; | 2122 Label miss, miss_before_stack_reserved; |
| 2140 GenerateNameCheck(name, &miss_before_stack_reserved); | 2123 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2141 | 2124 |
| 2142 // Get the receiver from the stack. | 2125 // Get the receiver from the stack. |
| 2143 const int argc = arguments().immediate(); | 2126 const int argc = arguments().immediate(); |
| 2144 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2127 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2145 | 2128 |
| 2146 // Check that the receiver isn't a smi. | 2129 // Check that the receiver isn't a smi. |
| 2147 __ JumpIfSmi(rdx, &miss_before_stack_reserved); | 2130 __ JumpIfSmi(rdx, &miss_before_stack_reserved); |
| 2148 | 2131 |
| 2149 Counters* counters = isolate()->counters(); | 2132 Counters* counters = isolate()->counters(); |
| 2150 __ IncrementCounter(counters->call_const(), 1); | 2133 __ IncrementCounter(counters->call_const(), 1); |
| 2151 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2134 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2152 | 2135 |
| 2153 // Allocate space for v8::Arguments implicit values. Must be initialized | 2136 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2154 // before calling any runtime function. | 2137 // before calling any runtime function. |
| 2155 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2138 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2156 | 2139 |
| 2157 // Check that the maps haven't changed and find a Holder as a side effect. | 2140 // Check that the maps haven't changed and find holder as a side effect. |
| 2141 // TODO(2268): Switch to return holder once embedders have adapted. |
| 2158 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2142 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2159 name, depth, &miss); | 2143 name, 0, &miss); |
| 2160 | 2144 |
| 2161 // Move the return address on top of the stack. | 2145 // Move the return address on top of the stack. |
| 2162 __ movq(rax, Operand(rsp, 4 * kPointerSize)); | 2146 __ movq(rax, Operand(rsp, 4 * kPointerSize)); |
| 2163 __ movq(Operand(rsp, 0 * kPointerSize), rax); | 2147 __ movq(Operand(rsp, 0 * kPointerSize), rax); |
| 2164 | 2148 |
| 2165 GenerateFastApiCall(masm(), optimization, argc); | 2149 GenerateFastApiCall(masm(), optimization, argc); |
| 2166 | 2150 |
| 2167 __ bind(&miss); | 2151 __ bind(&miss); |
| 2168 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2152 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2169 | 2153 |
| (...skipping 1966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4136 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4120 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
| 4137 } | 4121 } |
| 4138 } | 4122 } |
| 4139 | 4123 |
| 4140 | 4124 |
| 4141 #undef __ | 4125 #undef __ |
| 4142 | 4126 |
| 4143 } } // namespace v8::internal | 4127 } } // namespace v8::internal |
| 4144 | 4128 |
| 4145 #endif // V8_TARGET_ARCH_X64 | 4129 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |