OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 | 87 |
88 // Jump to the first instruction in the code stub. | 88 // Jump to the first instruction in the code stub. |
89 __ Daddu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag)); | 89 __ Daddu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag)); |
90 __ Jump(at); | 90 __ Jump(at); |
91 | 91 |
92 // Miss: fall through. | 92 // Miss: fall through. |
93 __ bind(&miss); | 93 __ bind(&miss); |
94 } | 94 } |
95 | 95 |
96 | 96 |
97 void StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 97 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
98 Label* miss_label, | 98 MacroAssembler* masm, Label* miss_label, Register receiver, |
99 Register receiver, | 99 Handle<Name> name, Register scratch0, Register scratch1) { |
100 Handle<Name> name, | |
101 Register scratch0, | |
102 Register scratch1) { | |
103 ASSERT(name->IsUniqueName()); | 100 ASSERT(name->IsUniqueName()); |
104 ASSERT(!receiver.is(scratch0)); | 101 ASSERT(!receiver.is(scratch0)); |
105 Counters* counters = masm->isolate()->counters(); | 102 Counters* counters = masm->isolate()->counters(); |
106 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 103 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
107 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 104 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
108 | 105 |
109 Label done; | 106 Label done; |
110 | 107 |
111 const int kInterceptorOrAccessCheckNeededMask = | 108 const int kInterceptorOrAccessCheckNeededMask = |
112 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 109 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 extra3); | 230 extra3); |
234 | 231 |
235 // Cache miss: Fall-through and let caller handle the miss by | 232 // Cache miss: Fall-through and let caller handle the miss by |
236 // entering the runtime system. | 233 // entering the runtime system. |
237 __ bind(&miss); | 234 __ bind(&miss); |
238 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, | 235 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, |
239 extra2, extra3); | 236 extra2, extra3); |
240 } | 237 } |
241 | 238 |
242 | 239 |
243 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 240 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
244 int index, | 241 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
245 Register prototype) { | |
246 // Load the global or builtins object from the current context. | |
247 __ ld(prototype, | |
248 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
249 // Load the native context from the global or builtins object. | |
250 __ ld(prototype, | |
251 FieldMemOperand(prototype, GlobalObject::kNativeContextOffset)); | |
252 // Load the function from the native context. | |
253 __ ld(prototype, MemOperand(prototype, Context::SlotOffset(index))); | |
254 // Load the initial map. The global functions all have initial maps. | |
255 __ ld(prototype, | |
256 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); | |
257 // Load the prototype from the initial map. | |
258 __ ld(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | |
259 } | |
260 | |
261 | |
262 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | |
263 MacroAssembler* masm, | |
264 int index, | |
265 Register prototype, | |
266 Label* miss) { | |
267 Isolate* isolate = masm->isolate(); | 242 Isolate* isolate = masm->isolate(); |
268 // Get the global function with the given index. | 243 // Get the global function with the given index. |
269 Handle<JSFunction> function( | 244 Handle<JSFunction> function( |
270 JSFunction::cast(isolate->native_context()->get(index))); | 245 JSFunction::cast(isolate->native_context()->get(index))); |
271 | 246 |
272 // Check we're still in the same context. | 247 // Check we're still in the same context. |
273 Register scratch = prototype; | 248 Register scratch = prototype; |
274 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); | 249 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
275 __ ld(scratch, MemOperand(cp, offset)); | 250 __ ld(scratch, MemOperand(cp, offset)); |
276 __ ld(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); | 251 __ ld(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
277 __ ld(scratch, MemOperand(scratch, Context::SlotOffset(index))); | 252 __ ld(scratch, MemOperand(scratch, Context::SlotOffset(index))); |
278 __ li(at, function); | 253 __ li(at, function); |
279 __ Branch(miss, ne, at, Operand(scratch)); | 254 __ Branch(miss, ne, at, Operand(scratch)); |
280 | 255 |
281 // Load its initial map. The global functions all have initial maps. | 256 // Load its initial map. The global functions all have initial maps. |
282 __ li(prototype, Handle<Map>(function->initial_map())); | 257 __ li(prototype, Handle<Map>(function->initial_map())); |
283 // Load the prototype from the initial map. | 258 // Load the prototype from the initial map. |
284 __ ld(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 259 __ ld(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
285 } | 260 } |
286 | 261 |
287 | 262 |
288 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 263 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
289 Register dst, | 264 MacroAssembler* masm, Register receiver, Register scratch1, |
290 Register src, | 265 Register scratch2, Label* miss_label) { |
291 bool inobject, | |
292 int index, | |
293 Representation representation) { | |
294 ASSERT(!representation.IsDouble()); | |
295 int offset = index * kPointerSize; | |
296 if (!inobject) { | |
297 // Calculate the offset into the properties array. | |
298 offset = offset + FixedArray::kHeaderSize; | |
299 __ ld(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); | |
300 src = dst; | |
301 } | |
302 __ ld(dst, FieldMemOperand(src, offset)); | |
303 } | |
304 | |
305 | |
306 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | |
307 Register receiver, | |
308 Register scratch, | |
309 Label* miss_label) { | |
310 // Check that the receiver isn't a smi. | |
311 __ JumpIfSmi(receiver, miss_label); | |
312 | |
313 // Check that the object is a JS array. | |
314 __ GetObjectType(receiver, scratch, scratch); | |
315 __ Branch(miss_label, ne, scratch, Operand(JS_ARRAY_TYPE)); | |
316 | |
317 // Load length directly from the JS array. | |
318 __ Ret(USE_DELAY_SLOT); | |
319 __ ld(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
320 } | |
321 | |
322 | |
323 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | |
324 Register receiver, | |
325 Register scratch1, | |
326 Register scratch2, | |
327 Label* miss_label) { | |
328 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 266 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
329 __ Ret(USE_DELAY_SLOT); | 267 __ Ret(USE_DELAY_SLOT); |
330 __ mov(v0, scratch1); | 268 __ mov(v0, scratch1); |
331 } | 269 } |
332 | 270 |
333 | 271 |
334 void StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm, | 272 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
335 Handle<JSGlobalObject> global, | 273 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
336 Handle<Name> name, | 274 Register scratch, Label* miss) { |
337 Register scratch, | |
338 Label* miss) { | |
339 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 275 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
340 ASSERT(cell->value()->IsTheHole()); | 276 ASSERT(cell->value()->IsTheHole()); |
341 __ li(scratch, Operand(cell)); | 277 __ li(scratch, Operand(cell)); |
342 __ ld(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 278 __ ld(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
343 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 279 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
344 __ Branch(miss, ne, scratch, Operand(at)); | 280 __ Branch(miss, ne, scratch, Operand(at)); |
345 } | 281 } |
346 | 282 |
347 | 283 |
348 void StoreStubCompiler::GenerateNegativeHolderLookup( | 284 void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( |
349 MacroAssembler* masm, | 285 MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg, |
350 Handle<JSObject> holder, | 286 Handle<Name> name, Label* miss) { |
351 Register holder_reg, | |
352 Handle<Name> name, | |
353 Label* miss) { | |
354 if (holder->IsJSGlobalObject()) { | 287 if (holder->IsJSGlobalObject()) { |
355 GenerateCheckPropertyCell( | 288 GenerateCheckPropertyCell( |
356 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); | 289 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); |
357 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 290 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
358 GenerateDictionaryNegativeLookup( | 291 GenerateDictionaryNegativeLookup( |
359 masm, miss, holder_reg, name, scratch1(), scratch2()); | 292 masm, miss, holder_reg, name, scratch1(), scratch2()); |
360 } | 293 } |
361 } | 294 } |
362 | 295 |
363 | 296 |
364 // Generate StoreTransition code, value is passed in a0 register. | 297 // Generate StoreTransition code, value is passed in a0 register. |
365 // After executing generated code, the receiver_reg and name_reg | 298 // After executing generated code, the receiver_reg and name_reg |
366 // may be clobbered. | 299 // may be clobbered. |
367 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 300 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
368 Handle<JSObject> object, | 301 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
369 LookupResult* lookup, | 302 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
370 Handle<Map> transition, | 303 Register storage_reg, Register value_reg, Register scratch1, |
371 Handle<Name> name, | 304 Register scratch2, Register scratch3, Label* miss_label, Label* slow) { |
372 Register receiver_reg, | |
373 Register storage_reg, | |
374 Register value_reg, | |
375 Register scratch1, | |
376 Register scratch2, | |
377 Register scratch3, | |
378 Label* miss_label, | |
379 Label* slow) { | |
380 // a0 : value. | 305 // a0 : value. |
381 Label exit; | 306 Label exit; |
382 | 307 |
383 int descriptor = transition->LastAdded(); | 308 int descriptor = transition->LastAdded(); |
384 DescriptorArray* descriptors = transition->instance_descriptors(); | 309 DescriptorArray* descriptors = transition->instance_descriptors(); |
385 PropertyDetails details = descriptors->GetDetails(descriptor); | 310 PropertyDetails details = descriptors->GetDetails(descriptor); |
386 Representation representation = details.representation(); | 311 Representation representation = details.representation(); |
387 ASSERT(!representation.IsNone()); | 312 ASSERT(!representation.IsNone()); |
388 | 313 |
389 if (details.type() == CONSTANT) { | 314 if (details.type() == CONSTANT) { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 __ bind(&exit); | 465 __ bind(&exit); |
541 __ Ret(USE_DELAY_SLOT); | 466 __ Ret(USE_DELAY_SLOT); |
542 __ mov(v0, a0); | 467 __ mov(v0, a0); |
543 } | 468 } |
544 | 469 |
545 | 470 |
546 // Generate StoreField code, value is passed in a0 register. | 471 // Generate StoreField code, value is passed in a0 register. |
547 // When leaving generated code after success, the receiver_reg and name_reg | 472 // When leaving generated code after success, the receiver_reg and name_reg |
548 // may be clobbered. Upon branch to miss_label, the receiver and name | 473 // may be clobbered. Upon branch to miss_label, the receiver and name |
549 // registers have their original values. | 474 // registers have their original values. |
550 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 475 void NamedStoreHandlerCompiler::GenerateStoreField( |
551 Handle<JSObject> object, | 476 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
552 LookupResult* lookup, | 477 Register receiver_reg, Register name_reg, Register value_reg, |
553 Register receiver_reg, | 478 Register scratch1, Register scratch2, Label* miss_label) { |
554 Register name_reg, | |
555 Register value_reg, | |
556 Register scratch1, | |
557 Register scratch2, | |
558 Label* miss_label) { | |
559 // a0 : value | 479 // a0 : value |
560 Label exit; | 480 Label exit; |
561 | 481 |
562 // Stub never generated for non-global objects that require access | 482 // Stub never generated for non-global objects that require access |
563 // checks. | 483 // checks. |
564 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 484 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
565 | 485 |
566 FieldIndex index = lookup->GetFieldIndex(); | 486 FieldIndex index = lookup->GetFieldIndex(); |
567 | 487 |
568 Representation representation = lookup->representation(); | 488 Representation representation = lookup->representation(); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 } | 590 } |
671 | 591 |
672 // Return the value (register v0). | 592 // Return the value (register v0). |
673 ASSERT(value_reg.is(a0)); | 593 ASSERT(value_reg.is(a0)); |
674 __ bind(&exit); | 594 __ bind(&exit); |
675 __ Ret(USE_DELAY_SLOT); | 595 __ Ret(USE_DELAY_SLOT); |
676 __ mov(v0, a0); | 596 __ mov(v0, a0); |
677 } | 597 } |
678 | 598 |
679 | 599 |
680 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 600 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, |
681 Label* label, | 601 Label* label, |
682 Handle<Name> name) { | 602 Handle<Name> name) { |
683 if (!label->is_unused()) { | 603 if (!label->is_unused()) { |
684 __ bind(label); | 604 __ bind(label); |
685 __ li(this->name(), Operand(name)); | 605 __ li(this->name(), Operand(name)); |
686 } | 606 } |
687 } | 607 } |
688 | 608 |
689 | 609 |
690 static void PushInterceptorArguments(MacroAssembler* masm, | 610 static void PushInterceptorArguments(MacroAssembler* masm, |
691 Register receiver, | 611 Register receiver, |
692 Register holder, | 612 Register holder, |
(...skipping 21 matching lines...) Expand all Loading... |
714 Handle<JSObject> holder_obj, | 634 Handle<JSObject> holder_obj, |
715 IC::UtilityId id) { | 635 IC::UtilityId id) { |
716 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 636 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
717 __ CallExternalReference( | 637 __ CallExternalReference( |
718 ExternalReference(IC_Utility(id), masm->isolate()), | 638 ExternalReference(IC_Utility(id), masm->isolate()), |
719 StubCache::kInterceptorArgsLength); | 639 StubCache::kInterceptorArgsLength); |
720 } | 640 } |
721 | 641 |
722 | 642 |
723 // Generate call to api function. | 643 // Generate call to api function. |
724 void StubCompiler::GenerateFastApiCall(MacroAssembler* masm, | 644 void PropertyHandlerCompiler::GenerateFastApiCall( |
725 const CallOptimization& optimization, | 645 MacroAssembler* masm, const CallOptimization& optimization, |
726 Handle<Map> receiver_map, | 646 Handle<Map> receiver_map, Register receiver, Register scratch_in, |
727 Register receiver, | 647 bool is_store, int argc, Register* values) { |
728 Register scratch_in, | |
729 bool is_store, | |
730 int argc, | |
731 Register* values) { | |
732 ASSERT(!receiver.is(scratch_in)); | 648 ASSERT(!receiver.is(scratch_in)); |
733 // Preparing to push, adjust sp. | 649 // Preparing to push, adjust sp. |
734 __ Dsubu(sp, sp, Operand((argc + 1) * kPointerSize)); | 650 __ Dsubu(sp, sp, Operand((argc + 1) * kPointerSize)); |
735 __ sd(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver. | 651 __ sd(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver. |
736 // Write the arguments to stack frame. | 652 // Write the arguments to stack frame. |
737 for (int i = 0; i < argc; i++) { | 653 for (int i = 0; i < argc; i++) { |
738 Register arg = values[argc-1-i]; | 654 Register arg = values[argc-1-i]; |
739 ASSERT(!receiver.is(arg)); | 655 ASSERT(!receiver.is(arg)); |
740 ASSERT(!scratch_in.is(arg)); | 656 ASSERT(!scratch_in.is(arg)); |
741 __ sd(arg, MemOperand(sp, (argc-1-i) * kPointerSize)); // Push arg. | 657 __ sd(arg, MemOperand(sp, (argc-1-i) * kPointerSize)); // Push arg. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 type, | 709 type, |
794 masm->isolate()); | 710 masm->isolate()); |
795 __ li(api_function_address, Operand(ref)); | 711 __ li(api_function_address, Operand(ref)); |
796 | 712 |
797 // Jump to stub. | 713 // Jump to stub. |
798 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 714 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
799 __ TailCallStub(&stub); | 715 __ TailCallStub(&stub); |
800 } | 716 } |
801 | 717 |
802 | 718 |
803 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 719 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
| 720 Handle<Code> code) { |
804 __ Jump(code, RelocInfo::CODE_TARGET); | 721 __ Jump(code, RelocInfo::CODE_TARGET); |
805 } | 722 } |
806 | 723 |
807 | 724 |
808 #undef __ | 725 #undef __ |
809 #define __ ACCESS_MASM(masm()) | 726 #define __ ACCESS_MASM(masm()) |
810 | 727 |
811 | 728 |
812 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 729 Register PropertyHandlerCompiler::CheckPrototypes( |
813 Register object_reg, | 730 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, |
814 Handle<JSObject> holder, | 731 Register holder_reg, Register scratch1, Register scratch2, |
815 Register holder_reg, | 732 Handle<Name> name, Label* miss, PrototypeCheckType check) { |
816 Register scratch1, | |
817 Register scratch2, | |
818 Handle<Name> name, | |
819 Label* miss, | |
820 PrototypeCheckType check) { | |
821 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 733 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
822 | 734 |
823 // Make sure there's no overlap between holder and object registers. | 735 // Make sure there's no overlap between holder and object registers. |
824 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 736 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
825 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 737 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
826 && !scratch2.is(scratch1)); | 738 && !scratch2.is(scratch1)); |
827 | 739 |
828 // Keep track of the current object in register reg. | 740 // Keep track of the current object in register reg. |
829 Register reg = object_reg; | 741 Register reg = object_reg; |
830 int depth = 0; | 742 int depth = 0; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
917 !current_map->is_access_check_needed()); | 829 !current_map->is_access_check_needed()); |
918 if (current_map->IsJSGlobalProxyMap()) { | 830 if (current_map->IsJSGlobalProxyMap()) { |
919 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 831 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
920 } | 832 } |
921 | 833 |
922 // Return the register containing the holder. | 834 // Return the register containing the holder. |
923 return reg; | 835 return reg; |
924 } | 836 } |
925 | 837 |
926 | 838 |
927 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 839 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
928 if (!miss->is_unused()) { | 840 if (!miss->is_unused()) { |
929 Label success; | 841 Label success; |
930 __ Branch(&success); | 842 __ Branch(&success); |
931 __ bind(miss); | 843 __ bind(miss); |
932 TailCallBuiltin(masm(), MissBuiltin(kind())); | 844 TailCallBuiltin(masm(), MissBuiltin(kind())); |
933 __ bind(&success); | 845 __ bind(&success); |
934 } | 846 } |
935 } | 847 } |
936 | 848 |
937 | 849 |
938 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 850 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
939 if (!miss->is_unused()) { | 851 if (!miss->is_unused()) { |
940 Label success; | 852 Label success; |
941 __ Branch(&success); | 853 __ Branch(&success); |
942 GenerateRestoreName(masm(), miss, name); | 854 GenerateRestoreName(masm(), miss, name); |
943 TailCallBuiltin(masm(), MissBuiltin(kind())); | 855 TailCallBuiltin(masm(), MissBuiltin(kind())); |
944 __ bind(&success); | 856 __ bind(&success); |
945 } | 857 } |
946 } | 858 } |
947 | 859 |
948 | 860 |
949 Register LoadStubCompiler::CallbackHandlerFrontend( | 861 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
950 Handle<HeapType> type, | 862 Register object_reg, |
951 Register object_reg, | 863 Handle<JSObject> holder, |
952 Handle<JSObject> holder, | 864 Handle<Name> name, |
953 Handle<Name> name, | 865 Handle<Object> callback) { |
954 Handle<Object> callback) { | |
955 Label miss; | 866 Label miss; |
956 | 867 |
957 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 868 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); |
958 | 869 |
959 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 870 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
960 ASSERT(!reg.is(scratch2())); | 871 ASSERT(!reg.is(scratch2())); |
961 ASSERT(!reg.is(scratch3())); | 872 ASSERT(!reg.is(scratch3())); |
962 ASSERT(!reg.is(scratch4())); | 873 ASSERT(!reg.is(scratch4())); |
963 | 874 |
964 // Load the properties dictionary. | 875 // Load the properties dictionary. |
965 Register dictionary = scratch4(); | 876 Register dictionary = scratch4(); |
966 __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 877 __ ld(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
967 | 878 |
(...skipping 11 matching lines...) Expand all Loading... |
979 // If probing finds an entry in the dictionary, scratch3 contains the | 890 // If probing finds an entry in the dictionary, scratch3 contains the |
980 // pointer into the dictionary. Check that the value is the callback. | 891 // pointer into the dictionary. Check that the value is the callback. |
981 Register pointer = scratch3(); | 892 Register pointer = scratch3(); |
982 const int kElementsStartOffset = NameDictionary::kHeaderSize + | 893 const int kElementsStartOffset = NameDictionary::kHeaderSize + |
983 NameDictionary::kElementsStartIndex * kPointerSize; | 894 NameDictionary::kElementsStartIndex * kPointerSize; |
984 const int kValueOffset = kElementsStartOffset + kPointerSize; | 895 const int kValueOffset = kElementsStartOffset + kPointerSize; |
985 __ ld(scratch2(), FieldMemOperand(pointer, kValueOffset)); | 896 __ ld(scratch2(), FieldMemOperand(pointer, kValueOffset)); |
986 __ Branch(&miss, ne, scratch2(), Operand(callback)); | 897 __ Branch(&miss, ne, scratch2(), Operand(callback)); |
987 } | 898 } |
988 | 899 |
989 HandlerFrontendFooter(name, &miss); | 900 FrontendFooter(name, &miss); |
990 return reg; | 901 return reg; |
991 } | 902 } |
992 | 903 |
993 | 904 |
994 void LoadStubCompiler::GenerateLoadField(Register reg, | 905 void NamedLoadHandlerCompiler::GenerateLoadField( |
995 Handle<JSObject> holder, | 906 Register reg, Handle<JSObject> holder, FieldIndex field, |
996 FieldIndex field, | 907 Representation representation) { |
997 Representation representation) { | |
998 if (!reg.is(receiver())) __ mov(receiver(), reg); | 908 if (!reg.is(receiver())) __ mov(receiver(), reg); |
999 LoadFieldStub stub(isolate(), field); | 909 LoadFieldStub stub(isolate(), field); |
1000 GenerateTailCall(masm(), stub.GetCode()); | 910 GenerateTailCall(masm(), stub.GetCode()); |
1001 } | 911 } |
1002 | 912 |
1003 | 913 |
1004 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 914 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
1005 // Return the constant value. | 915 // Return the constant value. |
1006 __ li(v0, value); | 916 __ li(v0, value); |
1007 __ Ret(); | 917 __ Ret(); |
1008 } | 918 } |
1009 | 919 |
1010 | 920 |
1011 void LoadStubCompiler::GenerateLoadCallback( | 921 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
1012 Register reg, | 922 Register reg, Handle<ExecutableAccessorInfo> callback) { |
1013 Handle<ExecutableAccessorInfo> callback) { | |
1014 // Build AccessorInfo::args_ list on the stack and push property name below | 923 // Build AccessorInfo::args_ list on the stack and push property name below |
1015 // the exit frame to make GC aware of them and store pointers to them. | 924 // the exit frame to make GC aware of them and store pointers to them. |
1016 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 925 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
1017 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 926 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
1018 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 927 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
1019 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 928 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
1020 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 929 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
1021 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 930 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
1022 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); | 931 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); |
1023 ASSERT(!scratch2().is(reg)); | 932 ASSERT(!scratch2().is(reg)); |
(...skipping 27 matching lines...) Expand all Loading... |
1051 ApiFunction fun(getter_address); | 960 ApiFunction fun(getter_address); |
1052 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 961 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
1053 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 962 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
1054 __ li(getter_address_reg, Operand(ref)); | 963 __ li(getter_address_reg, Operand(ref)); |
1055 | 964 |
1056 CallApiGetterStub stub(isolate()); | 965 CallApiGetterStub stub(isolate()); |
1057 __ TailCallStub(&stub); | 966 __ TailCallStub(&stub); |
1058 } | 967 } |
1059 | 968 |
1060 | 969 |
1061 void LoadStubCompiler::GenerateLoadInterceptor( | 970 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
1062 Register holder_reg, | 971 Register holder_reg, Handle<Object> object, |
1063 Handle<Object> object, | 972 Handle<JSObject> interceptor_holder, LookupResult* lookup, |
1064 Handle<JSObject> interceptor_holder, | |
1065 LookupResult* lookup, | |
1066 Handle<Name> name) { | 973 Handle<Name> name) { |
1067 ASSERT(interceptor_holder->HasNamedInterceptor()); | 974 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1068 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 975 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1069 | 976 |
1070 // So far the most popular follow ups for interceptor loads are FIELD | 977 // So far the most popular follow ups for interceptor loads are FIELD |
1071 // and CALLBACKS, so inline only them, other cases may be added | 978 // and CALLBACKS, so inline only them, other cases may be added |
1072 // later. | 979 // later. |
1073 bool compile_followup_inline = false; | 980 bool compile_followup_inline = false; |
1074 if (lookup->IsFound() && lookup->IsCacheable()) { | 981 if (lookup->IsFound() && lookup->IsCacheable()) { |
1075 if (lookup->IsField()) { | 982 if (lookup->IsField()) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1136 PushInterceptorArguments(masm(), receiver(), holder_reg, | 1043 PushInterceptorArguments(masm(), receiver(), holder_reg, |
1137 this->name(), interceptor_holder); | 1044 this->name(), interceptor_holder); |
1138 | 1045 |
1139 ExternalReference ref = ExternalReference( | 1046 ExternalReference ref = ExternalReference( |
1140 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); | 1047 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); |
1141 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); | 1048 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
1142 } | 1049 } |
1143 } | 1050 } |
1144 | 1051 |
1145 | 1052 |
1146 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1053 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1147 Handle<JSObject> object, | 1054 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
1148 Handle<JSObject> holder, | |
1149 Handle<Name> name, | |
1150 Handle<ExecutableAccessorInfo> callback) { | 1055 Handle<ExecutableAccessorInfo> callback) { |
1151 Register holder_reg = HandlerFrontend( | 1056 Register holder_reg = |
1152 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | 1057 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
1153 | 1058 |
1154 // Stub never generated for non-global objects that require access | 1059 // Stub never generated for non-global objects that require access |
1155 // checks. | 1060 // checks. |
1156 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1061 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1157 | 1062 |
1158 __ Push(receiver(), holder_reg); // Receiver. | 1063 __ Push(receiver(), holder_reg); // Receiver. |
1159 __ li(at, Operand(callback)); // Callback info. | 1064 __ li(at, Operand(callback)); // Callback info. |
1160 __ push(at); | 1065 __ push(at); |
1161 __ li(at, Operand(name)); | 1066 __ li(at, Operand(name)); |
1162 __ Push(at, value()); | 1067 __ Push(at, value()); |
1163 | 1068 |
1164 // Do tail-call to the runtime system. | 1069 // Do tail-call to the runtime system. |
1165 ExternalReference store_callback_property = | 1070 ExternalReference store_callback_property = |
1166 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 1071 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
1167 __ TailCallExternalReference(store_callback_property, 5, 1); | 1072 __ TailCallExternalReference(store_callback_property, 5, 1); |
1168 | 1073 |
1169 // Return the generated code. | 1074 // Return the generated code. |
1170 return GetCode(kind(), Code::FAST, name); | 1075 return GetCode(kind(), Code::FAST, name); |
1171 } | 1076 } |
1172 | 1077 |
1173 | 1078 |
1174 #undef __ | 1079 #undef __ |
1175 #define __ ACCESS_MASM(masm) | 1080 #define __ ACCESS_MASM(masm) |
1176 | 1081 |
1177 | 1082 |
1178 void StoreStubCompiler::GenerateStoreViaSetter( | 1083 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
1179 MacroAssembler* masm, | 1084 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
1180 Handle<HeapType> type, | |
1181 Register receiver, | |
1182 Handle<JSFunction> setter) { | 1085 Handle<JSFunction> setter) { |
1183 // ----------- S t a t e ------------- | 1086 // ----------- S t a t e ------------- |
1184 // -- ra : return address | 1087 // -- ra : return address |
1185 // ----------------------------------- | 1088 // ----------------------------------- |
1186 { | 1089 { |
1187 FrameScope scope(masm, StackFrame::INTERNAL); | 1090 FrameScope scope(masm, StackFrame::INTERNAL); |
1188 | 1091 |
1189 // Save value register, so we can restore it later. | 1092 // Save value register, so we can restore it later. |
1190 __ push(value()); | 1093 __ push(value()); |
1191 | 1094 |
(...skipping 22 matching lines...) Expand all Loading... |
1214 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1117 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1215 } | 1118 } |
1216 __ Ret(); | 1119 __ Ret(); |
1217 } | 1120 } |
1218 | 1121 |
1219 | 1122 |
1220 #undef __ | 1123 #undef __ |
1221 #define __ ACCESS_MASM(masm()) | 1124 #define __ ACCESS_MASM(masm()) |
1222 | 1125 |
1223 | 1126 |
1224 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 1127 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1225 Handle<JSObject> object, | 1128 Handle<JSObject> object, Handle<Name> name) { |
1226 Handle<Name> name) { | |
1227 __ Push(receiver(), this->name(), value()); | 1129 __ Push(receiver(), this->name(), value()); |
1228 | 1130 |
1229 // Do tail-call to the runtime system. | 1131 // Do tail-call to the runtime system. |
1230 ExternalReference store_ic_property = | 1132 ExternalReference store_ic_property = |
1231 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 1133 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
1232 __ TailCallExternalReference(store_ic_property, 3, 1); | 1134 __ TailCallExternalReference(store_ic_property, 3, 1); |
1233 | 1135 |
1234 // Return the generated code. | 1136 // Return the generated code. |
1235 return GetCode(kind(), Code::FAST, name); | 1137 return GetCode(kind(), Code::FAST, name); |
1236 } | 1138 } |
1237 | 1139 |
1238 | 1140 |
1239 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, | 1141 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1240 Handle<JSObject> last, | 1142 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { |
1241 Handle<Name> name) { | 1143 NonexistentFrontend(type, last, name); |
1242 NonexistentHandlerFrontend(type, last, name); | |
1243 | 1144 |
1244 // Return undefined if maps of the full prototype chain is still the same. | 1145 // Return undefined if maps of the full prototype chain is still the same. |
1245 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 1146 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
1246 __ Ret(); | 1147 __ Ret(); |
1247 | 1148 |
1248 // Return the generated code. | 1149 // Return the generated code. |
1249 return GetCode(kind(), Code::FAST, name); | 1150 return GetCode(kind(), Code::FAST, name); |
1250 } | 1151 } |
1251 | 1152 |
1252 | 1153 |
1253 Register* LoadStubCompiler::registers() { | 1154 Register* PropertyAccessCompiler::load_calling_convention() { |
1254 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1155 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
1255 Register receiver = LoadIC::ReceiverRegister(); | 1156 Register receiver = LoadIC::ReceiverRegister(); |
1256 Register name = LoadIC::NameRegister(); | 1157 Register name = LoadIC::NameRegister(); |
1257 static Register registers[] = { receiver, name, a3, a0, a4, a5 }; | 1158 static Register registers[] = { receiver, name, a3, a0, a4, a5 }; |
1258 return registers; | 1159 return registers; |
1259 } | 1160 } |
1260 | 1161 |
1261 | 1162 |
1262 Register* KeyedLoadStubCompiler::registers() { | 1163 Register* PropertyAccessCompiler::store_calling_convention() { |
1263 // receiver, name, scratch1, scratch2, scratch3, scratch4. | |
1264 Register receiver = LoadIC::ReceiverRegister(); | |
1265 Register name = LoadIC::NameRegister(); | |
1266 static Register registers[] = { receiver, name, a3, a0, a4, a5 }; | |
1267 return registers; | |
1268 } | |
1269 | |
1270 | |
1271 Register StoreStubCompiler::value() { | |
1272 return StoreIC::ValueRegister(); | |
1273 } | |
1274 | |
1275 | |
1276 Register* StoreStubCompiler::registers() { | |
1277 // receiver, name, scratch1, scratch2, scratch3. | 1164 // receiver, name, scratch1, scratch2, scratch3. |
1278 Register receiver = StoreIC::ReceiverRegister(); | 1165 Register receiver = StoreIC::ReceiverRegister(); |
1279 Register name = StoreIC::NameRegister(); | 1166 Register name = StoreIC::NameRegister(); |
1280 static Register registers[] = { receiver, name, a3, a4, a5 }; | 1167 static Register registers[] = { receiver, name, a3, a4, a5 }; |
1281 return registers; | 1168 return registers; |
1282 } | 1169 } |
1283 | 1170 |
1284 | 1171 |
1285 Register* KeyedStoreStubCompiler::registers() { | 1172 Register* PropertyAccessCompiler::keyed_store_calling_convention() { |
1286 // receiver, name, scratch1/map, scratch2, scratch3. | 1173 // receiver, name, scratch1/map, scratch2, scratch3. |
1287 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1174 Register receiver = KeyedStoreIC::ReceiverRegister(); |
1288 Register name = KeyedStoreIC::NameRegister(); | 1175 Register name = KeyedStoreIC::NameRegister(); |
1289 Register map = KeyedStoreIC::MapRegister(); | 1176 Register map = KeyedStoreIC::MapRegister(); |
1290 static Register registers[] = { receiver, name, map, a4, a5 }; | 1177 static Register registers[] = { receiver, name, map, a4, a5 }; |
1291 return registers; | 1178 return registers; |
1292 } | 1179 } |
1293 | 1180 |
1294 | 1181 |
| 1182 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1183 |
| 1184 |
1295 #undef __ | 1185 #undef __ |
1296 #define __ ACCESS_MASM(masm) | 1186 #define __ ACCESS_MASM(masm) |
1297 | 1187 |
1298 | 1188 |
1299 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1189 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
1300 Handle<HeapType> type, | 1190 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
1301 Register receiver, | 1191 Handle<JSFunction> getter) { |
1302 Handle<JSFunction> getter) { | |
1303 // ----------- S t a t e ------------- | 1192 // ----------- S t a t e ------------- |
1304 // -- a0 : receiver | 1193 // -- a0 : receiver |
1305 // -- a2 : name | 1194 // -- a2 : name |
1306 // -- ra : return address | 1195 // -- ra : return address |
1307 // ----------------------------------- | 1196 // ----------------------------------- |
1308 { | 1197 { |
1309 FrameScope scope(masm, StackFrame::INTERNAL); | 1198 FrameScope scope(masm, StackFrame::INTERNAL); |
1310 | 1199 |
1311 if (!getter.is_null()) { | 1200 if (!getter.is_null()) { |
1312 // Call the JavaScript getter with the receiver on the stack. | 1201 // Call the JavaScript getter with the receiver on the stack. |
(...skipping 17 matching lines...) Expand all Loading... |
1330 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1219 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1331 } | 1220 } |
1332 __ Ret(); | 1221 __ Ret(); |
1333 } | 1222 } |
1334 | 1223 |
1335 | 1224 |
1336 #undef __ | 1225 #undef __ |
1337 #define __ ACCESS_MASM(masm()) | 1226 #define __ ACCESS_MASM(masm()) |
1338 | 1227 |
1339 | 1228 |
1340 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 1229 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1341 Handle<HeapType> type, | 1230 Handle<HeapType> type, Handle<GlobalObject> global, |
1342 Handle<GlobalObject> global, | 1231 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1343 Handle<PropertyCell> cell, | |
1344 Handle<Name> name, | |
1345 bool is_dont_delete) { | |
1346 Label miss; | 1232 Label miss; |
1347 | 1233 |
1348 HandlerFrontendHeader(type, receiver(), global, name, &miss); | 1234 FrontendHeader(type, receiver(), global, name, &miss); |
1349 | 1235 |
1350 // Get the value from the cell. | 1236 // Get the value from the cell. |
1351 __ li(a3, Operand(cell)); | 1237 __ li(a3, Operand(cell)); |
1352 __ ld(a4, FieldMemOperand(a3, Cell::kValueOffset)); | 1238 __ ld(a4, FieldMemOperand(a3, Cell::kValueOffset)); |
1353 | 1239 |
1354 // Check for deleted property if property can actually be deleted. | 1240 // Check for deleted property if property can actually be deleted. |
1355 if (!is_dont_delete) { | 1241 if (!is_dont_delete) { |
1356 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1242 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
1357 __ Branch(&miss, eq, a4, Operand(at)); | 1243 __ Branch(&miss, eq, a4, Operand(at)); |
1358 } | 1244 } |
1359 | 1245 |
1360 Counters* counters = isolate()->counters(); | 1246 Counters* counters = isolate()->counters(); |
1361 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); | 1247 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); |
1362 __ Ret(USE_DELAY_SLOT); | 1248 __ Ret(USE_DELAY_SLOT); |
1363 __ mov(v0, a4); | 1249 __ mov(v0, a4); |
1364 | 1250 |
1365 HandlerFrontendFooter(name, &miss); | 1251 FrontendFooter(name, &miss); |
1366 | 1252 |
1367 // Return the generated code. | 1253 // Return the generated code. |
1368 return GetCode(kind(), Code::NORMAL, name); | 1254 return GetCode(kind(), Code::NORMAL, name); |
1369 } | 1255 } |
1370 | 1256 |
1371 | 1257 |
1372 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 1258 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
1373 TypeHandleList* types, | 1259 CodeHandleList* handlers, |
1374 CodeHandleList* handlers, | 1260 Handle<Name> name, |
1375 Handle<Name> name, | 1261 Code::StubType type, |
1376 Code::StubType type, | 1262 IcCheckType check) { |
1377 IcCheckType check) { | |
1378 Label miss; | 1263 Label miss; |
1379 | 1264 |
1380 if (check == PROPERTY && | 1265 if (check == PROPERTY && |
1381 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | 1266 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { |
1382 __ Branch(&miss, ne, this->name(), Operand(name)); | 1267 __ Branch(&miss, ne, this->name(), Operand(name)); |
1383 } | 1268 } |
1384 | 1269 |
1385 Label number_case; | 1270 Label number_case; |
1386 Register match = scratch2(); | 1271 Register match = scratch2(); |
1387 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1272 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
(...skipping 24 matching lines...) Expand all Loading... |
1412 } | 1297 } |
1413 } | 1298 } |
1414 ASSERT(number_of_handled_maps != 0); | 1299 ASSERT(number_of_handled_maps != 0); |
1415 | 1300 |
1416 __ bind(&miss); | 1301 __ bind(&miss); |
1417 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1302 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1418 | 1303 |
1419 // Return the generated code. | 1304 // Return the generated code. |
1420 InlineCacheState state = | 1305 InlineCacheState state = |
1421 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 1306 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
1422 return GetICCode(kind(), type, name, state); | 1307 return GetCode(kind(), type, name, state); |
1423 } | 1308 } |
1424 | 1309 |
1425 | 1310 |
1426 void StoreStubCompiler::GenerateStoreArrayLength() { | 1311 void NamedStoreHandlerCompiler::GenerateStoreArrayLength() { |
1427 // Prepare tail call to StoreIC_ArrayLength. | 1312 // Prepare tail call to StoreIC_ArrayLength. |
1428 __ Push(receiver(), value()); | 1313 __ Push(receiver(), value()); |
1429 | 1314 |
1430 ExternalReference ref = | 1315 ExternalReference ref = |
1431 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), | 1316 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), |
1432 masm()->isolate()); | 1317 masm()->isolate()); |
1433 __ TailCallExternalReference(ref, 2, 1); | 1318 __ TailCallExternalReference(ref, 2, 1); |
1434 } | 1319 } |
1435 | 1320 |
1436 | 1321 |
1437 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 1322 Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( |
1438 MapHandleList* receiver_maps, | 1323 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
1439 CodeHandleList* handler_stubs, | |
1440 MapHandleList* transitioned_maps) { | 1324 MapHandleList* transitioned_maps) { |
1441 Label miss; | 1325 Label miss; |
1442 __ JumpIfSmi(receiver(), &miss); | 1326 __ JumpIfSmi(receiver(), &miss); |
1443 | 1327 |
1444 int receiver_count = receiver_maps->length(); | 1328 int receiver_count = receiver_maps->length(); |
1445 __ ld(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset)); | 1329 __ ld(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
1446 for (int i = 0; i < receiver_count; ++i) { | 1330 for (int i = 0; i < receiver_count; ++i) { |
1447 if (transitioned_maps->at(i).is_null()) { | 1331 if (transitioned_maps->at(i).is_null()) { |
1448 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq, | 1332 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq, |
1449 scratch1(), Operand(receiver_maps->at(i))); | 1333 scratch1(), Operand(receiver_maps->at(i))); |
1450 } else { | 1334 } else { |
1451 Label next_map; | 1335 Label next_map; |
1452 __ Branch(&next_map, ne, scratch1(), Operand(receiver_maps->at(i))); | 1336 __ Branch(&next_map, ne, scratch1(), Operand(receiver_maps->at(i))); |
1453 __ li(transition_map(), Operand(transitioned_maps->at(i))); | 1337 __ li(transition_map(), Operand(transitioned_maps->at(i))); |
1454 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 1338 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
1455 __ bind(&next_map); | 1339 __ bind(&next_map); |
1456 } | 1340 } |
1457 } | 1341 } |
1458 | 1342 |
1459 __ bind(&miss); | 1343 __ bind(&miss); |
1460 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1344 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1461 | 1345 |
1462 // Return the generated code. | 1346 // Return the generated code. |
1463 return GetICCode( | 1347 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
1464 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
1465 } | 1348 } |
1466 | 1349 |
1467 | 1350 |
1468 #undef __ | 1351 #undef __ |
1469 #define __ ACCESS_MASM(masm) | 1352 #define __ ACCESS_MASM(masm) |
1470 | 1353 |
1471 | 1354 |
1472 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( | 1355 void IndexedHandlerCompiler::GenerateLoadDictionaryElement( |
1473 MacroAssembler* masm) { | 1356 MacroAssembler* masm) { |
1474 // The return address is in ra | 1357 // The return address is in ra |
1475 Label slow, miss; | 1358 Label slow, miss; |
1476 | 1359 |
1477 Register key = LoadIC::NameRegister(); | 1360 Register key = LoadIC::NameRegister(); |
1478 Register receiver = LoadIC::ReceiverRegister(); | 1361 Register receiver = LoadIC::ReceiverRegister(); |
1479 ASSERT(receiver.is(a1)); | 1362 ASSERT(receiver.is(a1)); |
1480 ASSERT(key.is(a2)); | 1363 ASSERT(key.is(a2)); |
1481 | 1364 |
1482 __ UntagAndJumpIfNotSmi(a6, key, &miss); | 1365 __ UntagAndJumpIfNotSmi(a6, key, &miss); |
(...skipping 15 matching lines...) Expand all Loading... |
1498 | 1381 |
1499 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1382 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1500 } | 1383 } |
1501 | 1384 |
1502 | 1385 |
1503 #undef __ | 1386 #undef __ |
1504 | 1387 |
1505 } } // namespace v8::internal | 1388 } } // namespace v8::internal |
1506 | 1389 |
1507 #endif // V8_TARGET_ARCH_MIPS64 | 1390 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |