OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
142 &done, | 142 &done, |
143 receiver, | 143 receiver, |
144 properties, | 144 properties, |
145 name, | 145 name, |
146 scratch1); | 146 scratch1); |
147 __ bind(&done); | 147 __ bind(&done); |
148 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 148 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
149 } | 149 } |
150 | 150 |
151 | 151 |
152 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
153 // handlified. | |
154 MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup( | |
155 MacroAssembler* masm, | |
156 Label* miss_label, | |
157 Register receiver, | |
158 String* name, | |
159 Register scratch0, | |
160 Register scratch1) { | |
161 ASSERT(name->IsSymbol()); | |
162 Counters* counters = masm->isolate()->counters(); | |
163 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | |
164 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | |
165 | |
166 Label done; | |
167 | |
168 const int kInterceptorOrAccessCheckNeededMask = | |
169 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | |
170 | |
171 // Bail out if the receiver has a named interceptor or requires access checks. | |
172 Register map = scratch1; | |
173 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | |
174 __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); | |
175 __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); | |
176 __ b(ne, miss_label); | |
177 | |
178 // Check that receiver is a JSObject. | |
179 __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); | |
180 __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); | |
181 __ b(lt, miss_label); | |
182 | |
183 // Load properties array. | |
184 Register properties = scratch0; | |
185 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
186 // Check that the properties array is a dictionary. | |
187 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); | |
188 Register tmp = properties; | |
189 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); | |
190 __ cmp(map, tmp); | |
191 __ b(ne, miss_label); | |
192 | |
193 // Restore the temporarily used register. | |
194 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
195 | |
196 | |
197 MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup( | |
198 masm, | |
199 miss_label, | |
200 &done, | |
201 receiver, | |
202 properties, | |
203 name, | |
204 scratch1); | |
205 if (result->IsFailure()) return result; | |
206 | |
207 __ bind(&done); | |
208 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | |
209 | |
210 return result; | |
211 } | |
212 | |
213 | |
214 void StubCache::GenerateProbe(MacroAssembler* masm, | 152 void StubCache::GenerateProbe(MacroAssembler* masm, |
215 Code::Flags flags, | 153 Code::Flags flags, |
216 Register receiver, | 154 Register receiver, |
217 Register name, | 155 Register name, |
218 Register scratch, | 156 Register scratch, |
219 Register extra, | 157 Register extra, |
220 Register extra2) { | 158 Register extra2) { |
221 Isolate* isolate = masm->isolate(); | 159 Isolate* isolate = masm->isolate(); |
222 Label miss; | 160 Label miss; |
223 | 161 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
287 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index))); | 225 __ ldr(prototype, MemOperand(prototype, Context::SlotOffset(index))); |
288 // Load the initial map. The global functions all have initial maps. | 226 // Load the initial map. The global functions all have initial maps. |
289 __ ldr(prototype, | 227 __ ldr(prototype, |
290 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); | 228 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); |
291 // Load the prototype from the initial map. | 229 // Load the prototype from the initial map. |
292 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 230 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
293 } | 231 } |
294 | 232 |
295 | 233 |
296 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 234 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
297 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 235 MacroAssembler* masm, |
236 int index, | |
237 Register prototype, | |
238 Label* miss) { | |
298 Isolate* isolate = masm->isolate(); | 239 Isolate* isolate = masm->isolate(); |
299 // Check we're still in the same context. | 240 // Check we're still in the same context. |
300 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); | 241 __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
301 __ Move(ip, isolate->global()); | 242 __ Move(ip, isolate->global()); |
302 __ cmp(prototype, ip); | 243 __ cmp(prototype, ip); |
303 __ b(ne, miss); | 244 __ b(ne, miss); |
304 // Get the global function with the given index. | 245 // Get the global function with the given index. |
305 JSFunction* function = | 246 Handle<JSFunction> function( |
306 JSFunction::cast(isolate->global_context()->get(index)); | 247 JSFunction::cast(isolate->global_context()->get(index))); |
307 // Load its initial map. The global functions all have initial maps. | 248 // Load its initial map. The global functions all have initial maps. |
308 __ Move(prototype, Handle<Map>(function->initial_map())); | 249 __ Move(prototype, Handle<Map>(function->initial_map())); |
309 // Load the prototype from the initial map. | 250 // Load the prototype from the initial map. |
310 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 251 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
311 } | 252 } |
312 | 253 |
313 | 254 |
314 // Load a fast property out of a holder object (src). In-object properties | 255 // Load a fast property out of a holder object (src). In-object properties |
315 // are loaded directly otherwise the property is loaded from the properties | 256 // are loaded directly otherwise the property is loaded from the properties |
316 // fixed array. | 257 // fixed array. |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
559 ? CALL_AS_FUNCTION | 500 ? CALL_AS_FUNCTION |
560 : CALL_AS_METHOD; | 501 : CALL_AS_METHOD; |
561 __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | 502 __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
562 } | 503 } |
563 | 504 |
564 | 505 |
565 static void PushInterceptorArguments(MacroAssembler* masm, | 506 static void PushInterceptorArguments(MacroAssembler* masm, |
566 Register receiver, | 507 Register receiver, |
567 Register holder, | 508 Register holder, |
568 Register name, | 509 Register name, |
569 JSObject* holder_obj) { | 510 Handle<JSObject> holder_obj) { |
570 __ push(name); | 511 __ push(name); |
571 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 512 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
572 ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor)); | 513 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
573 Register scratch = name; | 514 Register scratch = name; |
574 __ mov(scratch, Operand(Handle<Object>(interceptor))); | 515 __ mov(scratch, Operand(interceptor)); |
575 __ push(scratch); | 516 __ push(scratch); |
576 __ push(receiver); | 517 __ push(receiver); |
577 __ push(holder); | 518 __ push(holder); |
578 __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); | 519 __ ldr(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); |
579 __ push(scratch); | 520 __ push(scratch); |
580 } | 521 } |
581 | 522 |
582 | 523 |
583 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 524 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
584 Register receiver, | 525 Register receiver, |
585 Register holder, | 526 Register holder, |
586 Register name, | 527 Register name, |
587 JSObject* holder_obj) { | 528 Handle<JSObject> holder_obj) { |
588 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 529 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
589 | 530 |
590 ExternalReference ref = | 531 ExternalReference ref = |
591 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 532 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
592 masm->isolate()); | 533 masm->isolate()); |
593 __ mov(r0, Operand(5)); | 534 __ mov(r0, Operand(5)); |
594 __ mov(r1, Operand(ref)); | 535 __ mov(r1, Operand(ref)); |
595 | 536 |
596 CEntryStub stub(1); | 537 CEntryStub stub(1); |
597 __ CallStub(&stub); | 538 __ CallStub(&stub); |
598 } | 539 } |
599 | 540 |
541 | |
600 static const int kFastApiCallArguments = 3; | 542 static const int kFastApiCallArguments = 3; |
601 | 543 |
602 // Reserves space for the extra arguments to FastHandleApiCall in the | 544 // Reserves space for the extra arguments to FastHandleApiCall in the |
603 // caller's frame. | 545 // caller's frame. |
604 // | 546 // |
605 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. | 547 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. |
606 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, | 548 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |
607 Register scratch) { | 549 Register scratch) { |
608 __ mov(scratch, Operand(Smi::FromInt(0))); | 550 __ mov(scratch, Operand(Smi::FromInt(0))); |
609 for (int i = 0; i < kFastApiCallArguments; i++) { | 551 for (int i = 0; i < kFastApiCallArguments; i++) { |
610 __ push(scratch); | 552 __ push(scratch); |
611 } | 553 } |
612 } | 554 } |
613 | 555 |
614 | 556 |
615 // Undoes the effects of ReserveSpaceForFastApiCall. | 557 // Undoes the effects of ReserveSpaceForFastApiCall. |
616 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { | 558 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |
617 __ Drop(kFastApiCallArguments); | 559 __ Drop(kFastApiCallArguments); |
618 } | 560 } |
619 | 561 |
620 | 562 |
621 static MaybeObject* GenerateFastApiDirectCall( | 563 static void GenerateFastApiDirectCall(MacroAssembler* masm, |
622 MacroAssembler* masm, | 564 const CallOptimization& optimization, |
623 const CallOptimization& optimization, | 565 int argc) { |
624 int argc) { | |
625 // ----------- S t a t e ------------- | 566 // ----------- S t a t e ------------- |
626 // -- sp[0] : holder (set by CheckPrototypes) | 567 // -- sp[0] : holder (set by CheckPrototypes) |
627 // -- sp[4] : callee js function | 568 // -- sp[4] : callee js function |
628 // -- sp[8] : call data | 569 // -- sp[8] : call data |
629 // -- sp[12] : last js argument | 570 // -- sp[12] : last js argument |
630 // -- ... | 571 // -- ... |
631 // -- sp[(argc + 3) * 4] : first js argument | 572 // -- sp[(argc + 3) * 4] : first js argument |
632 // -- sp[(argc + 4) * 4] : receiver | 573 // -- sp[(argc + 4) * 4] : receiver |
633 // ----------------------------------- | 574 // ----------------------------------- |
634 // Get the function and setup the context. | 575 // Get the function and setup the context. |
635 JSFunction* function = optimization.constant_function(); | 576 Handle<JSFunction> function = optimization.constant_function(); |
636 __ mov(r5, Operand(Handle<JSFunction>(function))); | 577 __ mov(r5, Operand(function)); |
637 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); | 578 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); |
638 | 579 |
639 // Pass the additional arguments FastHandleApiCall expects. | 580 // Pass the additional arguments FastHandleApiCall expects. |
640 Object* call_data = optimization.api_call_info()->data(); | 581 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
641 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); | 582 Handle<Object> call_data(api_call_info->data()); |
642 if (masm->isolate()->heap()->InNewSpace(call_data)) { | 583 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
643 __ Move(r0, api_call_info_handle); | 584 __ Move(r0, api_call_info); |
644 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); | 585 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); |
645 } else { | 586 } else { |
646 __ Move(r6, Handle<Object>(call_data)); | 587 __ Move(r6, call_data); |
647 } | 588 } |
648 // Store js function and call data. | 589 // Store js function and call data. |
649 __ stm(ib, sp, r5.bit() | r6.bit()); | 590 __ stm(ib, sp, r5.bit() | r6.bit()); |
650 | 591 |
651 // r2 points to call data as expected by Arguments | 592 // r2 points to call data as expected by Arguments |
652 // (refer to layout above). | 593 // (refer to layout above). |
653 __ add(r2, sp, Operand(2 * kPointerSize)); | 594 __ add(r2, sp, Operand(2 * kPointerSize)); |
654 | 595 |
655 Object* callback = optimization.api_call_info()->callback(); | |
656 Address api_function_address = v8::ToCData<Address>(callback); | |
657 ApiFunction fun(api_function_address); | |
658 | |
659 const int kApiStackSpace = 4; | 596 const int kApiStackSpace = 4; |
660 | 597 |
661 FrameScope frame_scope(masm, StackFrame::MANUAL); | 598 FrameScope frame_scope(masm, StackFrame::MANUAL); |
662 __ EnterExitFrame(false, kApiStackSpace); | 599 __ EnterExitFrame(false, kApiStackSpace); |
663 | 600 |
664 // r0 = v8::Arguments& | 601 // r0 = v8::Arguments& |
665 // Arguments is after the return address. | 602 // Arguments is after the return address. |
666 __ add(r0, sp, Operand(1 * kPointerSize)); | 603 __ add(r0, sp, Operand(1 * kPointerSize)); |
667 // v8::Arguments::implicit_args = data | 604 // v8::Arguments::implicit_args = data |
668 __ str(r2, MemOperand(r0, 0 * kPointerSize)); | 605 __ str(r2, MemOperand(r0, 0 * kPointerSize)); |
669 // v8::Arguments::values = last argument | 606 // v8::Arguments::values = last argument |
670 __ add(ip, r2, Operand(argc * kPointerSize)); | 607 __ add(ip, r2, Operand(argc * kPointerSize)); |
671 __ str(ip, MemOperand(r0, 1 * kPointerSize)); | 608 __ str(ip, MemOperand(r0, 1 * kPointerSize)); |
672 // v8::Arguments::length_ = argc | 609 // v8::Arguments::length_ = argc |
673 __ mov(ip, Operand(argc)); | 610 __ mov(ip, Operand(argc)); |
674 __ str(ip, MemOperand(r0, 2 * kPointerSize)); | 611 __ str(ip, MemOperand(r0, 2 * kPointerSize)); |
675 // v8::Arguments::is_construct_call = 0 | 612 // v8::Arguments::is_construct_call = 0 |
676 __ mov(ip, Operand(0)); | 613 __ mov(ip, Operand(0)); |
677 __ str(ip, MemOperand(r0, 3 * kPointerSize)); | 614 __ str(ip, MemOperand(r0, 3 * kPointerSize)); |
678 | 615 |
679 // Emitting a stub call may try to allocate (if the code is not | |
680 // already generated). Do not allow the assembler to perform a | |
681 // garbage collection but instead return the allocation failure | |
682 // object. | |
683 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; | 616 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; |
617 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | |
618 ApiFunction fun(function_address); | |
684 ExternalReference ref = ExternalReference(&fun, | 619 ExternalReference ref = ExternalReference(&fun, |
685 ExternalReference::DIRECT_API_CALL, | 620 ExternalReference::DIRECT_API_CALL, |
686 masm->isolate()); | 621 masm->isolate()); |
687 AllowExternalCallThatCantCauseGC scope(masm); | 622 AllowExternalCallThatCantCauseGC scope(masm); |
688 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); | 623 |
624 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); | |
689 } | 625 } |
690 | 626 |
691 | 627 |
692 class CallInterceptorCompiler BASE_EMBEDDED { | 628 class CallInterceptorCompiler BASE_EMBEDDED { |
693 public: | 629 public: |
694 CallInterceptorCompiler(StubCompiler* stub_compiler, | 630 CallInterceptorCompiler(StubCompiler* stub_compiler, |
695 const ParameterCount& arguments, | 631 const ParameterCount& arguments, |
696 Register name, | 632 Register name, |
697 Code::ExtraICState extra_ic_state) | 633 Code::ExtraICState extra_ic_state) |
698 : stub_compiler_(stub_compiler), | 634 : stub_compiler_(stub_compiler), |
699 arguments_(arguments), | 635 arguments_(arguments), |
700 name_(name), | 636 name_(name), |
701 extra_ic_state_(extra_ic_state) {} | 637 extra_ic_state_(extra_ic_state) {} |
702 | 638 |
703 MaybeObject* Compile(MacroAssembler* masm, | 639 void Compile(MacroAssembler* masm, |
704 JSObject* object, | 640 Handle<JSObject> object, |
705 JSObject* holder, | 641 Handle<JSObject> holder, |
706 String* name, | 642 Handle<String> name, |
707 LookupResult* lookup, | 643 LookupResult* lookup, |
708 Register receiver, | 644 Register receiver, |
709 Register scratch1, | 645 Register scratch1, |
710 Register scratch2, | 646 Register scratch2, |
711 Register scratch3, | 647 Register scratch3, |
712 Label* miss) { | 648 Label* miss) { |
713 ASSERT(holder->HasNamedInterceptor()); | 649 ASSERT(holder->HasNamedInterceptor()); |
714 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 650 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
715 | 651 |
716 // Check that the receiver isn't a smi. | 652 // Check that the receiver isn't a smi. |
717 __ JumpIfSmi(receiver, miss); | 653 __ JumpIfSmi(receiver, miss); |
718 | |
719 CallOptimization optimization(lookup); | 654 CallOptimization optimization(lookup); |
720 | |
721 if (optimization.is_constant_call()) { | 655 if (optimization.is_constant_call()) { |
722 return CompileCacheable(masm, | 656 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, |
723 object, | 657 holder, lookup, name, optimization, miss); |
724 receiver, | |
725 scratch1, | |
726 scratch2, | |
727 scratch3, | |
728 holder, | |
729 lookup, | |
730 name, | |
731 optimization, | |
732 miss); | |
733 } else { | 658 } else { |
734 CompileRegular(masm, | 659 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, |
735 object, | 660 name, holder, miss); |
736 receiver, | |
737 scratch1, | |
738 scratch2, | |
739 scratch3, | |
740 name, | |
741 holder, | |
742 miss); | |
743 return masm->isolate()->heap()->undefined_value(); | |
744 } | 661 } |
745 } | 662 } |
746 | 663 |
747 private: | 664 private: |
748 MaybeObject* CompileCacheable(MacroAssembler* masm, | 665 void CompileCacheable(MacroAssembler* masm, |
749 JSObject* object, | 666 Handle<JSObject> object, |
750 Register receiver, | 667 Register receiver, |
751 Register scratch1, | 668 Register scratch1, |
752 Register scratch2, | 669 Register scratch2, |
753 Register scratch3, | 670 Register scratch3, |
754 JSObject* interceptor_holder, | 671 Handle<JSObject> interceptor_holder, |
755 LookupResult* lookup, | 672 LookupResult* lookup, |
756 String* name, | 673 Handle<String> name, |
757 const CallOptimization& optimization, | 674 const CallOptimization& optimization, |
758 Label* miss_label) { | 675 Label* miss_label) { |
759 ASSERT(optimization.is_constant_call()); | 676 ASSERT(optimization.is_constant_call()); |
760 ASSERT(!lookup->holder()->IsGlobalObject()); | 677 ASSERT(!lookup->holder()->IsGlobalObject()); |
761 | |
762 Counters* counters = masm->isolate()->counters(); | 678 Counters* counters = masm->isolate()->counters(); |
763 | |
764 int depth1 = kInvalidProtoDepth; | 679 int depth1 = kInvalidProtoDepth; |
765 int depth2 = kInvalidProtoDepth; | 680 int depth2 = kInvalidProtoDepth; |
766 bool can_do_fast_api_call = false; | 681 bool can_do_fast_api_call = false; |
767 if (optimization.is_simple_api_call() && | 682 if (optimization.is_simple_api_call() && |
768 !lookup->holder()->IsGlobalObject()) { | 683 !lookup->holder()->IsGlobalObject()) { |
769 depth1 = | 684 depth1 = optimization.GetPrototypeDepthOfExpectedType( |
770 optimization.GetPrototypeDepthOfExpectedType(object, | 685 object, interceptor_holder); |
771 interceptor_holder); | 686 if (depth1 == kInvalidProtoDepth) { |
772 if (depth1 == kInvalidProtoDepth) { | 687 depth2 = optimization.GetPrototypeDepthOfExpectedType( |
773 depth2 = | 688 interceptor_holder, Handle<JSObject>(lookup->holder())); |
774 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, | 689 } |
775 lookup->holder()); | 690 can_do_fast_api_call = |
776 } | 691 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; |
777 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || | |
778 (depth2 != kInvalidProtoDepth); | |
779 } | 692 } |
780 | 693 |
781 __ IncrementCounter(counters->call_const_interceptor(), 1, | 694 __ IncrementCounter(counters->call_const_interceptor(), 1, |
782 scratch1, scratch2); | 695 scratch1, scratch2); |
783 | 696 |
784 if (can_do_fast_api_call) { | 697 if (can_do_fast_api_call) { |
785 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, | 698 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, |
786 scratch1, scratch2); | 699 scratch1, scratch2); |
787 ReserveSpaceForFastApiCall(masm, scratch1); | 700 ReserveSpaceForFastApiCall(masm, scratch1); |
788 } | 701 } |
789 | 702 |
790 // Check that the maps from receiver to interceptor's holder | 703 // Check that the maps from receiver to interceptor's holder |
791 // haven't changed and thus we can invoke interceptor. | 704 // haven't changed and thus we can invoke interceptor. |
792 Label miss_cleanup; | 705 Label miss_cleanup; |
793 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 706 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
794 Register holder = | 707 Register holder = |
795 stub_compiler_->CheckPrototypes(object, receiver, | 708 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
796 interceptor_holder, scratch1, | 709 scratch1, scratch2, scratch3, |
797 scratch2, scratch3, name, depth1, miss); | 710 name, depth1, miss); |
798 | 711 |
799 // Invoke an interceptor and if it provides a value, | 712 // Invoke an interceptor and if it provides a value, |
800 // branch to |regular_invoke|. | 713 // branch to |regular_invoke|. |
801 Label regular_invoke; | 714 Label regular_invoke; |
802 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | 715 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, |
803 ®ular_invoke); | 716 ®ular_invoke); |
804 | 717 |
805 // Interceptor returned nothing for this property. Try to use cached | 718 // Interceptor returned nothing for this property. Try to use cached |
806 // constant function. | 719 // constant function. |
807 | 720 |
808 // Check that the maps from interceptor's holder to constant function's | 721 // Check that the maps from interceptor's holder to constant function's |
809 // holder haven't changed and thus we can use cached constant function. | 722 // holder haven't changed and thus we can use cached constant function. |
810 if (interceptor_holder != lookup->holder()) { | 723 if (*interceptor_holder != lookup->holder()) { |
811 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 724 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
812 lookup->holder(), scratch1, | 725 Handle<JSObject>(lookup->holder()), |
813 scratch2, scratch3, name, depth2, miss); | 726 scratch1, scratch2, scratch3, |
727 name, depth2, miss); | |
814 } else { | 728 } else { |
815 // CheckPrototypes has a side effect of fetching a 'holder' | 729 // CheckPrototypes has a side effect of fetching a 'holder' |
816 // for API (object which is instanceof for the signature). It's | 730 // for API (object which is instanceof for the signature). It's |
817 // safe to omit it here, as if present, it should be fetched | 731 // safe to omit it here, as if present, it should be fetched |
818 // by the previous CheckPrototypes. | 732 // by the previous CheckPrototypes. |
819 ASSERT(depth2 == kInvalidProtoDepth); | 733 ASSERT(depth2 == kInvalidProtoDepth); |
820 } | 734 } |
821 | 735 |
822 // Invoke function. | 736 // Invoke function. |
823 if (can_do_fast_api_call) { | 737 if (can_do_fast_api_call) { |
824 MaybeObject* result = GenerateFastApiDirectCall(masm, | 738 GenerateFastApiDirectCall(masm, optimization, arguments_.immediate()); |
825 optimization, | |
826 arguments_.immediate()); | |
827 if (result->IsFailure()) return result; | |
828 } else { | 739 } else { |
829 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 740 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
830 ? CALL_AS_FUNCTION | 741 ? CALL_AS_FUNCTION |
831 : CALL_AS_METHOD; | 742 : CALL_AS_METHOD; |
832 __ InvokeFunction(optimization.constant_function(), arguments_, | 743 __ InvokeFunction(optimization.constant_function(), arguments_, |
833 JUMP_FUNCTION, call_kind); | 744 JUMP_FUNCTION, call_kind); |
834 } | 745 } |
835 | 746 |
836 // Deferred code for fast API call case---clean preallocated space. | 747 // Deferred code for fast API call case---clean preallocated space. |
837 if (can_do_fast_api_call) { | 748 if (can_do_fast_api_call) { |
838 __ bind(&miss_cleanup); | 749 __ bind(&miss_cleanup); |
839 FreeSpaceForFastApiCall(masm); | 750 FreeSpaceForFastApiCall(masm); |
840 __ b(miss_label); | 751 __ b(miss_label); |
841 } | 752 } |
842 | 753 |
843 // Invoke a regular function. | 754 // Invoke a regular function. |
844 __ bind(®ular_invoke); | 755 __ bind(®ular_invoke); |
845 if (can_do_fast_api_call) { | 756 if (can_do_fast_api_call) { |
846 FreeSpaceForFastApiCall(masm); | 757 FreeSpaceForFastApiCall(masm); |
847 } | 758 } |
848 | |
849 return masm->isolate()->heap()->undefined_value(); | |
850 } | 759 } |
851 | 760 |
852 void CompileRegular(MacroAssembler* masm, | 761 void CompileRegular(MacroAssembler* masm, |
853 JSObject* object, | 762 Handle<JSObject> object, |
854 Register receiver, | 763 Register receiver, |
855 Register scratch1, | 764 Register scratch1, |
856 Register scratch2, | 765 Register scratch2, |
857 Register scratch3, | 766 Register scratch3, |
858 String* name, | 767 Handle<String> name, |
859 JSObject* interceptor_holder, | 768 Handle<JSObject> interceptor_holder, |
860 Label* miss_label) { | 769 Label* miss_label) { |
861 Register holder = | 770 Register holder = |
862 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 771 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
863 scratch1, scratch2, scratch3, name, | 772 scratch1, scratch2, scratch3, |
864 miss_label); | 773 name, miss_label); |
865 | 774 |
866 // Call a runtime function to load the interceptor property. | 775 // Call a runtime function to load the interceptor property. |
867 FrameScope scope(masm, StackFrame::INTERNAL); | 776 FrameScope scope(masm, StackFrame::INTERNAL); |
868 // Save the name_ register across the call. | 777 // Save the name_ register across the call. |
869 __ push(name_); | 778 __ push(name_); |
870 | 779 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
871 PushInterceptorArguments(masm, | |
872 receiver, | |
873 holder, | |
874 name_, | |
875 interceptor_holder); | |
876 | |
877 __ CallExternalReference( | 780 __ CallExternalReference( |
878 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 781 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
879 masm->isolate()), | 782 masm->isolate()), |
880 5); | 783 5); |
881 | |
882 // Restore the name_ register. | 784 // Restore the name_ register. |
883 __ pop(name_); | 785 __ pop(name_); |
884 | |
885 // Leave the internal frame. | 786 // Leave the internal frame. |
886 } | 787 } |
887 | 788 |
888 void LoadWithInterceptor(MacroAssembler* masm, | 789 void LoadWithInterceptor(MacroAssembler* masm, |
889 Register receiver, | 790 Register receiver, |
890 Register holder, | 791 Register holder, |
891 JSObject* holder_obj, | 792 Handle<JSObject> holder_obj, |
892 Register scratch, | 793 Register scratch, |
893 Label* interceptor_succeeded) { | 794 Label* interceptor_succeeded) { |
894 { | 795 { |
895 FrameScope scope(masm, StackFrame::INTERNAL); | 796 FrameScope scope(masm, StackFrame::INTERNAL); |
896 __ Push(holder, name_); | 797 __ Push(holder, name_); |
897 | |
898 CompileCallLoadPropertyWithInterceptor(masm, | 798 CompileCallLoadPropertyWithInterceptor(masm, |
899 receiver, | 799 receiver, |
900 holder, | 800 holder, |
901 name_, | 801 name_, |
902 holder_obj); | 802 holder_obj); |
903 | |
904 __ pop(name_); // Restore the name. | 803 __ pop(name_); // Restore the name. |
905 __ pop(receiver); // Restore the holder. | 804 __ pop(receiver); // Restore the holder. |
906 } | 805 } |
907 | |
908 // If interceptor returns no-result sentinel, call the constant function. | 806 // If interceptor returns no-result sentinel, call the constant function. |
909 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 807 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
910 __ cmp(r0, scratch); | 808 __ cmp(r0, scratch); |
911 __ b(ne, interceptor_succeeded); | 809 __ b(ne, interceptor_succeeded); |
912 } | 810 } |
913 | 811 |
914 StubCompiler* stub_compiler_; | 812 StubCompiler* stub_compiler_; |
915 const ParameterCount& arguments_; | 813 const ParameterCount& arguments_; |
916 Register name_; | 814 Register name_; |
917 Code::ExtraICState extra_ic_state_; | 815 Code::ExtraICState extra_ic_state_; |
(...skipping 13 matching lines...) Expand all Loading... | |
931 ASSERT(cell->value()->IsTheHole()); | 829 ASSERT(cell->value()->IsTheHole()); |
932 __ mov(scratch, Operand(cell)); | 830 __ mov(scratch, Operand(cell)); |
933 __ ldr(scratch, | 831 __ ldr(scratch, |
934 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | 832 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
935 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 833 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
936 __ cmp(scratch, ip); | 834 __ cmp(scratch, ip); |
937 __ b(ne, miss); | 835 __ b(ne, miss); |
938 } | 836 } |
939 | 837 |
940 | 838 |
941 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
942 // handlified. | |
943 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( | |
944 MacroAssembler* masm, | |
945 GlobalObject* global, | |
946 String* name, | |
947 Register scratch, | |
948 Label* miss) { | |
949 Object* probe; | |
950 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | |
951 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | |
952 } | |
953 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | |
954 ASSERT(cell->value()->IsTheHole()); | |
955 __ mov(scratch, Operand(Handle<Object>(cell))); | |
956 __ ldr(scratch, | |
957 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | |
958 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | |
959 __ cmp(scratch, ip); | |
960 __ b(ne, miss); | |
961 return cell; | |
962 } | |
963 | |
964 | |
965 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 839 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
966 // from object to (but not including) holder. | 840 // from object to (but not including) holder. |
967 static void GenerateCheckPropertyCells(MacroAssembler* masm, | 841 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
968 Handle<JSObject> object, | 842 Handle<JSObject> object, |
969 Handle<JSObject> holder, | 843 Handle<JSObject> holder, |
970 Handle<String> name, | 844 Handle<String> name, |
971 Register scratch, | 845 Register scratch, |
972 Label* miss) { | 846 Label* miss) { |
973 Handle<JSObject> current = object; | 847 Handle<JSObject> current = object; |
974 while (!current.is_identical_to(holder)) { | 848 while (!current.is_identical_to(holder)) { |
975 if (current->IsGlobalObject()) { | 849 if (current->IsGlobalObject()) { |
976 GenerateCheckPropertyCell(masm, | 850 GenerateCheckPropertyCell(masm, |
977 Handle<GlobalObject>::cast(current), | 851 Handle<GlobalObject>::cast(current), |
978 name, | 852 name, |
979 scratch, | 853 scratch, |
980 miss); | 854 miss); |
981 } | 855 } |
982 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | 856 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
983 } | 857 } |
984 } | 858 } |
985 | 859 |
986 | 860 |
987 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
988 // handlified. | |
989 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( | |
990 MacroAssembler* masm, | |
991 JSObject* object, | |
992 JSObject* holder, | |
993 String* name, | |
994 Register scratch, | |
995 Label* miss) { | |
996 JSObject* current = object; | |
997 while (current != holder) { | |
998 if (current->IsGlobalObject()) { | |
999 // Returns a cell or a failure. | |
1000 MaybeObject* result = TryGenerateCheckPropertyCell( | |
1001 masm, | |
1002 GlobalObject::cast(current), | |
1003 name, | |
1004 scratch, | |
1005 miss); | |
1006 if (result->IsFailure()) return result; | |
1007 } | |
1008 ASSERT(current->IsJSObject()); | |
1009 current = JSObject::cast(current->GetPrototype()); | |
1010 } | |
1011 return NULL; | |
1012 } | |
1013 | |
1014 | |
1015 // Convert and store int passed in register ival to IEEE 754 single precision | 861 // Convert and store int passed in register ival to IEEE 754 single precision |
1016 // floating point value at memory location (dst + 4 * wordoffset) | 862 // floating point value at memory location (dst + 4 * wordoffset) |
1017 // If VFP3 is available use it for conversion. | 863 // If VFP3 is available use it for conversion. |
1018 static void StoreIntAsFloat(MacroAssembler* masm, | 864 static void StoreIntAsFloat(MacroAssembler* masm, |
1019 Register dst, | 865 Register dst, |
1020 Register wordoffset, | 866 Register wordoffset, |
1021 Register ival, | 867 Register ival, |
1022 Register fval, | 868 Register fval, |
1023 Register scratch1, | 869 Register scratch1, |
1024 Register scratch2) { | 870 Register scratch2) { |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1219 // If we've skipped any global objects, it's not enough to verify that | 1065 // If we've skipped any global objects, it's not enough to verify that |
1220 // their maps haven't changed. We also need to check that the property | 1066 // their maps haven't changed. We also need to check that the property |
1221 // cell for the property is still empty. | 1067 // cell for the property is still empty. |
1222 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1068 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
1223 | 1069 |
1224 // Return the register containing the holder. | 1070 // Return the register containing the holder. |
1225 return reg; | 1071 return reg; |
1226 } | 1072 } |
1227 | 1073 |
1228 | 1074 |
1229 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
1230 // handlified. | |
1231 Register StubCompiler::CheckPrototypes(JSObject* object, | |
1232 Register object_reg, | |
1233 JSObject* holder, | |
1234 Register holder_reg, | |
1235 Register scratch1, | |
1236 Register scratch2, | |
1237 String* name, | |
1238 int save_at_depth, | |
1239 Label* miss) { | |
1240 // Make sure there's no overlap between holder and object registers. | |
1241 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | |
1242 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | |
1243 && !scratch2.is(scratch1)); | |
1244 | |
1245 // Keep track of the current object in register reg. | |
1246 Register reg = object_reg; | |
1247 int depth = 0; | |
1248 | |
1249 if (save_at_depth == depth) { | |
1250 __ str(reg, MemOperand(sp)); | |
1251 } | |
1252 | |
1253 // Check the maps in the prototype chain. | |
1254 // Traverse the prototype chain from the object and do map checks. | |
1255 JSObject* current = object; | |
1256 while (current != holder) { | |
1257 depth++; | |
1258 | |
1259 // Only global objects and objects that do not require access | |
1260 // checks are allowed in stubs. | |
1261 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | |
1262 | |
1263 ASSERT(current->GetPrototype()->IsJSObject()); | |
1264 JSObject* prototype = JSObject::cast(current->GetPrototype()); | |
1265 if (!current->HasFastProperties() && | |
1266 !current->IsJSGlobalObject() && | |
1267 !current->IsJSGlobalProxy()) { | |
1268 if (!name->IsSymbol()) { | |
1269 MaybeObject* maybe_lookup_result = heap()->LookupSymbol(name); | |
1270 Object* lookup_result = NULL; // Initialization to please compiler. | |
1271 if (!maybe_lookup_result->ToObject(&lookup_result)) { | |
1272 set_failure(Failure::cast(maybe_lookup_result)); | |
1273 return reg; | |
1274 } | |
1275 name = String::cast(lookup_result); | |
1276 } | |
1277 ASSERT(current->property_dictionary()->FindEntry(name) == | |
1278 StringDictionary::kNotFound); | |
1279 | |
1280 MaybeObject* negative_lookup = | |
1281 TryGenerateDictionaryNegativeLookup(masm(), | |
1282 miss, | |
1283 reg, | |
1284 name, | |
1285 scratch1, | |
1286 scratch2); | |
1287 if (negative_lookup->IsFailure()) { | |
1288 set_failure(Failure::cast(negative_lookup)); | |
1289 return reg; | |
1290 } | |
1291 | |
1292 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
1293 reg = holder_reg; // from now the object is in holder_reg | |
1294 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | |
1295 } else if (heap()->InNewSpace(prototype)) { | |
1296 // Get the map of the current object. | |
1297 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
1298 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); | |
1299 | |
1300 // Branch on the result of the map check. | |
1301 __ b(ne, miss); | |
1302 | |
1303 // Check access rights to the global object. This has to happen | |
1304 // after the map check so that we know that the object is | |
1305 // actually a global object. | |
1306 if (current->IsJSGlobalProxy()) { | |
1307 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
1308 // Restore scratch register to be the map of the object. In the | |
1309 // new space case below, we load the prototype from the map in | |
1310 // the scratch register. | |
1311 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
1312 } | |
1313 | |
1314 reg = holder_reg; // from now the object is in holder_reg | |
1315 // The prototype is in new space; we cannot store a reference | |
1316 // to it in the code. Load it from the map. | |
1317 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | |
1318 } else { | |
1319 // Check the map of the current object. | |
1320 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
1321 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); | |
1322 // Branch on the result of the map check. | |
1323 __ b(ne, miss); | |
1324 // Check access rights to the global object. This has to happen | |
1325 // after the map check so that we know that the object is | |
1326 // actually a global object. | |
1327 if (current->IsJSGlobalProxy()) { | |
1328 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
1329 } | |
1330 // The prototype is in old space; load it directly. | |
1331 reg = holder_reg; // from now the object is in holder_reg | |
1332 __ mov(reg, Operand(Handle<JSObject>(prototype))); | |
1333 } | |
1334 | |
1335 if (save_at_depth == depth) { | |
1336 __ str(reg, MemOperand(sp)); | |
1337 } | |
1338 | |
1339 // Go to the next object in the prototype chain. | |
1340 current = prototype; | |
1341 } | |
1342 | |
1343 // Check the holder map. | |
1344 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
1345 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); | |
1346 __ b(ne, miss); | |
1347 | |
1348 // Log the check depth. | |
1349 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); | |
1350 | |
1351 // Perform security check for access to the global object. | |
1352 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
1353 if (holder->IsJSGlobalProxy()) { | |
1354 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
1355 } | |
1356 | |
1357 // If we've skipped any global objects, it's not enough to verify | |
1358 // that their maps haven't changed. We also need to check that the | |
1359 // property cell for the property is still empty. | |
1360 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), | |
1361 object, | |
1362 holder, | |
1363 name, | |
1364 scratch1, | |
1365 miss); | |
1366 if (result->IsFailure()) set_failure(Failure::cast(result)); | |
1367 | |
1368 // Return the register containing the holder. | |
1369 return reg; | |
1370 } | |
1371 | |
1372 | |
1373 void StubCompiler::GenerateLoadField(Handle<JSObject> object, | 1075 void StubCompiler::GenerateLoadField(Handle<JSObject> object, |
1374 Handle<JSObject> holder, | 1076 Handle<JSObject> holder, |
1375 Register receiver, | 1077 Register receiver, |
1376 Register scratch1, | 1078 Register scratch1, |
1377 Register scratch2, | 1079 Register scratch2, |
1378 Register scratch3, | 1080 Register scratch3, |
1379 int index, | 1081 int index, |
1380 Handle<String> name, | 1082 Handle<String> name, |
1381 Label* miss) { | 1083 Label* miss) { |
1382 // Check that the receiver isn't a smi. | 1084 // Check that the receiver isn't a smi. |
(...skipping 22 matching lines...) Expand all Loading... | |
1405 // Check that the maps haven't changed. | 1107 // Check that the maps haven't changed. |
1406 CheckPrototypes( | 1108 CheckPrototypes( |
1407 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); | 1109 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
1408 | 1110 |
1409 // Return the constant value. | 1111 // Return the constant value. |
1410 __ mov(r0, Operand(value)); | 1112 __ mov(r0, Operand(value)); |
1411 __ Ret(); | 1113 __ Ret(); |
1412 } | 1114 } |
1413 | 1115 |
1414 | 1116 |
1415 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1117 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, |
1416 JSObject* holder, | 1118 Handle<JSObject> holder, |
1417 Register receiver, | 1119 Register receiver, |
1418 Register name_reg, | 1120 Register name_reg, |
1419 Register scratch1, | 1121 Register scratch1, |
1420 Register scratch2, | 1122 Register scratch2, |
1421 Register scratch3, | 1123 Register scratch3, |
1422 AccessorInfo* callback, | 1124 Handle<AccessorInfo> callback, |
1423 String* name, | 1125 Handle<String> name, |
1424 Label* miss) { | 1126 Label* miss) { |
1425 // Check that the receiver isn't a smi. | 1127 // Check that the receiver isn't a smi. |
1426 __ JumpIfSmi(receiver, miss); | 1128 __ JumpIfSmi(receiver, miss); |
1427 | 1129 |
1428 // Check that the maps haven't changed. | 1130 // Check that the maps haven't changed. |
1429 Register reg = | 1131 Register reg = CheckPrototypes(object, receiver, holder, scratch1, |
1430 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, | 1132 scratch2, scratch3, name, miss); |
1431 name, miss); | |
1432 | 1133 |
1433 // Build AccessorInfo::args_ list on the stack and push property name below | 1134 // Build AccessorInfo::args_ list on the stack and push property name below |
1434 // the exit frame to make GC aware of them and store pointers to them. | 1135 // the exit frame to make GC aware of them and store pointers to them. |
1435 __ push(receiver); | 1136 __ push(receiver); |
1436 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ | 1137 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ |
1437 Handle<AccessorInfo> callback_handle(callback); | 1138 if (heap()->InNewSpace(callback->data())) { |
1438 if (heap()->InNewSpace(callback_handle->data())) { | 1139 __ Move(scratch3, callback); |
1439 __ Move(scratch3, callback_handle); | |
1440 __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); | 1140 __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); |
1441 } else { | 1141 } else { |
1442 __ Move(scratch3, Handle<Object>(callback_handle->data())); | 1142 __ Move(scratch3, Handle<Object>(callback->data())); |
1443 } | 1143 } |
1444 __ Push(reg, scratch3, name_reg); | 1144 __ Push(reg, scratch3, name_reg); |
1445 __ mov(r0, sp); // r0 = Handle<String> | 1145 __ mov(r0, sp); // r0 = Handle<String> |
1446 | 1146 |
1447 Address getter_address = v8::ToCData<Address>(callback->getter()); | |
1448 ApiFunction fun(getter_address); | |
1449 | |
1450 const int kApiStackSpace = 1; | 1147 const int kApiStackSpace = 1; |
1451 | |
1452 FrameScope frame_scope(masm(), StackFrame::MANUAL); | 1148 FrameScope frame_scope(masm(), StackFrame::MANUAL); |
1453 __ EnterExitFrame(false, kApiStackSpace); | 1149 __ EnterExitFrame(false, kApiStackSpace); |
1454 | 1150 |
1455 // Create AccessorInfo instance on the stack above the exit frame with | 1151 // Create AccessorInfo instance on the stack above the exit frame with |
1456 // scratch2 (internal::Object **args_) as the data. | 1152 // scratch2 (internal::Object **args_) as the data. |
1457 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); | 1153 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); |
1458 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& | 1154 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& |
1459 | 1155 |
1460 // Emitting a stub call may try to allocate (if the code is not | 1156 // Emitting a stub call may try to allocate (if the code is not |
ulan
2011/10/27 10:10:26
Old comment.
Kevin Millikin (Chromium)
2011/10/27 10:53:43
Thanks.
| |
1461 // already generated). Do not allow the assembler to perform a | 1157 // already generated). Do not allow the assembler to perform a |
1462 // garbage collection but instead return the allocation failure | 1158 // garbage collection but instead return the allocation failure |
1463 // object. | 1159 // object. |
1464 const int kStackUnwindSpace = 4; | 1160 const int kStackUnwindSpace = 4; |
1161 Address getter_address = v8::ToCData<Address>(callback->getter()); | |
1162 ApiFunction fun(getter_address); | |
1465 ExternalReference ref = | 1163 ExternalReference ref = |
1466 ExternalReference(&fun, | 1164 ExternalReference(&fun, |
1467 ExternalReference::DIRECT_GETTER_CALL, | 1165 ExternalReference::DIRECT_GETTER_CALL, |
1468 masm()->isolate()); | 1166 masm()->isolate()); |
1469 return masm()->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); | 1167 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); |
1470 } | 1168 } |
1471 | 1169 |
1472 | 1170 |
1473 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1171 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, |
1474 JSObject* interceptor_holder, | 1172 Handle<JSObject> interceptor_holder, |
1475 LookupResult* lookup, | 1173 LookupResult* lookup, |
1476 Register receiver, | 1174 Register receiver, |
1477 Register name_reg, | 1175 Register name_reg, |
1478 Register scratch1, | 1176 Register scratch1, |
1479 Register scratch2, | 1177 Register scratch2, |
1480 Register scratch3, | 1178 Register scratch3, |
1481 String* name, | 1179 Handle<String> name, |
1482 Label* miss) { | 1180 Label* miss) { |
1483 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1181 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1484 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1182 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1485 | 1183 |
1486 // Check that the receiver isn't a smi. | 1184 // Check that the receiver isn't a smi. |
1487 __ JumpIfSmi(receiver, miss); | 1185 __ JumpIfSmi(receiver, miss); |
1488 | 1186 |
1489 // So far the most popular follow ups for interceptor loads are FIELD | 1187 // So far the most popular follow ups for interceptor loads are FIELD |
1490 // and CALLBACKS, so inline only them, other cases may be added | 1188 // and CALLBACKS, so inline only them, other cases may be added |
1491 // later. | 1189 // later. |
1492 bool compile_followup_inline = false; | 1190 bool compile_followup_inline = false; |
1493 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1191 if (lookup->IsProperty() && lookup->IsCacheable()) { |
1494 if (lookup->type() == FIELD) { | 1192 if (lookup->type() == FIELD) { |
1495 compile_followup_inline = true; | 1193 compile_followup_inline = true; |
1496 } else if (lookup->type() == CALLBACKS && | 1194 } else if (lookup->type() == CALLBACKS && |
1497 lookup->GetCallbackObject()->IsAccessorInfo() && | 1195 lookup->GetCallbackObject()->IsAccessorInfo()) { |
1498 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { | 1196 compile_followup_inline = |
ulan
2011/10/27 10:10:26
Nitpick: the old code does (compile_followup_inlin
Kevin Millikin (Chromium)
2011/10/27 10:53:43
There's no reason to preserve the implementation.
| |
1499 compile_followup_inline = true; | 1197 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; |
1500 } | 1198 } |
1501 } | 1199 } |
1502 | 1200 |
1503 if (compile_followup_inline) { | 1201 if (compile_followup_inline) { |
1504 // Compile the interceptor call, followed by inline code to load the | 1202 // Compile the interceptor call, followed by inline code to load the |
1505 // property from further up the prototype chain if the call fails. | 1203 // property from further up the prototype chain if the call fails. |
1506 // Check that the maps haven't changed. | 1204 // Check that the maps haven't changed. |
1507 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1205 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
1508 scratch1, scratch2, scratch3, | 1206 scratch1, scratch2, scratch3, |
1509 name, miss); | 1207 name, miss); |
1510 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); | 1208 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); |
1511 | 1209 |
1512 // Save necessary data before invoking an interceptor. | 1210 // Save necessary data before invoking an interceptor. |
1513 // Requires a frame to make GC aware of pushed pointers. | 1211 // Requires a frame to make GC aware of pushed pointers. |
1514 { | 1212 { |
1515 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 1213 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
1516 | |
1517 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1214 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
1518 // CALLBACKS case needs a receiver to be passed into C++ callback. | 1215 // CALLBACKS case needs a receiver to be passed into C++ callback. |
1519 __ Push(receiver, holder_reg, name_reg); | 1216 __ Push(receiver, holder_reg, name_reg); |
1520 } else { | 1217 } else { |
1521 __ Push(holder_reg, name_reg); | 1218 __ Push(holder_reg, name_reg); |
1522 } | 1219 } |
1523 | |
1524 // Invoke an interceptor. Note: map checks from receiver to | 1220 // Invoke an interceptor. Note: map checks from receiver to |
1525 // interceptor's holder has been compiled before (see a caller | 1221 // interceptor's holder has been compiled before (see a caller |
1526 // of this method.) | 1222 // of this method.) |
1527 CompileCallLoadPropertyWithInterceptor(masm(), | 1223 CompileCallLoadPropertyWithInterceptor(masm(), |
1528 receiver, | 1224 receiver, |
1529 holder_reg, | 1225 holder_reg, |
1530 name_reg, | 1226 name_reg, |
1531 interceptor_holder); | 1227 interceptor_holder); |
1532 | |
1533 // Check if interceptor provided a value for property. If it's | 1228 // Check if interceptor provided a value for property. If it's |
1534 // the case, return immediately. | 1229 // the case, return immediately. |
1535 Label interceptor_failed; | 1230 Label interceptor_failed; |
1536 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); | 1231 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); |
1537 __ cmp(r0, scratch1); | 1232 __ cmp(r0, scratch1); |
1538 __ b(eq, &interceptor_failed); | 1233 __ b(eq, &interceptor_failed); |
1539 frame_scope.GenerateLeaveFrame(); | 1234 frame_scope.GenerateLeaveFrame(); |
1540 __ Ret(); | 1235 __ Ret(); |
1541 | 1236 |
1542 __ bind(&interceptor_failed); | 1237 __ bind(&interceptor_failed); |
1543 __ pop(name_reg); | 1238 __ pop(name_reg); |
1544 __ pop(holder_reg); | 1239 __ pop(holder_reg); |
1545 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1240 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
1546 __ pop(receiver); | 1241 __ pop(receiver); |
1547 } | 1242 } |
1548 | |
1549 // Leave the internal frame. | 1243 // Leave the internal frame. |
1550 } | 1244 } |
1551 | |
1552 // Check that the maps from interceptor's holder to lookup's holder | 1245 // Check that the maps from interceptor's holder to lookup's holder |
1553 // haven't changed. And load lookup's holder into |holder| register. | 1246 // haven't changed. And load lookup's holder into |holder| register. |
1554 if (interceptor_holder != lookup->holder()) { | 1247 if (*interceptor_holder != lookup->holder()) { |
1555 holder_reg = CheckPrototypes(interceptor_holder, | 1248 holder_reg = CheckPrototypes(interceptor_holder, |
1556 holder_reg, | 1249 holder_reg, |
1557 lookup->holder(), | 1250 Handle<JSObject>(lookup->holder()), |
1558 scratch1, | 1251 scratch1, |
1559 scratch2, | 1252 scratch2, |
1560 scratch3, | 1253 scratch3, |
1561 name, | 1254 name, |
1562 miss); | 1255 miss); |
1563 } | 1256 } |
1564 | 1257 |
1565 if (lookup->type() == FIELD) { | 1258 if (lookup->type() == FIELD) { |
1566 // We found FIELD property in prototype chain of interceptor's holder. | 1259 // We found FIELD property in prototype chain of interceptor's holder. |
1567 // Retrieve a field from field's holder. | 1260 // Retrieve a field from field's holder. |
1568 GenerateFastPropertyLoad(masm(), r0, holder_reg, | 1261 GenerateFastPropertyLoad(masm(), r0, holder_reg, |
1569 Handle<JSObject>(lookup->holder()), | 1262 Handle<JSObject>(lookup->holder()), |
1570 lookup->GetFieldIndex()); | 1263 lookup->GetFieldIndex()); |
1571 __ Ret(); | 1264 __ Ret(); |
1572 } else { | 1265 } else { |
1573 // We found CALLBACKS property in prototype chain of interceptor's | 1266 // We found CALLBACKS property in prototype chain of interceptor's |
1574 // holder. | 1267 // holder. |
1575 ASSERT(lookup->type() == CALLBACKS); | 1268 ASSERT(lookup->type() == CALLBACKS); |
1576 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1269 Handle<AccessorInfo> callback( |
1577 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1270 AccessorInfo::cast(lookup->GetCallbackObject())); |
1578 ASSERT(callback != NULL); | |
1579 ASSERT(callback->getter() != NULL); | 1271 ASSERT(callback->getter() != NULL); |
1580 | 1272 |
1581 // Tail call to runtime. | 1273 // Tail call to runtime. |
1582 // Important invariant in CALLBACKS case: the code above must be | 1274 // Important invariant in CALLBACKS case: the code above must be |
1583 // structured to never clobber |receiver| register. | 1275 // structured to never clobber |receiver| register. |
1584 __ Move(scratch2, Handle<AccessorInfo>(callback)); | 1276 __ Move(scratch2, callback); |
1585 // holder_reg is either receiver or scratch1. | 1277 // holder_reg is either receiver or scratch1. |
1586 if (!receiver.is(holder_reg)) { | 1278 if (!receiver.is(holder_reg)) { |
1587 ASSERT(scratch1.is(holder_reg)); | 1279 ASSERT(scratch1.is(holder_reg)); |
1588 __ Push(receiver, holder_reg); | 1280 __ Push(receiver, holder_reg); |
1589 __ ldr(scratch3, | 1281 __ ldr(scratch3, |
1590 FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); | 1282 FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); |
1591 __ Push(scratch3, scratch2, name_reg); | 1283 __ Push(scratch3, scratch2, name_reg); |
1592 } else { | 1284 } else { |
1593 __ push(receiver); | 1285 __ push(receiver); |
1594 __ ldr(scratch3, | 1286 __ ldr(scratch3, |
(...skipping 24 matching lines...) Expand all Loading... | |
1619 | 1311 |
1620 | 1312 |
1621 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { | 1313 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
1622 if (kind_ == Code::KEYED_CALL_IC) { | 1314 if (kind_ == Code::KEYED_CALL_IC) { |
1623 __ cmp(r2, Operand(name)); | 1315 __ cmp(r2, Operand(name)); |
1624 __ b(ne, miss); | 1316 __ b(ne, miss); |
1625 } | 1317 } |
1626 } | 1318 } |
1627 | 1319 |
1628 | 1320 |
1629 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1321 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, |
1630 JSObject* holder, | 1322 Handle<JSObject> holder, |
1631 String* name, | 1323 Handle<String> name, |
1632 Label* miss) { | 1324 Label* miss) { |
1633 ASSERT(holder->IsGlobalObject()); | 1325 ASSERT(holder->IsGlobalObject()); |
1634 | 1326 |
1635 // Get the number of arguments. | 1327 // Get the number of arguments. |
1636 const int argc = arguments().immediate(); | 1328 const int argc = arguments().immediate(); |
1637 | 1329 |
1638 // Get the receiver from the stack. | 1330 // Get the receiver from the stack. |
1639 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 1331 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
1640 | 1332 |
1641 // If the object is the holder then we know that it's a global | 1333 // If the object is the holder then we know that it's a global |
1642 // object which can only happen for contextual calls. In this case, | 1334 // object which can only happen for contextual calls. In this case, |
1643 // the receiver cannot be a smi. | 1335 // the receiver cannot be a smi. |
1644 if (object != holder) { | 1336 if (!object.is_identical_to(holder)) { |
1645 __ JumpIfSmi(r0, miss); | 1337 __ JumpIfSmi(r0, miss); |
1646 } | 1338 } |
1647 | 1339 |
1648 // Check that the maps haven't changed. | 1340 // Check that the maps haven't changed. |
1649 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); | 1341 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); |
1650 } | 1342 } |
1651 | 1343 |
1652 | 1344 |
1653 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1345 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1654 JSFunction* function, | 1346 Handle<JSGlobalPropertyCell> cell, |
1655 Label* miss) { | 1347 Handle<JSFunction> function, |
1348 Label* miss) { | |
1656 // Get the value from the cell. | 1349 // Get the value from the cell. |
1657 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 1350 __ mov(r3, Operand(cell)); |
1658 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 1351 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
1659 | 1352 |
1660 // Check that the cell contains the same function. | 1353 // Check that the cell contains the same function. |
1661 if (heap()->InNewSpace(function)) { | 1354 if (heap()->InNewSpace(*function)) { |
1662 // We can't embed a pointer to a function in new space so we have | 1355 // We can't embed a pointer to a function in new space so we have |
1663 // to verify that the shared function info is unchanged. This has | 1356 // to verify that the shared function info is unchanged. This has |
1664 // the nice side effect that multiple closures based on the same | 1357 // the nice side effect that multiple closures based on the same |
1665 // function can all use this call IC. Before we load through the | 1358 // function can all use this call IC. Before we load through the |
1666 // function, we have to verify that it still is a function. | 1359 // function, we have to verify that it still is a function. |
1667 __ JumpIfSmi(r1, miss); | 1360 __ JumpIfSmi(r1, miss); |
1668 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | 1361 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
1669 __ b(ne, miss); | 1362 __ b(ne, miss); |
1670 | 1363 |
1671 // Check the shared function info. Make sure it hasn't changed. | 1364 // Check the shared function info. Make sure it hasn't changed. |
1672 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); | 1365 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); |
1673 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1366 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
1674 __ cmp(r4, r3); | 1367 __ cmp(r4, r3); |
1675 __ b(ne, miss); | |
1676 } else { | 1368 } else { |
1677 __ cmp(r1, Operand(Handle<JSFunction>(function))); | 1369 __ cmp(r1, Operand(function)); |
1678 __ b(ne, miss); | |
1679 } | 1370 } |
1371 __ b(ne, miss); | |
1680 } | 1372 } |
1681 | 1373 |
1682 | 1374 |
1683 void CallStubCompiler::GenerateMissBranch() { | 1375 void CallStubCompiler::GenerateMissBranch() { |
1684 Handle<Code> code = | 1376 Handle<Code> code = |
1685 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1377 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
1686 kind_, | 1378 kind_, |
1687 extra_state_); | 1379 extra_state_); |
1688 __ Jump(code, RelocInfo::CODE_TARGET); | 1380 __ Jump(code, RelocInfo::CODE_TARGET); |
1689 } | 1381 } |
1690 | 1382 |
1691 | 1383 |
1692 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
1693 // handlified. | |
1694 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { | |
1695 MaybeObject* maybe_obj = | |
1696 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), | |
1697 kind_, | |
1698 extra_state_); | |
1699 Object* obj; | |
1700 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
1701 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | |
1702 return obj; | |
1703 } | |
1704 | |
1705 | |
1706 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1384 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
1707 Handle<JSObject> holder, | 1385 Handle<JSObject> holder, |
1708 int index, | 1386 int index, |
1709 Handle<String> name) { | 1387 Handle<String> name) { |
1710 // ----------- S t a t e ------------- | 1388 // ----------- S t a t e ------------- |
1711 // -- r2 : name | 1389 // -- r2 : name |
1712 // -- lr : return address | 1390 // -- lr : return address |
1713 // ----------------------------------- | 1391 // ----------------------------------- |
1714 Label miss; | 1392 Label miss; |
1715 | 1393 |
(...skipping 14 matching lines...) Expand all Loading... | |
1730 | 1408 |
1731 // Handle call cache miss. | 1409 // Handle call cache miss. |
1732 __ bind(&miss); | 1410 __ bind(&miss); |
1733 GenerateMissBranch(); | 1411 GenerateMissBranch(); |
1734 | 1412 |
1735 // Return the generated code. | 1413 // Return the generated code. |
1736 return GetCode(FIELD, name); | 1414 return GetCode(FIELD, name); |
1737 } | 1415 } |
1738 | 1416 |
1739 | 1417 |
1740 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1418 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
1741 JSObject* holder, | 1419 Handle<Object> object, |
1742 JSGlobalPropertyCell* cell, | 1420 Handle<JSObject> holder, |
1743 JSFunction* function, | 1421 Handle<JSGlobalPropertyCell> cell, |
1744 String* name) { | 1422 Handle<JSFunction> function, |
1423 Handle<String> name) { | |
1745 // ----------- S t a t e ------------- | 1424 // ----------- S t a t e ------------- |
1746 // -- r2 : name | 1425 // -- r2 : name |
1747 // -- lr : return address | 1426 // -- lr : return address |
1748 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1427 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
1749 // -- ... | 1428 // -- ... |
1750 // -- sp[argc * 4] : receiver | 1429 // -- sp[argc * 4] : receiver |
1751 // ----------------------------------- | 1430 // ----------------------------------- |
1752 | 1431 |
1753 // If object is not an array, bail out to regular call. | 1432 // If object is not an array, bail out to regular call. |
1754 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1433 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
1755 | 1434 |
1756 Label miss; | 1435 Label miss; |
1757 | 1436 GenerateNameCheck(name, &miss); |
1758 GenerateNameCheck(Handle<String>(name), &miss); | |
1759 | 1437 |
1760 Register receiver = r1; | 1438 Register receiver = r1; |
1761 | |
1762 // Get the receiver from the stack | 1439 // Get the receiver from the stack |
1763 const int argc = arguments().immediate(); | 1440 const int argc = arguments().immediate(); |
1764 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1441 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
1765 | 1442 |
1766 // Check that the receiver isn't a smi. | 1443 // Check that the receiver isn't a smi. |
1767 __ JumpIfSmi(receiver, &miss); | 1444 __ JumpIfSmi(receiver, &miss); |
1768 | 1445 |
1769 // Check that the maps haven't changed. | 1446 // Check that the maps haven't changed. |
1770 CheckPrototypes(JSObject::cast(object), receiver, | 1447 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0, r4, |
1771 holder, r3, r0, r4, name, &miss); | 1448 name, &miss); |
1772 | 1449 |
1773 if (argc == 0) { | 1450 if (argc == 0) { |
1774 // Nothing to do, just return the length. | 1451 // Nothing to do, just return the length. |
1775 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1452 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1776 __ Drop(argc + 1); | 1453 __ Drop(argc + 1); |
1777 __ Ret(); | 1454 __ Ret(); |
1778 } else { | 1455 } else { |
1779 Label call_builtin; | 1456 Label call_builtin; |
1780 | |
1781 Register elements = r3; | 1457 Register elements = r3; |
1782 Register end_elements = r5; | 1458 Register end_elements = r5; |
1783 | |
1784 // Get the elements array of the object. | 1459 // Get the elements array of the object. |
1785 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1460 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
1786 | 1461 |
1787 // Check that the elements are in fast mode and writable. | 1462 // Check that the elements are in fast mode and writable. |
1788 __ CheckMap(elements, | 1463 __ CheckMap(elements, |
1789 r0, | 1464 r0, |
1790 Heap::kFixedArrayMapRootIndex, | 1465 Heap::kFixedArrayMapRootIndex, |
1791 &call_builtin, | 1466 &call_builtin, |
1792 DONT_DO_SMI_CHECK); | 1467 DONT_DO_SMI_CHECK); |
1793 | 1468 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1914 } | 1589 } |
1915 __ bind(&call_builtin); | 1590 __ bind(&call_builtin); |
1916 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1591 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
1917 masm()->isolate()), | 1592 masm()->isolate()), |
1918 argc + 1, | 1593 argc + 1, |
1919 1); | 1594 1); |
1920 } | 1595 } |
1921 | 1596 |
1922 // Handle call cache miss. | 1597 // Handle call cache miss. |
1923 __ bind(&miss); | 1598 __ bind(&miss); |
1924 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1599 GenerateMissBranch(); |
1925 if (maybe_result->IsFailure()) return maybe_result; | |
1926 | 1600 |
1927 // Return the generated code. | 1601 // Return the generated code. |
1928 return TryGetCode(function); | 1602 return GetCode(function); |
1929 } | 1603 } |
1930 | 1604 |
1931 | 1605 |
1932 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1606 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
1933 JSObject* holder, | 1607 Handle<Object> object, |
1934 JSGlobalPropertyCell* cell, | 1608 Handle<JSObject> holder, |
1935 JSFunction* function, | 1609 Handle<JSGlobalPropertyCell> cell, |
1936 String* name) { | 1610 Handle<JSFunction> function, |
1611 Handle<String> name) { | |
1937 // ----------- S t a t e ------------- | 1612 // ----------- S t a t e ------------- |
1938 // -- r2 : name | 1613 // -- r2 : name |
1939 // -- lr : return address | 1614 // -- lr : return address |
1940 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1615 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
1941 // -- ... | 1616 // -- ... |
1942 // -- sp[argc * 4] : receiver | 1617 // -- sp[argc * 4] : receiver |
1943 // ----------------------------------- | 1618 // ----------------------------------- |
1944 | 1619 |
1945 // If object is not an array, bail out to regular call. | 1620 // If object is not an array, bail out to regular call. |
1946 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1621 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
1947 | 1622 |
1948 Label miss, return_undefined, call_builtin; | 1623 Label miss, return_undefined, call_builtin; |
1949 | |
1950 Register receiver = r1; | 1624 Register receiver = r1; |
1951 Register elements = r3; | 1625 Register elements = r3; |
1952 | 1626 GenerateNameCheck(name, &miss); |
1953 GenerateNameCheck(Handle<String>(name), &miss); | |
1954 | 1627 |
1955 // Get the receiver from the stack | 1628 // Get the receiver from the stack |
1956 const int argc = arguments().immediate(); | 1629 const int argc = arguments().immediate(); |
1957 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1630 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
1958 | |
1959 // Check that the receiver isn't a smi. | 1631 // Check that the receiver isn't a smi. |
1960 __ JumpIfSmi(receiver, &miss); | 1632 __ JumpIfSmi(receiver, &miss); |
1961 | 1633 |
1962 // Check that the maps haven't changed. | 1634 // Check that the maps haven't changed. |
1963 CheckPrototypes(JSObject::cast(object), | 1635 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements, |
1964 receiver, holder, elements, r4, r0, name, &miss); | 1636 r4, r0, name, &miss); |
1965 | 1637 |
1966 // Get the elements array of the object. | 1638 // Get the elements array of the object. |
1967 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1639 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
1968 | 1640 |
1969 // Check that the elements are in fast mode and writable. | 1641 // Check that the elements are in fast mode and writable. |
1970 __ CheckMap(elements, | 1642 __ CheckMap(elements, |
1971 r0, | 1643 r0, |
1972 Heap::kFixedArrayMapRootIndex, | 1644 Heap::kFixedArrayMapRootIndex, |
1973 &call_builtin, | 1645 &call_builtin, |
1974 DONT_DO_SMI_CHECK); | 1646 DONT_DO_SMI_CHECK); |
(...skipping 28 matching lines...) Expand all Loading... | |
2003 __ Ret(); | 1675 __ Ret(); |
2004 | 1676 |
2005 __ bind(&call_builtin); | 1677 __ bind(&call_builtin); |
2006 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, | 1678 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, |
2007 masm()->isolate()), | 1679 masm()->isolate()), |
2008 argc + 1, | 1680 argc + 1, |
2009 1); | 1681 1); |
2010 | 1682 |
2011 // Handle call cache miss. | 1683 // Handle call cache miss. |
2012 __ bind(&miss); | 1684 __ bind(&miss); |
2013 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1685 GenerateMissBranch(); |
2014 if (maybe_result->IsFailure()) return maybe_result; | |
2015 | 1686 |
2016 // Return the generated code. | 1687 // Return the generated code. |
2017 return TryGetCode(function); | 1688 return GetCode(function); |
2018 } | 1689 } |
2019 | 1690 |
2020 | 1691 |
2021 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1692 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
2022 Object* object, | 1693 Handle<Object> object, |
2023 JSObject* holder, | 1694 Handle<JSObject> holder, |
2024 JSGlobalPropertyCell* cell, | 1695 Handle<JSGlobalPropertyCell> cell, |
2025 JSFunction* function, | 1696 Handle<JSFunction> function, |
2026 String* name) { | 1697 Handle<String> name) { |
2027 // ----------- S t a t e ------------- | 1698 // ----------- S t a t e ------------- |
2028 // -- r2 : function name | 1699 // -- r2 : function name |
2029 // -- lr : return address | 1700 // -- lr : return address |
2030 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1701 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
2031 // -- ... | 1702 // -- ... |
2032 // -- sp[argc * 4] : receiver | 1703 // -- sp[argc * 4] : receiver |
2033 // ----------------------------------- | 1704 // ----------------------------------- |
2034 | 1705 |
2035 // If object is not a string, bail out to regular call. | 1706 // If object is not a string, bail out to regular call. |
2036 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1707 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
2037 | 1708 |
2038 const int argc = arguments().immediate(); | 1709 const int argc = arguments().immediate(); |
2039 | |
2040 Label miss; | 1710 Label miss; |
2041 Label name_miss; | 1711 Label name_miss; |
2042 Label index_out_of_range; | 1712 Label index_out_of_range; |
2043 Label* index_out_of_range_label = &index_out_of_range; | 1713 Label* index_out_of_range_label = &index_out_of_range; |
2044 | 1714 |
2045 if (kind_ == Code::CALL_IC && | 1715 if (kind_ == Code::CALL_IC && |
2046 (CallICBase::StringStubState::decode(extra_state_) == | 1716 (CallICBase::StringStubState::decode(extra_state_) == |
2047 DEFAULT_STRING_STUB)) { | 1717 DEFAULT_STRING_STUB)) { |
2048 index_out_of_range_label = &miss; | 1718 index_out_of_range_label = &miss; |
2049 } | 1719 } |
2050 | 1720 GenerateNameCheck(name, &name_miss); |
2051 GenerateNameCheck(Handle<String>(name), &name_miss); | |
2052 | 1721 |
2053 // Check that the maps starting from the prototype haven't changed. | 1722 // Check that the maps starting from the prototype haven't changed. |
2054 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1723 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
2055 Context::STRING_FUNCTION_INDEX, | 1724 Context::STRING_FUNCTION_INDEX, |
2056 r0, | 1725 r0, |
2057 &miss); | 1726 &miss); |
2058 ASSERT(object != holder); | 1727 ASSERT(object != holder); |
2059 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, | 1728 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
2060 r1, r3, r4, name, &miss); | 1729 r0, holder, r1, r3, r4, name, &miss); |
2061 | 1730 |
2062 Register receiver = r1; | 1731 Register receiver = r1; |
2063 Register index = r4; | 1732 Register index = r4; |
2064 Register scratch = r3; | 1733 Register scratch = r3; |
2065 Register result = r0; | 1734 Register result = r0; |
2066 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1735 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
2067 if (argc > 0) { | 1736 if (argc > 0) { |
2068 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1737 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
2069 } else { | 1738 } else { |
2070 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1739 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
2071 } | 1740 } |
2072 | 1741 |
2073 StringCharCodeAtGenerator char_code_at_generator(receiver, | 1742 StringCharCodeAtGenerator generator(receiver, |
2074 index, | 1743 index, |
2075 scratch, | 1744 scratch, |
2076 result, | 1745 result, |
2077 &miss, // When not a string. | 1746 &miss, // When not a string. |
2078 &miss, // When not a number. | 1747 &miss, // When not a number. |
2079 index_out_of_range_label, | 1748 index_out_of_range_label, |
2080 STRING_INDEX_IS_NUMBER); | 1749 STRING_INDEX_IS_NUMBER); |
2081 char_code_at_generator.GenerateFast(masm()); | 1750 generator.GenerateFast(masm()); |
2082 __ Drop(argc + 1); | 1751 __ Drop(argc + 1); |
2083 __ Ret(); | 1752 __ Ret(); |
2084 | 1753 |
2085 StubRuntimeCallHelper call_helper; | 1754 StubRuntimeCallHelper call_helper; |
2086 char_code_at_generator.GenerateSlow(masm(), call_helper); | 1755 generator.GenerateSlow(masm(), call_helper); |
2087 | 1756 |
2088 if (index_out_of_range.is_linked()) { | 1757 if (index_out_of_range.is_linked()) { |
2089 __ bind(&index_out_of_range); | 1758 __ bind(&index_out_of_range); |
2090 __ LoadRoot(r0, Heap::kNanValueRootIndex); | 1759 __ LoadRoot(r0, Heap::kNanValueRootIndex); |
2091 __ Drop(argc + 1); | 1760 __ Drop(argc + 1); |
2092 __ Ret(); | 1761 __ Ret(); |
2093 } | 1762 } |
2094 | 1763 |
2095 __ bind(&miss); | 1764 __ bind(&miss); |
2096 // Restore function name in r2. | 1765 // Restore function name in r2. |
2097 __ Move(r2, Handle<String>(name)); | 1766 __ Move(r2, name); |
2098 __ bind(&name_miss); | 1767 __ bind(&name_miss); |
2099 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1768 GenerateMissBranch(); |
2100 if (maybe_result->IsFailure()) return maybe_result; | |
2101 | 1769 |
2102 // Return the generated code. | 1770 // Return the generated code. |
2103 return TryGetCode(function); | 1771 return GetCode(function); |
2104 } | 1772 } |
2105 | 1773 |
2106 | 1774 |
2107 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1775 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
2108 Object* object, | 1776 Handle<Object> object, |
2109 JSObject* holder, | 1777 Handle<JSObject> holder, |
2110 JSGlobalPropertyCell* cell, | 1778 Handle<JSGlobalPropertyCell> cell, |
2111 JSFunction* function, | 1779 Handle<JSFunction> function, |
2112 String* name) { | 1780 Handle<String> name) { |
2113 // ----------- S t a t e ------------- | 1781 // ----------- S t a t e ------------- |
2114 // -- r2 : function name | 1782 // -- r2 : function name |
2115 // -- lr : return address | 1783 // -- lr : return address |
2116 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1784 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
2117 // -- ... | 1785 // -- ... |
2118 // -- sp[argc * 4] : receiver | 1786 // -- sp[argc * 4] : receiver |
2119 // ----------------------------------- | 1787 // ----------------------------------- |
2120 | 1788 |
2121 // If object is not a string, bail out to regular call. | 1789 // If object is not a string, bail out to regular call. |
2122 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1790 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
2123 | 1791 |
2124 const int argc = arguments().immediate(); | 1792 const int argc = arguments().immediate(); |
2125 | |
2126 Label miss; | 1793 Label miss; |
2127 Label name_miss; | 1794 Label name_miss; |
2128 Label index_out_of_range; | 1795 Label index_out_of_range; |
2129 Label* index_out_of_range_label = &index_out_of_range; | 1796 Label* index_out_of_range_label = &index_out_of_range; |
2130 | |
2131 if (kind_ == Code::CALL_IC && | 1797 if (kind_ == Code::CALL_IC && |
2132 (CallICBase::StringStubState::decode(extra_state_) == | 1798 (CallICBase::StringStubState::decode(extra_state_) == |
2133 DEFAULT_STRING_STUB)) { | 1799 DEFAULT_STRING_STUB)) { |
2134 index_out_of_range_label = &miss; | 1800 index_out_of_range_label = &miss; |
2135 } | 1801 } |
2136 | 1802 GenerateNameCheck(name, &name_miss); |
2137 GenerateNameCheck(Handle<String>(name), &name_miss); | |
2138 | 1803 |
2139 // Check that the maps starting from the prototype haven't changed. | 1804 // Check that the maps starting from the prototype haven't changed. |
2140 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1805 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
2141 Context::STRING_FUNCTION_INDEX, | 1806 Context::STRING_FUNCTION_INDEX, |
2142 r0, | 1807 r0, |
2143 &miss); | 1808 &miss); |
2144 ASSERT(object != holder); | 1809 ASSERT(object != holder); |
2145 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, | 1810 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
2146 r1, r3, r4, name, &miss); | 1811 r0, holder, r1, r3, r4, name, &miss); |
2147 | 1812 |
2148 Register receiver = r0; | 1813 Register receiver = r0; |
2149 Register index = r4; | 1814 Register index = r4; |
2150 Register scratch1 = r1; | 1815 Register scratch1 = r1; |
2151 Register scratch2 = r3; | 1816 Register scratch2 = r3; |
2152 Register result = r0; | 1817 Register result = r0; |
2153 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); | 1818 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
2154 if (argc > 0) { | 1819 if (argc > 0) { |
2155 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1820 __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
2156 } else { | 1821 } else { |
2157 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1822 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
2158 } | 1823 } |
2159 | 1824 |
2160 StringCharAtGenerator char_at_generator(receiver, | 1825 StringCharAtGenerator generator(receiver, |
2161 index, | 1826 index, |
2162 scratch1, | 1827 scratch1, |
2163 scratch2, | 1828 scratch2, |
2164 result, | 1829 result, |
2165 &miss, // When not a string. | 1830 &miss, // When not a string. |
2166 &miss, // When not a number. | 1831 &miss, // When not a number. |
2167 index_out_of_range_label, | 1832 index_out_of_range_label, |
2168 STRING_INDEX_IS_NUMBER); | 1833 STRING_INDEX_IS_NUMBER); |
2169 char_at_generator.GenerateFast(masm()); | 1834 generator.GenerateFast(masm()); |
2170 __ Drop(argc + 1); | 1835 __ Drop(argc + 1); |
2171 __ Ret(); | 1836 __ Ret(); |
2172 | 1837 |
2173 StubRuntimeCallHelper call_helper; | 1838 StubRuntimeCallHelper call_helper; |
2174 char_at_generator.GenerateSlow(masm(), call_helper); | 1839 generator.GenerateSlow(masm(), call_helper); |
2175 | 1840 |
2176 if (index_out_of_range.is_linked()) { | 1841 if (index_out_of_range.is_linked()) { |
2177 __ bind(&index_out_of_range); | 1842 __ bind(&index_out_of_range); |
2178 __ LoadRoot(r0, Heap::kEmptyStringRootIndex); | 1843 __ LoadRoot(r0, Heap::kEmptyStringRootIndex); |
2179 __ Drop(argc + 1); | 1844 __ Drop(argc + 1); |
2180 __ Ret(); | 1845 __ Ret(); |
2181 } | 1846 } |
2182 | 1847 |
2183 __ bind(&miss); | 1848 __ bind(&miss); |
2184 // Restore function name in r2. | 1849 // Restore function name in r2. |
2185 __ Move(r2, Handle<String>(name)); | 1850 __ Move(r2, name); |
2186 __ bind(&name_miss); | 1851 __ bind(&name_miss); |
2187 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1852 GenerateMissBranch(); |
2188 if (maybe_result->IsFailure()) return maybe_result; | |
2189 | 1853 |
2190 // Return the generated code. | 1854 // Return the generated code. |
2191 return TryGetCode(function); | 1855 return GetCode(function); |
2192 } | 1856 } |
2193 | 1857 |
2194 | 1858 |
2195 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 1859 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2196 Object* object, | 1860 Handle<Object> object, |
2197 JSObject* holder, | 1861 Handle<JSObject> holder, |
2198 JSGlobalPropertyCell* cell, | 1862 Handle<JSGlobalPropertyCell> cell, |
2199 JSFunction* function, | 1863 Handle<JSFunction> function, |
2200 String* name) { | 1864 Handle<String> name) { |
2201 // ----------- S t a t e ------------- | 1865 // ----------- S t a t e ------------- |
2202 // -- r2 : function name | 1866 // -- r2 : function name |
2203 // -- lr : return address | 1867 // -- lr : return address |
2204 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1868 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
2205 // -- ... | 1869 // -- ... |
2206 // -- sp[argc * 4] : receiver | 1870 // -- sp[argc * 4] : receiver |
2207 // ----------------------------------- | 1871 // ----------------------------------- |
2208 | 1872 |
2209 const int argc = arguments().immediate(); | 1873 const int argc = arguments().immediate(); |
2210 | 1874 |
2211 // If the object is not a JSObject or we got an unexpected number of | 1875 // If the object is not a JSObject or we got an unexpected number of |
2212 // arguments, bail out to the regular call. | 1876 // arguments, bail out to the regular call. |
2213 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1877 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2214 | 1878 |
2215 Label miss; | 1879 Label miss; |
2216 GenerateNameCheck(Handle<String>(name), &miss); | 1880 GenerateNameCheck(name, &miss); |
2217 | 1881 |
2218 if (cell == NULL) { | 1882 if (cell.is_null()) { |
2219 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 1883 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
2220 | 1884 |
2221 STATIC_ASSERT(kSmiTag == 0); | 1885 STATIC_ASSERT(kSmiTag == 0); |
2222 __ JumpIfSmi(r1, &miss); | 1886 __ JumpIfSmi(r1, &miss); |
2223 | 1887 |
2224 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 1888 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, |
2225 &miss); | 1889 name, &miss); |
2226 } else { | 1890 } else { |
2227 ASSERT(cell->value() == function); | 1891 ASSERT(cell->value() == *function); |
2228 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1892 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
1893 &miss); | |
2229 GenerateLoadFunctionFromCell(cell, function, &miss); | 1894 GenerateLoadFunctionFromCell(cell, function, &miss); |
2230 } | 1895 } |
2231 | 1896 |
2232 // Load the char code argument. | 1897 // Load the char code argument. |
2233 Register code = r1; | 1898 Register code = r1; |
2234 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); | 1899 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); |
2235 | 1900 |
2236 // Check the code is a smi. | 1901 // Check the code is a smi. |
2237 Label slow; | 1902 Label slow; |
2238 STATIC_ASSERT(kSmiTag == 0); | 1903 STATIC_ASSERT(kSmiTag == 0); |
2239 __ JumpIfNotSmi(code, &slow); | 1904 __ JumpIfNotSmi(code, &slow); |
2240 | 1905 |
2241 // Convert the smi code to uint16. | 1906 // Convert the smi code to uint16. |
2242 __ and_(code, code, Operand(Smi::FromInt(0xffff))); | 1907 __ and_(code, code, Operand(Smi::FromInt(0xffff))); |
2243 | 1908 |
2244 StringCharFromCodeGenerator char_from_code_generator(code, r0); | 1909 StringCharFromCodeGenerator generator(code, r0); |
2245 char_from_code_generator.GenerateFast(masm()); | 1910 generator.GenerateFast(masm()); |
2246 __ Drop(argc + 1); | 1911 __ Drop(argc + 1); |
2247 __ Ret(); | 1912 __ Ret(); |
2248 | 1913 |
2249 StubRuntimeCallHelper call_helper; | 1914 StubRuntimeCallHelper call_helper; |
2250 char_from_code_generator.GenerateSlow(masm(), call_helper); | 1915 generator.GenerateSlow(masm(), call_helper); |
2251 | 1916 |
2252 // Tail call the full function. We do not have to patch the receiver | 1917 // Tail call the full function. We do not have to patch the receiver |
2253 // because the function makes no use of it. | 1918 // because the function makes no use of it. |
2254 __ bind(&slow); | 1919 __ bind(&slow); |
2255 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 1920 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
2256 | 1921 |
2257 __ bind(&miss); | 1922 __ bind(&miss); |
2258 // r2: function name. | 1923 // r2: function name. |
2259 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1924 GenerateMissBranch(); |
2260 if (maybe_result->IsFailure()) return maybe_result; | |
2261 | 1925 |
2262 // Return the generated code. | 1926 // Return the generated code. |
2263 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 1927 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
2264 } | 1928 } |
2265 | 1929 |
2266 | 1930 |
2267 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 1931 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2268 JSObject* holder, | 1932 Handle<Object> object, |
2269 JSGlobalPropertyCell* cell, | 1933 Handle<JSObject> holder, |
2270 JSFunction* function, | 1934 Handle<JSGlobalPropertyCell> cell, |
2271 String* name) { | 1935 Handle<JSFunction> function, |
1936 Handle<String> name) { | |
2272 // ----------- S t a t e ------------- | 1937 // ----------- S t a t e ------------- |
2273 // -- r2 : function name | 1938 // -- r2 : function name |
2274 // -- lr : return address | 1939 // -- lr : return address |
2275 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1940 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
2276 // -- ... | 1941 // -- ... |
2277 // -- sp[argc * 4] : receiver | 1942 // -- sp[argc * 4] : receiver |
2278 // ----------------------------------- | 1943 // ----------------------------------- |
2279 | 1944 |
2280 if (!CpuFeatures::IsSupported(VFP3)) { | 1945 if (!CpuFeatures::IsSupported(VFP3)) { |
2281 return heap()->undefined_value(); | 1946 return Handle<Code>::null(); |
2282 } | 1947 } |
2283 | 1948 |
2284 CpuFeatures::Scope scope_vfp3(VFP3); | 1949 CpuFeatures::Scope scope_vfp3(VFP3); |
2285 | |
2286 const int argc = arguments().immediate(); | 1950 const int argc = arguments().immediate(); |
2287 | |
2288 // If the object is not a JSObject or we got an unexpected number of | 1951 // If the object is not a JSObject or we got an unexpected number of |
2289 // arguments, bail out to the regular call. | 1952 // arguments, bail out to the regular call. |
2290 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1953 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2291 | 1954 |
2292 Label miss, slow; | 1955 Label miss, slow; |
2293 GenerateNameCheck(Handle<String>(name), &miss); | 1956 GenerateNameCheck(name, &miss); |
2294 | 1957 |
2295 if (cell == NULL) { | 1958 if (cell.is_null()) { |
2296 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 1959 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
2297 | |
2298 STATIC_ASSERT(kSmiTag == 0); | 1960 STATIC_ASSERT(kSmiTag == 0); |
2299 __ JumpIfSmi(r1, &miss); | 1961 __ JumpIfSmi(r1, &miss); |
2300 | 1962 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, |
2301 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 1963 name, &miss); |
2302 &miss); | |
2303 } else { | 1964 } else { |
2304 ASSERT(cell->value() == function); | 1965 ASSERT(cell->value() == *function); |
2305 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1966 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
1967 &miss); | |
2306 GenerateLoadFunctionFromCell(cell, function, &miss); | 1968 GenerateLoadFunctionFromCell(cell, function, &miss); |
2307 } | 1969 } |
2308 | 1970 |
2309 // Load the (only) argument into r0. | 1971 // Load the (only) argument into r0. |
2310 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 1972 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); |
2311 | 1973 |
2312 // If the argument is a smi, just return. | 1974 // If the argument is a smi, just return. |
2313 STATIC_ASSERT(kSmiTag == 0); | 1975 STATIC_ASSERT(kSmiTag == 0); |
2314 __ tst(r0, Operand(kSmiTagMask)); | 1976 __ tst(r0, Operand(kSmiTagMask)); |
2315 __ Drop(argc + 1, eq); | 1977 __ Drop(argc + 1, eq); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2397 // Restore FPCSR and fall to slow case. | 2059 // Restore FPCSR and fall to slow case. |
2398 __ vmsr(r3); | 2060 __ vmsr(r3); |
2399 | 2061 |
2400 __ bind(&slow); | 2062 __ bind(&slow); |
2401 // Tail call the full function. We do not have to patch the receiver | 2063 // Tail call the full function. We do not have to patch the receiver |
2402 // because the function makes no use of it. | 2064 // because the function makes no use of it. |
2403 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 2065 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
2404 | 2066 |
2405 __ bind(&miss); | 2067 __ bind(&miss); |
2406 // r2: function name. | 2068 // r2: function name. |
2407 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2069 GenerateMissBranch(); |
2408 if (maybe_result->IsFailure()) return maybe_result; | |
2409 | 2070 |
2410 // Return the generated code. | 2071 // Return the generated code. |
2411 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 2072 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
2412 } | 2073 } |
2413 | 2074 |
2414 | 2075 |
2415 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 2076 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2416 JSObject* holder, | 2077 Handle<Object> object, |
2417 JSGlobalPropertyCell* cell, | 2078 Handle<JSObject> holder, |
2418 JSFunction* function, | 2079 Handle<JSGlobalPropertyCell> cell, |
2419 String* name) { | 2080 Handle<JSFunction> function, |
2081 Handle<String> name) { | |
2420 // ----------- S t a t e ------------- | 2082 // ----------- S t a t e ------------- |
2421 // -- r2 : function name | 2083 // -- r2 : function name |
2422 // -- lr : return address | 2084 // -- lr : return address |
2423 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 2085 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
2424 // -- ... | 2086 // -- ... |
2425 // -- sp[argc * 4] : receiver | 2087 // -- sp[argc * 4] : receiver |
2426 // ----------------------------------- | 2088 // ----------------------------------- |
2427 | 2089 |
2428 const int argc = arguments().immediate(); | 2090 const int argc = arguments().immediate(); |
2429 | |
2430 // If the object is not a JSObject or we got an unexpected number of | 2091 // If the object is not a JSObject or we got an unexpected number of |
2431 // arguments, bail out to the regular call. | 2092 // arguments, bail out to the regular call. |
2432 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2093 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
2433 | 2094 |
2434 Label miss; | 2095 Label miss; |
2435 GenerateNameCheck(Handle<String>(name), &miss); | 2096 GenerateNameCheck(name, &miss); |
2436 | 2097 if (cell.is_null()) { |
2437 if (cell == NULL) { | |
2438 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); | 2098 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); |
2439 | |
2440 STATIC_ASSERT(kSmiTag == 0); | 2099 STATIC_ASSERT(kSmiTag == 0); |
2441 __ JumpIfSmi(r1, &miss); | 2100 __ JumpIfSmi(r1, &miss); |
2442 | 2101 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, |
2443 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2102 name, &miss); |
2444 &miss); | |
2445 } else { | 2103 } else { |
2446 ASSERT(cell->value() == function); | 2104 ASSERT(cell->value() == *function); |
2447 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 2105 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
2106 &miss); | |
2448 GenerateLoadFunctionFromCell(cell, function, &miss); | 2107 GenerateLoadFunctionFromCell(cell, function, &miss); |
2449 } | 2108 } |
2450 | 2109 |
2451 // Load the (only) argument into r0. | 2110 // Load the (only) argument into r0. |
2452 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 2111 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); |
2453 | 2112 |
2454 // Check if the argument is a smi. | 2113 // Check if the argument is a smi. |
2455 Label not_smi; | 2114 Label not_smi; |
2456 STATIC_ASSERT(kSmiTag == 0); | 2115 STATIC_ASSERT(kSmiTag == 0); |
2457 __ JumpIfNotSmi(r0, ¬_smi); | 2116 __ JumpIfNotSmi(r0, ¬_smi); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2498 __ Drop(argc + 1); | 2157 __ Drop(argc + 1); |
2499 __ Ret(); | 2158 __ Ret(); |
2500 | 2159 |
2501 // Tail call the full function. We do not have to patch the receiver | 2160 // Tail call the full function. We do not have to patch the receiver |
2502 // because the function makes no use of it. | 2161 // because the function makes no use of it. |
2503 __ bind(&slow); | 2162 __ bind(&slow); |
2504 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 2163 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
2505 | 2164 |
2506 __ bind(&miss); | 2165 __ bind(&miss); |
2507 // r2: function name. | 2166 // r2: function name. |
2508 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2167 GenerateMissBranch(); |
2509 if (maybe_result->IsFailure()) return maybe_result; | |
2510 | 2168 |
2511 // Return the generated code. | 2169 // Return the generated code. |
2512 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 2170 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
2513 } | 2171 } |
2514 | 2172 |
2515 | 2173 |
2516 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2174 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2517 const CallOptimization& optimization, | 2175 const CallOptimization& optimization, |
2518 Object* object, | 2176 Handle<Object> object, |
2519 JSObject* holder, | 2177 Handle<JSObject> holder, |
2520 JSGlobalPropertyCell* cell, | 2178 Handle<JSGlobalPropertyCell> cell, |
2521 JSFunction* function, | 2179 Handle<JSFunction> function, |
2522 String* name) { | 2180 Handle<String> name) { |
2523 Counters* counters = isolate()->counters(); | 2181 Counters* counters = isolate()->counters(); |
2524 | 2182 |
2525 ASSERT(optimization.is_simple_api_call()); | 2183 ASSERT(optimization.is_simple_api_call()); |
2526 // Bail out if object is a global object as we don't want to | 2184 // Bail out if object is a global object as we don't want to |
2527 // repatch it to global receiver. | 2185 // repatch it to global receiver. |
2528 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2186 if (object->IsGlobalObject()) return Handle<Code>::null(); |
2529 if (cell != NULL) return heap()->undefined_value(); | 2187 if (!cell.is_null()) return Handle<Code>::null(); |
2530 if (!object->IsJSObject()) return heap()->undefined_value(); | 2188 if (!object->IsJSObject()) return Handle<Code>::null(); |
2531 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2189 int depth = optimization.GetPrototypeDepthOfExpectedType( |
2532 JSObject::cast(object), holder); | 2190 Handle<JSObject>::cast(object), holder); |
2533 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2191 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); |
2534 | 2192 |
2535 Label miss, miss_before_stack_reserved; | 2193 Label miss, miss_before_stack_reserved; |
2536 | 2194 GenerateNameCheck(name, &miss_before_stack_reserved); |
2537 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); | |
2538 | 2195 |
2539 // Get the receiver from the stack. | 2196 // Get the receiver from the stack. |
2540 const int argc = arguments().immediate(); | 2197 const int argc = arguments().immediate(); |
2541 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2198 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
2542 | 2199 |
2543 // Check that the receiver isn't a smi. | 2200 // Check that the receiver isn't a smi. |
2544 __ JumpIfSmi(r1, &miss_before_stack_reserved); | 2201 __ JumpIfSmi(r1, &miss_before_stack_reserved); |
2545 | 2202 |
2546 __ IncrementCounter(counters->call_const(), 1, r0, r3); | 2203 __ IncrementCounter(counters->call_const(), 1, r0, r3); |
2547 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); | 2204 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); |
2548 | 2205 |
2549 ReserveSpaceForFastApiCall(masm(), r0); | 2206 ReserveSpaceForFastApiCall(masm(), r0); |
2550 | 2207 |
2551 // Check that the maps haven't changed and find a Holder as a side effect. | 2208 // Check that the maps haven't changed and find a Holder as a side effect. |
2552 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2209 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, name, |
2553 depth, &miss); | 2210 depth, &miss); |
2554 | 2211 |
2555 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); | 2212 GenerateFastApiDirectCall(masm(), optimization, argc); |
2556 if (result->IsFailure()) return result; | |
2557 | 2213 |
2558 __ bind(&miss); | 2214 __ bind(&miss); |
2559 FreeSpaceForFastApiCall(masm()); | 2215 FreeSpaceForFastApiCall(masm()); |
2560 | 2216 |
2561 __ bind(&miss_before_stack_reserved); | 2217 __ bind(&miss_before_stack_reserved); |
2562 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2218 GenerateMissBranch(); |
2563 if (maybe_result->IsFailure()) return maybe_result; | |
2564 | 2219 |
2565 // Return the generated code. | 2220 // Return the generated code. |
2566 return TryGetCode(function); | 2221 return GetCode(function); |
2567 } | 2222 } |
2568 | 2223 |
2569 | 2224 |
2570 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2225 Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, |
2571 JSObject* holder, | 2226 Handle<JSObject> holder, |
2572 JSFunction* function, | 2227 Handle<JSFunction> function, |
2573 String* name, | 2228 Handle<String> name, |
2574 CheckType check) { | 2229 CheckType check) { |
2575 // ----------- S t a t e ------------- | 2230 // ----------- S t a t e ------------- |
2576 // -- r2 : name | 2231 // -- r2 : name |
2577 // -- lr : return address | 2232 // -- lr : return address |
2578 // ----------------------------------- | 2233 // ----------------------------------- |
2579 if (HasCustomCallGenerator(function)) { | 2234 if (HasCustomCallGenerator(function)) { |
2580 MaybeObject* maybe_result = CompileCustomCall( | 2235 Handle<Code> code = CompileCustomCall(object, holder, |
2581 object, holder, NULL, function, name); | 2236 Handle<JSGlobalPropertyCell>::null(), |
2582 Object* result; | 2237 function, name); |
2583 if (!maybe_result->ToObject(&result)) return maybe_result; | 2238 // A null handle means bail out to the regular compiler code below. |
2584 // undefined means bail out to regular compiler. | 2239 if (!code.is_null()) return code; |
2585 if (!result->IsUndefined()) return result; | |
2586 } | 2240 } |
2587 | 2241 |
2588 Label miss; | 2242 Label miss; |
2589 | 2243 GenerateNameCheck(name, &miss); |
2590 GenerateNameCheck(Handle<String>(name), &miss); | |
2591 | 2244 |
2592 // Get the receiver from the stack | 2245 // Get the receiver from the stack |
2593 const int argc = arguments().immediate(); | 2246 const int argc = arguments().immediate(); |
2594 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2247 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
2595 | 2248 |
2596 // Check that the receiver isn't a smi. | 2249 // Check that the receiver isn't a smi. |
2597 if (check != NUMBER_CHECK) { | 2250 if (check != NUMBER_CHECK) { |
2598 __ JumpIfSmi(r1, &miss); | 2251 __ JumpIfSmi(r1, &miss); |
2599 } | 2252 } |
2600 | 2253 |
2601 // Make sure that it's okay not to patch the on stack receiver | 2254 // Make sure that it's okay not to patch the on stack receiver |
2602 // unless we're doing a receiver map check. | 2255 // unless we're doing a receiver map check. |
2603 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2256 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2604 | |
2605 SharedFunctionInfo* function_info = function->shared(); | |
2606 switch (check) { | 2257 switch (check) { |
2607 case RECEIVER_MAP_CHECK: | 2258 case RECEIVER_MAP_CHECK: |
2608 __ IncrementCounter(masm()->isolate()->counters()->call_const(), | 2259 __ IncrementCounter(masm()->isolate()->counters()->call_const(), |
2609 1, r0, r3); | 2260 1, r0, r3); |
2610 | 2261 |
2611 // Check that the maps haven't changed. | 2262 // Check that the maps haven't changed. |
2612 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, | 2263 CheckPrototypes(Handle<JSObject>::cast(object), r1, holder, r0, r3, r4, |
2613 &miss); | 2264 name, &miss); |
2614 | 2265 |
2615 // Patch the receiver on the stack with the global proxy if | 2266 // Patch the receiver on the stack with the global proxy if |
2616 // necessary. | 2267 // necessary. |
2617 if (object->IsGlobalObject()) { | 2268 if (object->IsGlobalObject()) { |
2618 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2269 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
2619 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 2270 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
2620 } | 2271 } |
2621 break; | 2272 break; |
2622 | 2273 |
2623 case STRING_CHECK: | 2274 case STRING_CHECK: |
2624 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2275 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
2625 // Calling non-strict non-builtins with a value as the receiver | |
2626 // requires boxing. | |
2627 __ jmp(&miss); | |
2628 } else { | |
2629 // Check that the object is a two-byte string or a symbol. | 2276 // Check that the object is a two-byte string or a symbol. |
2630 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); | 2277 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); |
2631 __ b(ge, &miss); | 2278 __ b(ge, &miss); |
2632 // Check that the maps starting from the prototype haven't changed. | 2279 // Check that the maps starting from the prototype haven't changed. |
2633 GenerateDirectLoadGlobalFunctionPrototype( | 2280 GenerateDirectLoadGlobalFunctionPrototype( |
2634 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); | 2281 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); |
2635 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2282 CheckPrototypes( |
2636 r1, r4, name, &miss); | 2283 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
2284 r0, holder, r3, r1, r4, name, &miss); | |
2285 } else { | |
2286 // Calling non-strict non-builtins with a value as the receiver | |
2287 // requires boxing. | |
2288 __ jmp(&miss); | |
2637 } | 2289 } |
2638 break; | 2290 break; |
2639 | 2291 |
2640 case NUMBER_CHECK: { | 2292 case NUMBER_CHECK: |
2641 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2293 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
2642 // Calling non-strict non-builtins with a value as the receiver | |
2643 // requires boxing. | |
2644 __ jmp(&miss); | |
2645 } else { | |
2646 Label fast; | 2294 Label fast; |
2647 // Check that the object is a smi or a heap number. | 2295 // Check that the object is a smi or a heap number. |
2648 __ JumpIfSmi(r1, &fast); | 2296 __ JumpIfSmi(r1, &fast); |
2649 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); | 2297 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); |
2650 __ b(ne, &miss); | 2298 __ b(ne, &miss); |
2651 __ bind(&fast); | 2299 __ bind(&fast); |
2652 // Check that the maps starting from the prototype haven't changed. | 2300 // Check that the maps starting from the prototype haven't changed. |
2653 GenerateDirectLoadGlobalFunctionPrototype( | 2301 GenerateDirectLoadGlobalFunctionPrototype( |
2654 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); | 2302 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); |
2655 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2303 CheckPrototypes( |
2656 r1, r4, name, &miss); | 2304 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
2657 } | 2305 r0, holder, r3, r1, r4, name, &miss); |
2658 break; | 2306 } else { |
2659 } | |
2660 | |
2661 case BOOLEAN_CHECK: { | |
2662 if (!function->IsBuiltin() && !function_info->strict_mode()) { | |
2663 // Calling non-strict non-builtins with a value as the receiver | 2307 // Calling non-strict non-builtins with a value as the receiver |
2664 // requires boxing. | 2308 // requires boxing. |
2665 __ jmp(&miss); | 2309 __ jmp(&miss); |
2666 } else { | 2310 } |
2311 break; | |
2312 | |
2313 case BOOLEAN_CHECK: | |
2314 if (function->IsBuiltin() || function->shared()->strict_mode()) { | |
2667 Label fast; | 2315 Label fast; |
2668 // Check that the object is a boolean. | 2316 // Check that the object is a boolean. |
2669 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 2317 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
2670 __ cmp(r1, ip); | 2318 __ cmp(r1, ip); |
2671 __ b(eq, &fast); | 2319 __ b(eq, &fast); |
2672 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 2320 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
2673 __ cmp(r1, ip); | 2321 __ cmp(r1, ip); |
2674 __ b(ne, &miss); | 2322 __ b(ne, &miss); |
2675 __ bind(&fast); | 2323 __ bind(&fast); |
2676 // Check that the maps starting from the prototype haven't changed. | 2324 // Check that the maps starting from the prototype haven't changed. |
2677 GenerateDirectLoadGlobalFunctionPrototype( | 2325 GenerateDirectLoadGlobalFunctionPrototype( |
2678 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); | 2326 masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); |
2679 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, | 2327 CheckPrototypes( |
2680 r1, r4, name, &miss); | 2328 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
2329 r0, holder, r3, r1, r4, name, &miss); | |
2330 } else { | |
2331 // Calling non-strict non-builtins with a value as the receiver | |
2332 // requires boxing. | |
2333 __ jmp(&miss); | |
2681 } | 2334 } |
2682 break; | 2335 break; |
2683 } | |
2684 | |
2685 default: | |
2686 UNREACHABLE(); | |
ulan
2011/10/27 10:10:26
Wouldn't it be helpful in future if CheckType is e
Kevin Millikin (Chromium)
2011/10/27 10:53:43
Actually the opposite.
default: UNREACHABLE() can
| |
2687 } | 2336 } |
2688 | 2337 |
2689 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2338 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2690 ? CALL_AS_FUNCTION | 2339 ? CALL_AS_FUNCTION |
2691 : CALL_AS_METHOD; | 2340 : CALL_AS_METHOD; |
2692 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); | 2341 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); |
2693 | 2342 |
2694 // Handle call cache miss. | 2343 // Handle call cache miss. |
2695 __ bind(&miss); | 2344 __ bind(&miss); |
2696 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2345 GenerateMissBranch(); |
2697 if (maybe_result->IsFailure()) return maybe_result; | |
2698 | 2346 |
2699 // Return the generated code. | 2347 // Return the generated code. |
2700 return TryGetCode(function); | 2348 return GetCode(function); |
2701 } | 2349 } |
2702 | 2350 |
2703 | 2351 |
2704 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2352 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2705 JSObject* holder, | 2353 Handle<JSObject> holder, |
2706 String* name) { | 2354 Handle<String> name) { |
2707 // ----------- S t a t e ------------- | 2355 // ----------- S t a t e ------------- |
2708 // -- r2 : name | 2356 // -- r2 : name |
2709 // -- lr : return address | 2357 // -- lr : return address |
2710 // ----------------------------------- | 2358 // ----------------------------------- |
2711 | |
2712 Label miss; | 2359 Label miss; |
2713 | 2360 GenerateNameCheck(name, &miss); |
2714 GenerateNameCheck(Handle<String>(name), &miss); | |
2715 | 2361 |
2716 // Get the number of arguments. | 2362 // Get the number of arguments. |
2717 const int argc = arguments().immediate(); | 2363 const int argc = arguments().immediate(); |
2718 | |
2719 LookupResult lookup(isolate()); | 2364 LookupResult lookup(isolate()); |
2720 LookupPostInterceptor(holder, name, &lookup); | 2365 LookupPostInterceptor(holder, name, &lookup); |
2721 | 2366 |
2722 // Get the receiver from the stack. | 2367 // Get the receiver from the stack. |
2723 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2368 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
2724 | 2369 |
2725 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); | 2370 CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); |
2726 MaybeObject* result = compiler.Compile(masm(), | 2371 compiler.Compile(masm(), object, holder, name, &lookup, r1, r3, r4, r0, |
2727 object, | 2372 &miss); |
2728 holder, | |
2729 name, | |
2730 &lookup, | |
2731 r1, | |
2732 r3, | |
2733 r4, | |
2734 r0, | |
2735 &miss); | |
2736 if (result->IsFailure()) { | |
2737 return result; | |
2738 } | |
2739 | 2373 |
2740 // Move returned value, the function to call, to r1. | 2374 // Move returned value, the function to call, to r1. |
2741 __ mov(r1, r0); | 2375 __ mov(r1, r0); |
2742 // Restore receiver. | 2376 // Restore receiver. |
2743 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 2377 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
2744 | 2378 |
2745 GenerateCallFunction(masm(), Handle<Object>(object), arguments(), &miss, | 2379 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
2746 extra_state_); | |
2747 | 2380 |
2748 // Handle call cache miss. | 2381 // Handle call cache miss. |
2749 __ bind(&miss); | 2382 __ bind(&miss); |
2750 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2383 GenerateMissBranch(); |
2751 if (maybe_result->IsFailure()) return maybe_result; | |
2752 | 2384 |
2753 // Return the generated code. | 2385 // Return the generated code. |
2754 return TryGetCode(INTERCEPTOR, name); | 2386 return GetCode(INTERCEPTOR, name); |
2755 } | 2387 } |
2756 | 2388 |
2757 | 2389 |
2758 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, | 2390 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2759 GlobalObject* holder, | 2391 Handle<JSObject> object, |
2760 JSGlobalPropertyCell* cell, | 2392 Handle<GlobalObject> holder, |
2761 JSFunction* function, | 2393 Handle<JSGlobalPropertyCell> cell, |
2762 String* name) { | 2394 Handle<JSFunction> function, |
2395 Handle<String> name) { | |
2763 // ----------- S t a t e ------------- | 2396 // ----------- S t a t e ------------- |
2764 // -- r2 : name | 2397 // -- r2 : name |
2765 // -- lr : return address | 2398 // -- lr : return address |
2766 // ----------------------------------- | 2399 // ----------------------------------- |
2767 | |
2768 if (HasCustomCallGenerator(function)) { | 2400 if (HasCustomCallGenerator(function)) { |
2769 MaybeObject* maybe_result = CompileCustomCall( | 2401 Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); |
2770 object, holder, cell, function, name); | 2402 // A null handle means bail out to the regular compiler code below. |
2771 Object* result; | 2403 if (!code.is_null()) return code; |
2772 if (!maybe_result->ToObject(&result)) return maybe_result; | |
2773 // undefined means bail out to regular compiler. | |
2774 if (!result->IsUndefined()) return result; | |
2775 } | 2404 } |
2776 | 2405 |
2777 Label miss; | 2406 Label miss; |
2778 | 2407 GenerateNameCheck(name, &miss); |
2779 GenerateNameCheck(Handle<String>(name), &miss); | |
2780 | 2408 |
2781 // Get the number of arguments. | 2409 // Get the number of arguments. |
2782 const int argc = arguments().immediate(); | 2410 const int argc = arguments().immediate(); |
2783 | |
2784 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2411 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
2785 | |
2786 GenerateLoadFunctionFromCell(cell, function, &miss); | 2412 GenerateLoadFunctionFromCell(cell, function, &miss); |
2787 | 2413 |
2788 // Patch the receiver on the stack with the global proxy if | 2414 // Patch the receiver on the stack with the global proxy if |
2789 // necessary. | 2415 // necessary. |
2790 if (object->IsGlobalObject()) { | 2416 if (object->IsGlobalObject()) { |
2791 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 2417 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
2792 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 2418 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
2793 } | 2419 } |
2794 | 2420 |
2795 // Setup the context (function already in r1). | 2421 // Setup the context (function already in r1). |
2796 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 2422 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
2797 | 2423 |
2798 // Jump to the cached code (tail call). | 2424 // Jump to the cached code (tail call). |
2799 Counters* counters = masm()->isolate()->counters(); | 2425 Counters* counters = masm()->isolate()->counters(); |
2800 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); | 2426 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); |
2801 Handle<Code> code(function->code()); | |
2802 ParameterCount expected(function->shared()->formal_parameter_count()); | 2427 ParameterCount expected(function->shared()->formal_parameter_count()); |
2803 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2428 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2804 ? CALL_AS_FUNCTION | 2429 ? CALL_AS_FUNCTION |
2805 : CALL_AS_METHOD; | 2430 : CALL_AS_METHOD; |
2806 // We call indirectly through the code field in the function to | 2431 // We call indirectly through the code field in the function to |
2807 // allow recompilation to take effect without changing any of the | 2432 // allow recompilation to take effect without changing any of the |
2808 // call sites. | 2433 // call sites. |
2809 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 2434 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
2810 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, | 2435 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, |
2811 NullCallWrapper(), call_kind); | 2436 NullCallWrapper(), call_kind); |
2812 | 2437 |
2813 // Handle call cache miss. | 2438 // Handle call cache miss. |
2814 __ bind(&miss); | 2439 __ bind(&miss); |
2815 __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3); | 2440 __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3); |
2816 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2441 GenerateMissBranch(); |
2817 if (maybe_result->IsFailure()) return maybe_result; | |
2818 | 2442 |
2819 // Return the generated code. | 2443 // Return the generated code. |
2820 return TryGetCode(NORMAL, name); | 2444 return GetCode(NORMAL, name); |
2821 } | 2445 } |
2822 | 2446 |
2823 | 2447 |
2824 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 2448 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
2825 int index, | 2449 int index, |
2826 Handle<Map> transition, | 2450 Handle<Map> transition, |
2827 Handle<String> name) { | 2451 Handle<String> name) { |
2828 // ----------- S t a t e ------------- | 2452 // ----------- S t a t e ------------- |
2829 // -- r0 : value | 2453 // -- r0 : value |
2830 // -- r1 : receiver | 2454 // -- r1 : receiver |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3043 | 2667 |
3044 GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss); | 2668 GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss); |
3045 __ bind(&miss); | 2669 __ bind(&miss); |
3046 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2670 GenerateLoadMiss(masm(), Code::LOAD_IC); |
3047 | 2671 |
3048 // Return the generated code. | 2672 // Return the generated code. |
3049 return GetCode(FIELD, name); | 2673 return GetCode(FIELD, name); |
3050 } | 2674 } |
3051 | 2675 |
3052 | 2676 |
3053 MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, | 2677 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
3054 JSObject* object, | 2678 Handle<String> name, |
3055 JSObject* holder, | 2679 Handle<JSObject> object, |
3056 AccessorInfo* callback) { | 2680 Handle<JSObject> holder, |
2681 Handle<AccessorInfo> callback) { | |
3057 // ----------- S t a t e ------------- | 2682 // ----------- S t a t e ------------- |
3058 // -- r0 : receiver | 2683 // -- r0 : receiver |
3059 // -- r2 : name | 2684 // -- r2 : name |
3060 // -- lr : return address | 2685 // -- lr : return address |
3061 // ----------------------------------- | 2686 // ----------------------------------- |
3062 Label miss; | 2687 Label miss; |
3063 | 2688 GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, callback, name, |
3064 MaybeObject* result = GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, | 2689 &miss); |
3065 callback, name, &miss); | |
3066 if (result->IsFailure()) { | |
3067 miss.Unuse(); | |
3068 return result; | |
3069 } | |
3070 | |
3071 __ bind(&miss); | 2690 __ bind(&miss); |
3072 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2691 GenerateLoadMiss(masm(), Code::LOAD_IC); |
3073 | 2692 |
3074 // Return the generated code. | 2693 // Return the generated code. |
3075 return TryGetCode(CALLBACKS, name); | 2694 return GetCode(CALLBACKS, name); |
3076 } | 2695 } |
3077 | 2696 |
3078 | 2697 |
3079 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, | 2698 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
3080 Handle<JSObject> holder, | 2699 Handle<JSObject> holder, |
3081 Handle<Object> value, | 2700 Handle<Object> value, |
3082 Handle<String> name) { | 2701 Handle<String> name) { |
3083 // ----------- S t a t e ------------- | 2702 // ----------- S t a t e ------------- |
3084 // -- r0 : receiver | 2703 // -- r0 : receiver |
3085 // -- r2 : name | 2704 // -- r2 : name |
3086 // -- lr : return address | 2705 // -- lr : return address |
3087 // ----------------------------------- | 2706 // ----------------------------------- |
3088 Label miss; | 2707 Label miss; |
3089 | 2708 |
3090 GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss); | 2709 GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss); |
3091 __ bind(&miss); | 2710 __ bind(&miss); |
3092 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2711 GenerateLoadMiss(masm(), Code::LOAD_IC); |
3093 | 2712 |
3094 // Return the generated code. | 2713 // Return the generated code. |
3095 return GetCode(CONSTANT_FUNCTION, name); | 2714 return GetCode(CONSTANT_FUNCTION, name); |
3096 } | 2715 } |
3097 | 2716 |
3098 | 2717 |
3099 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, | 2718 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object, |
3100 JSObject* holder, | 2719 Handle<JSObject> holder, |
3101 String* name) { | 2720 Handle<String> name) { |
3102 // ----------- S t a t e ------------- | 2721 // ----------- S t a t e ------------- |
3103 // -- r0 : receiver | 2722 // -- r0 : receiver |
3104 // -- r2 : name | 2723 // -- r2 : name |
3105 // -- lr : return address | 2724 // -- lr : return address |
3106 // ----------------------------------- | 2725 // ----------------------------------- |
3107 Label miss; | 2726 Label miss; |
3108 | 2727 |
3109 LookupResult lookup(isolate()); | 2728 LookupResult lookup(isolate()); |
3110 LookupPostInterceptor(holder, name, &lookup); | 2729 LookupPostInterceptor(holder, name, &lookup); |
3111 GenerateLoadInterceptor(object, | 2730 GenerateLoadInterceptor(object, holder, &lookup, r0, r2, r3, r1, r4, name, |
3112 holder, | |
3113 &lookup, | |
3114 r0, | |
3115 r2, | |
3116 r3, | |
3117 r1, | |
3118 r4, | |
3119 name, | |
3120 &miss); | 2731 &miss); |
3121 __ bind(&miss); | 2732 __ bind(&miss); |
3122 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2733 GenerateLoadMiss(masm(), Code::LOAD_IC); |
3123 | 2734 |
3124 // Return the generated code. | 2735 // Return the generated code. |
3125 return TryGetCode(INTERCEPTOR, name); | 2736 return GetCode(INTERCEPTOR, name); |
3126 } | 2737 } |
3127 | 2738 |
3128 | 2739 |
3129 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2740 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
3130 Handle<JSObject> object, | 2741 Handle<JSObject> object, |
3131 Handle<GlobalObject> holder, | 2742 Handle<GlobalObject> holder, |
3132 Handle<JSGlobalPropertyCell> cell, | 2743 Handle<JSGlobalPropertyCell> cell, |
3133 Handle<String> name, | 2744 Handle<String> name, |
3134 bool is_dont_delete) { | 2745 bool is_dont_delete) { |
3135 // ----------- S t a t e ------------- | 2746 // ----------- S t a t e ------------- |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3190 __ b(ne, &miss); | 2801 __ b(ne, &miss); |
3191 | 2802 |
3192 GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); | 2803 GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); |
3193 __ bind(&miss); | 2804 __ bind(&miss); |
3194 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2805 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3195 | 2806 |
3196 return GetCode(FIELD, name); | 2807 return GetCode(FIELD, name); |
3197 } | 2808 } |
3198 | 2809 |
3199 | 2810 |
3200 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2811 Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( |
3201 String* name, | 2812 Handle<String> name, |
3202 JSObject* receiver, | 2813 Handle<JSObject> receiver, |
3203 JSObject* holder, | 2814 Handle<JSObject> holder, |
3204 AccessorInfo* callback) { | 2815 Handle<AccessorInfo> callback) { |
3205 // ----------- S t a t e ------------- | 2816 // ----------- S t a t e ------------- |
3206 // -- lr : return address | 2817 // -- lr : return address |
3207 // -- r0 : key | 2818 // -- r0 : key |
3208 // -- r1 : receiver | 2819 // -- r1 : receiver |
3209 // ----------------------------------- | 2820 // ----------------------------------- |
3210 Label miss; | 2821 Label miss; |
3211 | 2822 |
3212 // Check the key is the cached one. | 2823 // Check the key is the cached one. |
3213 __ cmp(r0, Operand(Handle<String>(name))); | 2824 __ cmp(r0, Operand(name)); |
3214 __ b(ne, &miss); | 2825 __ b(ne, &miss); |
3215 | 2826 |
3216 MaybeObject* result = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, | 2827 GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, callback, name, |
3217 r4, callback, name, &miss); | 2828 &miss); |
3218 if (result->IsFailure()) { | |
3219 miss.Unuse(); | |
3220 return result; | |
3221 } | |
3222 | |
3223 __ bind(&miss); | 2829 __ bind(&miss); |
3224 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2830 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3225 | 2831 |
3226 return TryGetCode(CALLBACKS, name); | 2832 return GetCode(CALLBACKS, name); |
3227 } | 2833 } |
3228 | 2834 |
3229 | 2835 |
3230 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( | 2836 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
3231 Handle<String> name, | 2837 Handle<String> name, |
3232 Handle<JSObject> receiver, | 2838 Handle<JSObject> receiver, |
3233 Handle<JSObject> holder, | 2839 Handle<JSObject> holder, |
3234 Handle<Object> value) { | 2840 Handle<Object> value) { |
3235 // ----------- S t a t e ------------- | 2841 // ----------- S t a t e ------------- |
3236 // -- lr : return address | 2842 // -- lr : return address |
3237 // -- r0 : key | 2843 // -- r0 : key |
3238 // -- r1 : receiver | 2844 // -- r1 : receiver |
3239 // ----------------------------------- | 2845 // ----------------------------------- |
3240 Label miss; | 2846 Label miss; |
3241 | 2847 |
3242 // Check the key is the cached one. | 2848 // Check the key is the cached one. |
3243 __ cmp(r0, Operand(name)); | 2849 __ cmp(r0, Operand(name)); |
3244 __ b(ne, &miss); | 2850 __ b(ne, &miss); |
3245 | 2851 |
3246 GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); | 2852 GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); |
3247 __ bind(&miss); | 2853 __ bind(&miss); |
3248 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2854 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3249 | 2855 |
3250 // Return the generated code. | 2856 // Return the generated code. |
3251 return GetCode(CONSTANT_FUNCTION, name); | 2857 return GetCode(CONSTANT_FUNCTION, name); |
3252 } | 2858 } |
3253 | 2859 |
3254 | 2860 |
3255 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2861 Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
3256 JSObject* holder, | 2862 Handle<JSObject> receiver, |
3257 String* name) { | 2863 Handle<JSObject> holder, |
2864 Handle<String> name) { | |
3258 // ----------- S t a t e ------------- | 2865 // ----------- S t a t e ------------- |
3259 // -- lr : return address | 2866 // -- lr : return address |
3260 // -- r0 : key | 2867 // -- r0 : key |
3261 // -- r1 : receiver | 2868 // -- r1 : receiver |
3262 // ----------------------------------- | 2869 // ----------------------------------- |
3263 Label miss; | 2870 Label miss; |
3264 | 2871 |
3265 // Check the key is the cached one. | 2872 // Check the key is the cached one. |
3266 __ cmp(r0, Operand(Handle<String>(name))); | 2873 __ cmp(r0, Operand(name)); |
3267 __ b(ne, &miss); | 2874 __ b(ne, &miss); |
3268 | 2875 |
3269 LookupResult lookup(isolate()); | 2876 LookupResult lookup(isolate()); |
3270 LookupPostInterceptor(holder, name, &lookup); | 2877 LookupPostInterceptor(holder, name, &lookup); |
3271 GenerateLoadInterceptor(receiver, | 2878 GenerateLoadInterceptor(receiver, holder, &lookup, r1, r0, r2, r3, r4, name, |
3272 holder, | |
3273 &lookup, | |
3274 r1, | |
3275 r0, | |
3276 r2, | |
3277 r3, | |
3278 r4, | |
3279 name, | |
3280 &miss); | 2879 &miss); |
3281 __ bind(&miss); | 2880 __ bind(&miss); |
3282 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2881 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3283 | 2882 |
3284 return TryGetCode(INTERCEPTOR, name); | 2883 return GetCode(INTERCEPTOR, name); |
3285 } | 2884 } |
3286 | 2885 |
3287 | 2886 |
3288 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( | 2887 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
3289 Handle<String> name) { | 2888 Handle<String> name) { |
3290 // ----------- S t a t e ------------- | 2889 // ----------- S t a t e ------------- |
3291 // -- lr : return address | 2890 // -- lr : return address |
3292 // -- r0 : key | 2891 // -- r0 : key |
3293 // -- r1 : receiver | 2892 // -- r1 : receiver |
3294 // ----------------------------------- | 2893 // ----------------------------------- |
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4036 // -- lr : return address | 3635 // -- lr : return address |
4037 // -- r0 : key | 3636 // -- r0 : key |
4038 // -- r1 : receiver | 3637 // -- r1 : receiver |
4039 // ----------------------------------- | 3638 // ----------------------------------- |
4040 | 3639 |
4041 __ Push(r1, r0); | 3640 __ Push(r1, r0); |
4042 | 3641 |
4043 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 3642 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
4044 | 3643 |
4045 __ bind(&miss_force_generic); | 3644 __ bind(&miss_force_generic); |
4046 Code* stub = masm->isolate()->builtins()->builtin( | 3645 Handle<Code> stub = |
4047 Builtins::kKeyedLoadIC_MissForceGeneric); | 3646 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
4048 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); | 3647 __ Jump(stub, RelocInfo::CODE_TARGET); |
4049 } | 3648 } |
4050 | 3649 |
4051 | 3650 |
4052 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3651 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
4053 MacroAssembler* masm, | 3652 MacroAssembler* masm, |
4054 ElementsKind elements_kind) { | 3653 ElementsKind elements_kind) { |
4055 // ---------- S t a t e -------------- | 3654 // ---------- S t a t e -------------- |
4056 // -- r0 : value | 3655 // -- r0 : value |
4057 // -- r1 : key | 3656 // -- r1 : key |
4058 // -- r2 : receiver | 3657 // -- r2 : receiver |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4412 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | 4011 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
4413 __ ldr(r4, | 4012 __ ldr(r4, |
4414 MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 4013 MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
4415 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 4014 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
4416 __ cmp(r4, ip); | 4015 __ cmp(r4, ip); |
4417 __ b(eq, &miss_force_generic); | 4016 __ b(eq, &miss_force_generic); |
4418 __ mov(r0, r4); | 4017 __ mov(r0, r4); |
4419 __ Ret(); | 4018 __ Ret(); |
4420 | 4019 |
4421 __ bind(&miss_force_generic); | 4020 __ bind(&miss_force_generic); |
4422 Code* stub = masm->isolate()->builtins()->builtin( | 4021 Handle<Code> stub = |
4423 Builtins::kKeyedLoadIC_MissForceGeneric); | 4022 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
4424 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); | 4023 __ Jump(stub, RelocInfo::CODE_TARGET); |
4425 } | 4024 } |
4426 | 4025 |
4427 | 4026 |
4428 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( | 4027 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( |
4429 MacroAssembler* masm) { | 4028 MacroAssembler* masm) { |
4430 // ----------- S t a t e ------------- | 4029 // ----------- S t a t e ------------- |
4431 // -- lr : return address | 4030 // -- lr : return address |
4432 // -- r0 : key | 4031 // -- r0 : key |
4433 // -- r1 : receiver | 4032 // -- r1 : receiver |
4434 // ----------------------------------- | 4033 // ----------------------------------- |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4646 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4245 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
4647 __ Jump(ic_miss, RelocInfo::CODE_TARGET); | 4246 __ Jump(ic_miss, RelocInfo::CODE_TARGET); |
4648 } | 4247 } |
4649 | 4248 |
4650 | 4249 |
4651 #undef __ | 4250 #undef __ |
4652 | 4251 |
4653 } } // namespace v8::internal | 4252 } } // namespace v8::internal |
4654 | 4253 |
4655 #endif // V8_TARGET_ARCH_ARM | 4254 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |