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