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 |