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