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