Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: src/arm/ic-arm.cc

Issue 2441002: ARM: Add more logic to the generic keyed load stub... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 30 matching lines...) Expand all
41 namespace internal { 41 namespace internal {
42 42
43 43
44 // ---------------------------------------------------------------------------- 44 // ----------------------------------------------------------------------------
45 // Static IC stub generators. 45 // Static IC stub generators.
46 // 46 //
47 47
48 #define __ ACCESS_MASM(masm) 48 #define __ ACCESS_MASM(masm)
49 49
50 // Helper function used from LoadIC/CallIC GenerateNormal. 50 // Helper function used from LoadIC/CallIC GenerateNormal.
51 // receiver: Receiver. It is not clobbered if a jump to the miss label is
52 // done
53 // name: Property name. It is not clobbered if a jump to the miss label is
54 // done
55 // result: Register for the result. It is only updated if a jump to the miss
56 // label is not done. Can be the same as receiver or name clobbering
57 // one of these in the case of not jumping to the miss label.
58 // The three scratch registers need to be different from the receiver, name and
59 // result.
51 static void GenerateDictionaryLoad(MacroAssembler* masm, 60 static void GenerateDictionaryLoad(MacroAssembler* masm,
52 Label* miss, 61 Label* miss,
53 Register t0, 62 Register receiver,
54 Register t1) { 63 Register name,
55 // Register use: 64 Register result,
56 // 65 Register scratch1,
57 // t0 - used to hold the property dictionary. 66 Register scratch2,
58 // 67 Register scratch3,
59 // t1 - initially the receiver. 68 DictionaryCheck check_dictionary) {
60 // - holds the result on exit. 69 // Main use of the scratch registers.
61 // 70 // scratch1: Used to hold the property dictionary.
62 // r3 - used as temporary and to hold the capacity of the property 71 // scratch2: Used as temporary and to hold the capacity of the property
63 // dictionary. 72 // dictionary.
64 // 73 // scratch3: Used as temporary.
65 // r2 - initially holds the name of the property and is unchanged.
66 // r4 - used to hold the index into the property dictionary.
67 74
68 Label done; 75 Label done;
69 76
70 // Check for the absence of an interceptor. 77 // Check for the absence of an interceptor.
71 // Load the map into t0. 78 // Load the map into scratch1.
72 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset)); 79 __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kMapOffset));
73 80
74 // Bail out if the receiver has a named interceptor. 81 // Bail out if the receiver has a named interceptor.
75 __ ldrb(r3, FieldMemOperand(t0, Map::kBitFieldOffset)); 82 __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
76 __ tst(r3, Operand(1 << Map::kHasNamedInterceptor)); 83 __ tst(scratch2, Operand(1 << Map::kHasNamedInterceptor));
77 __ b(nz, miss); 84 __ b(nz, miss);
78 85
79 // Bail out if we have a JS global proxy object. 86 // Bail out if we have a JS global proxy object.
80 __ ldrb(r3, FieldMemOperand(t0, Map::kInstanceTypeOffset)); 87 __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
81 __ cmp(r3, Operand(JS_GLOBAL_PROXY_TYPE)); 88 __ cmp(scratch2, Operand(JS_GLOBAL_PROXY_TYPE));
82 __ b(eq, miss); 89 __ b(eq, miss);
83 90
84 // Possible work-around for http://crbug.com/16276. 91 // Possible work-around for http://crbug.com/16276.
85 // See also: http://codereview.chromium.org/155418. 92 // See also: http://codereview.chromium.org/155418.
86 __ cmp(r3, Operand(JS_GLOBAL_OBJECT_TYPE)); 93 __ cmp(scratch2, Operand(JS_GLOBAL_OBJECT_TYPE));
87 __ b(eq, miss); 94 __ b(eq, miss);
88 __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE)); 95 __ cmp(scratch2, Operand(JS_BUILTINS_OBJECT_TYPE));
89 __ b(eq, miss); 96 __ b(eq, miss);
90 97
98 // Load the properties array.
99 __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
100
91 // Check that the properties array is a dictionary. 101 // Check that the properties array is a dictionary.
92 __ ldr(t0, FieldMemOperand(t1, JSObject::kPropertiesOffset)); 102 if (check_dictionary == CHECK_DICTIONARY) {
93 __ ldr(r3, FieldMemOperand(t0, HeapObject::kMapOffset)); 103 __ ldr(scratch2, FieldMemOperand(scratch1, HeapObject::kMapOffset));
94 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 104 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
95 __ cmp(r3, ip); 105 __ cmp(scratch2, ip);
96 __ b(ne, miss); 106 __ b(ne, miss);
107 }
97 108
98 // Compute the capacity mask. 109 // Compute the capacity mask.
99 const int kCapacityOffset = StringDictionary::kHeaderSize + 110 const int kCapacityOffset = StringDictionary::kHeaderSize +
100 StringDictionary::kCapacityIndex * kPointerSize; 111 StringDictionary::kCapacityIndex * kPointerSize;
101 __ ldr(r3, FieldMemOperand(t0, kCapacityOffset)); 112 __ ldr(scratch2, FieldMemOperand(scratch1, kCapacityOffset));
102 __ mov(r3, Operand(r3, ASR, kSmiTagSize)); // convert smi to int 113 __ mov(scratch2, Operand(scratch2, ASR, kSmiTagSize)); // convert smi to int
103 __ sub(r3, r3, Operand(1)); 114 __ sub(scratch2, scratch2, Operand(1));
104 115
105 const int kElementsStartOffset = StringDictionary::kHeaderSize + 116 const int kElementsStartOffset = StringDictionary::kHeaderSize +
106 StringDictionary::kElementsStartIndex * kPointerSize; 117 StringDictionary::kElementsStartIndex * kPointerSize;
107 118
108 // Generate an unrolled loop that performs a few probes before 119 // Generate an unrolled loop that performs a few probes before
109 // giving up. Measurements done on Gmail indicate that 2 probes 120 // giving up. Measurements done on Gmail indicate that 2 probes
110 // cover ~93% of loads from dictionaries. 121 // cover ~93% of loads from dictionaries.
111 static const int kProbes = 4; 122 static const int kProbes = 4;
112 for (int i = 0; i < kProbes; i++) { 123 for (int i = 0; i < kProbes; i++) {
113 // Compute the masked index: (hash + i + i * i) & mask. 124 // Compute the masked index: (hash + i + i * i) & mask.
114 __ ldr(r4, FieldMemOperand(r2, String::kHashFieldOffset)); 125 __ ldr(scratch3, FieldMemOperand(name, String::kHashFieldOffset));
115 if (i > 0) { 126 if (i > 0) {
116 // Add the probe offset (i + i * i) left shifted to avoid right shifting 127 // Add the probe offset (i + i * i) left shifted to avoid right shifting
117 // the hash in a separate instruction. The value hash + i + i * i is right 128 // the hash in a separate instruction. The value hash + i + i * i is right
118 // shifted in the following and instruction. 129 // shifted in the following and instruction.
119 ASSERT(StringDictionary::GetProbeOffset(i) < 130 ASSERT(StringDictionary::GetProbeOffset(i) <
120 1 << (32 - String::kHashFieldOffset)); 131 1 << (32 - String::kHashFieldOffset));
121 __ add(r4, r4, Operand( 132 __ add(scratch3, scratch3, Operand(
122 StringDictionary::GetProbeOffset(i) << String::kHashShift)); 133 StringDictionary::GetProbeOffset(i) << String::kHashShift));
123 } 134 }
124 __ and_(r4, r3, Operand(r4, LSR, String::kHashShift)); 135 __ and_(scratch3, scratch2, Operand(scratch3, LSR, String::kHashShift));
125 136
126 // Scale the index by multiplying by the element size. 137 // Scale the index by multiplying by the element size.
127 ASSERT(StringDictionary::kEntrySize == 3); 138 ASSERT(StringDictionary::kEntrySize == 3);
128 __ add(r4, r4, Operand(r4, LSL, 1)); // r4 = r4 * 3 139 // scratch3 = scratch3 * 3.
140 __ add(scratch3, scratch3, Operand(scratch3, LSL, 1));
129 141
130 // Check if the key is identical to the name. 142 // Check if the key is identical to the name.
131 __ add(r4, t0, Operand(r4, LSL, 2)); 143 __ add(scratch3, scratch1, Operand(scratch3, LSL, 2));
132 __ ldr(ip, FieldMemOperand(r4, kElementsStartOffset)); 144 __ ldr(ip, FieldMemOperand(scratch3, kElementsStartOffset));
133 __ cmp(r2, Operand(ip)); 145 __ cmp(name, Operand(ip));
134 if (i != kProbes - 1) { 146 if (i != kProbes - 1) {
135 __ b(eq, &done); 147 __ b(eq, &done);
136 } else { 148 } else {
137 __ b(ne, miss); 149 __ b(ne, miss);
138 } 150 }
139 } 151 }
140 152
141 // Check that the value is a normal property. 153 // Check that the value is a normal property.
142 __ bind(&done); // r4 == t0 + 4*index 154 __ bind(&done); // scratch3 == scratch1 + 4 * index
143 __ ldr(r3, FieldMemOperand(r4, kElementsStartOffset + 2 * kPointerSize)); 155 __ ldr(scratch2,
144 __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); 156 FieldMemOperand(scratch3, kElementsStartOffset + 2 * kPointerSize));
157 __ tst(scratch2, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
145 __ b(ne, miss); 158 __ b(ne, miss);
146 159
147 // Get the value at the masked, scaled index and return. 160 // Get the value at the masked, scaled index and return.
148 __ ldr(t1, FieldMemOperand(r4, kElementsStartOffset + 1 * kPointerSize)); 161 __ ldr(result,
162 FieldMemOperand(scratch3, kElementsStartOffset + 1 * kPointerSize));
149 } 163 }
150 164
151 165
152 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, 166 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
153 Label* miss, 167 Label* miss,
154 Register elements, 168 Register elements,
155 Register key, 169 Register key,
156 Register t0, 170 Register t0,
157 Register t1, 171 Register t1,
158 Register t2) { 172 Register t2) {
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 GenerateMiss(masm, argc); 360 GenerateMiss(masm, argc);
347 } 361 }
348 362
349 363
350 static void GenerateNormalHelper(MacroAssembler* masm, 364 static void GenerateNormalHelper(MacroAssembler* masm,
351 int argc, 365 int argc,
352 bool is_global_object, 366 bool is_global_object,
353 Label* miss, 367 Label* miss,
354 Register scratch) { 368 Register scratch) {
355 // Search dictionary - put result in register r1. 369 // Search dictionary - put result in register r1.
356 GenerateDictionaryLoad(masm, miss, r0, r1); 370 GenerateDictionaryLoad(masm, miss, r1, r2, r1, r0, r3, r4, CHECK_DICTIONARY);
357 371
358 // Check that the value isn't a smi. 372 // Check that the value isn't a smi.
359 __ tst(r1, Operand(kSmiTagMask)); 373 __ tst(r1, Operand(kSmiTagMask));
360 __ b(eq, miss); 374 __ b(eq, miss);
361 375
362 // Check that the value is a JSFunction. 376 // Check that the value is a JSFunction.
363 __ CompareObjectType(r1, scratch, scratch, JS_FUNCTION_TYPE); 377 __ CompareObjectType(r1, scratch, scratch, JS_FUNCTION_TYPE);
364 __ b(ne, miss); 378 __ b(ne, miss);
365 379
366 // Patch the receiver with the global proxy if necessary. 380 // Patch the receiver with the global proxy if necessary.
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 // Check for access to global object (unlikely). 540 // Check for access to global object (unlikely).
527 __ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE)); 541 __ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE));
528 __ b(eq, &global); 542 __ b(eq, &global);
529 543
530 // Check for non-global object that requires access check. 544 // Check for non-global object that requires access check.
531 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset)); 545 __ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
532 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded)); 546 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
533 __ b(ne, &miss); 547 __ b(ne, &miss);
534 548
535 __ bind(&probe); 549 __ bind(&probe);
536 GenerateDictionaryLoad(masm, &miss, r1, r0); 550 GenerateDictionaryLoad(masm, &miss, r0, r2, r0, r1, r3, r4, CHECK_DICTIONARY);
537 __ Ret(); 551 __ Ret();
538 552
539 // Global object access: Check access rights. 553 // Global object access: Check access rights.
540 __ bind(&global); 554 __ bind(&global);
541 __ CheckAccessGlobalProxy(r0, r1, &miss); 555 __ CheckAccessGlobalProxy(r0, r1, &miss);
542 __ b(&probe); 556 __ b(&probe);
543 557
544 // Cache miss: Jump to runtime. 558 // Cache miss: Jump to runtime.
545 __ bind(&miss); 559 __ bind(&miss);
546 GenerateMiss(masm); 560 GenerateMiss(masm);
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 721
708 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 722 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
709 // ---------- S t a t e -------------- 723 // ---------- S t a t e --------------
710 // -- lr : return address 724 // -- lr : return address
711 // -- r0 : key 725 // -- r0 : key
712 // -- r1 : receiver 726 // -- r1 : receiver
713 // ----------------------------------- 727 // -----------------------------------
714 728
715 __ Push(r1, r0); 729 __ Push(r1, r0);
716 730
717 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); 731 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
718 } 732 }
719 733
720 734
721 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 735 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
722 // ---------- S t a t e -------------- 736 // ---------- S t a t e --------------
723 // -- lr : return address 737 // -- lr : return address
724 // -- r0 : key 738 // -- r0 : key
725 // -- r1 : receiver 739 // -- r1 : receiver
726 // ----------------------------------- 740 // -----------------------------------
727 Label slow, fast, check_pixel_array, check_number_dictionary; 741 Label slow, check_string, index_smi, index_string;
742 Label check_pixel_array, probe_dictionary, check_number_dictionary;
728 743
729 Register key = r0; 744 Register key = r0;
730 Register receiver = r1; 745 Register receiver = r1;
731 746
732 // Check that the object isn't a smi. 747 // Check that the object isn't a smi.
733 __ BranchOnSmi(receiver, &slow); 748 __ BranchOnSmi(receiver, &slow);
734 // Get the map of the receiver. 749 // Get the map of the receiver.
735 __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset)); 750 __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
736 // Check bit field. 751 // Check bit field.
737 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset)); 752 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
738 __ tst(r3, Operand(kSlowCaseBitFieldMask)); 753 __ tst(r3, Operand(kSlowCaseBitFieldMask));
739 __ b(ne, &slow); 754 __ b(ne, &slow);
740 // Check that the object is some kind of JS object EXCEPT JS Value type. 755 // Check that the object is some kind of JS object EXCEPT JS Value type.
741 // In the case that the object is a value-wrapper object, 756 // In the case that the object is a value-wrapper object,
742 // we enter the runtime system to make sure that indexing into string 757 // we enter the runtime system to make sure that indexing into string
743 // objects work as intended. 758 // objects work as intended.
744 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 759 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
745 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 760 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
746 __ cmp(r2, Operand(JS_OBJECT_TYPE)); 761 __ cmp(r2, Operand(JS_OBJECT_TYPE));
747 __ b(lt, &slow); 762 __ b(lt, &slow);
748 763
749 // Check that the key is a smi. 764 // Check that the key is a smi.
750 __ BranchOnNotSmi(key, &slow); 765 __ BranchOnNotSmi(key, &check_string);
751 // Get the elements array of the object. 766 __ bind(&index_smi);
767 // Now the key is known to be a smi. This place is also jumped to from below
768 // where a numeric string is converted to a smi.
752 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); 769 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
753 // Check that the object is in fast mode (not dictionary). 770 // Check that the object is in fast mode (not dictionary).
754 __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset)); 771 __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset));
755 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 772 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
756 __ cmp(r3, ip); 773 __ cmp(r3, ip);
757 __ b(ne, &check_pixel_array); 774 __ b(ne, &check_pixel_array);
758 // Check that the key (index) is within bounds. 775 // Check that the key (index) is within bounds.
759 __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset)); 776 __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset));
760 __ cmp(key, Operand(r3)); 777 __ cmp(key, Operand(r3));
761 __ b(hs, &slow); 778 __ b(hs, &slow);
762 // Fast case: Do the load. 779 // Fast case: Do the load.
763 __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 780 __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
764 // The key is a smi. 781 // The key is a smi.
765 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 782 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
766 __ ldr(r2, MemOperand(r3, key, LSL, kPointerSizeLog2 - kSmiTagSize)); 783 __ ldr(r2, MemOperand(r3, key, LSL, kPointerSizeLog2 - kSmiTagSize));
767 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 784 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
768 __ cmp(r2, ip); 785 __ cmp(r2, ip);
769 // In case the loaded value is the_hole we have to consult GetProperty 786 // In case the loaded value is the_hole we have to consult GetProperty
770 // to ensure the prototype chain is searched. 787 // to ensure the prototype chain is searched.
771 __ b(eq, &slow); 788 __ b(eq, &slow);
772 __ mov(r0, r2); 789 __ mov(r0, r2);
790 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3);
773 __ Ret(); 791 __ Ret();
774 792
775 // Check whether the elements is a pixel array. 793 // Check whether the elements is a pixel array.
776 // r0: key 794 // r0: key
777 // r3: elements map 795 // r3: elements map
778 // r4: elements 796 // r4: elements
779 __ bind(&check_pixel_array); 797 __ bind(&check_pixel_array);
780 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); 798 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
781 __ cmp(r3, ip); 799 __ cmp(r3, ip);
782 __ b(ne, &check_number_dictionary); 800 __ b(ne, &check_number_dictionary);
(...skipping 15 matching lines...) Expand all
798 __ cmp(r3, ip); 816 __ cmp(r3, ip);
799 __ b(ne, &slow); 817 __ b(ne, &slow);
800 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); 818 __ mov(r2, Operand(r0, ASR, kSmiTagSize));
801 GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r2, r3, r5); 819 GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r2, r3, r5);
802 __ Ret(); 820 __ Ret();
803 821
804 // Slow case, key and receiver still in r0 and r1. 822 // Slow case, key and receiver still in r0 and r1.
805 __ bind(&slow); 823 __ bind(&slow);
806 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r2, r3); 824 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r2, r3);
807 GenerateRuntimeGetProperty(masm); 825 GenerateRuntimeGetProperty(masm);
826
827 __ bind(&check_string);
828 // The key is not a smi.
829 // Is it a string?
830 // r0: key
831 // r1: receiver
832 __ CompareObjectType(r0, r2, r3, FIRST_NONSTRING_TYPE);
833 __ b(ge, &slow);
834
835 // Is the string an array index, with cached numeric value?
836 __ ldr(r3, FieldMemOperand(r0, String::kHashFieldOffset));
837 __ tst(r3, Operand(String::kIsArrayIndexMask));
838 __ b(ne, &index_string);
839
840 // Is the string a symbol?
841 // r2: key map
842 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
843 ASSERT(kSymbolTag != 0);
844 __ tst(r3, Operand(kIsSymbolMask));
845 __ b(eq, &slow);
846
847 // If the receiver is a fast-case object, check the keyed lookup
848 // cache. Otherwise probe the dictionary.
849 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset));
850 __ ldr(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
851 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
852 __ cmp(r3, ip);
853 __ b(eq, &probe_dictionary);
854
855 // Load the map of the receiver, compute the keyed lookup cache hash
856 // based on 32 bits of the map pointer and the string hash.
857 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
858 __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
859 __ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset));
860 __ eor(r3, r3, Operand(r4, ASR, String::kHashShift));
861 __ and_(r3, r3, Operand(KeyedLookupCache::kCapacityMask));
862
863 // Load the key (consisting of map and symbol) from the cache and
864 // check for match.
865 ExternalReference cache_keys = ExternalReference::keyed_lookup_cache_keys();
866 __ mov(r4, Operand(cache_keys));
867 __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1));
868 __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); // Move r4 to symbol.
869 __ cmp(r2, r5);
870 __ b(ne, &slow);
871 __ ldr(r5, MemOperand(r4));
872 __ cmp(r0, r5);
873 __ b(ne, &slow);
874
875 // Get field offset and check that it is an in-object property.
876 // r0 : key
877 // r1 : receiver
878 // r2 : receiver's map
879 // r3 : lookup cache index
880 ExternalReference cache_field_offsets
881 = ExternalReference::keyed_lookup_cache_field_offsets();
882 __ mov(r4, Operand(cache_field_offsets));
883 __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
884 __ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
885 __ cmp(r5, r6);
886 __ b(ge, &slow);
887
888 // Load in-object property.
889 __ sub(r5, r5, r6); // Index from end of object.
890 __ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset));
891 __ add(r6, r6, r5); // Index from start of object.
892 __ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag.
893 __ ldr(r0, MemOperand(r1, r6, LSL, kPointerSizeLog2));
894 __ IncrementCounter(&Counters::keyed_load_generic_lookup_cache, 1, r2, r3);
895 __ Ret();
896
897 // Do a quick inline probe of the receiver's dictionary, if it
898 // exists.
899 __ bind(&probe_dictionary);
900 // Load the property to r0.
901 GenerateDictionaryLoad(
902 masm, &slow, r1, r0, r0, r2, r3, r4, DICTIONARY_CHECK_DONE);
903 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1, r2, r3);
904 __ Ret();
905
906 __ b(&slow);
907 // If the hash field contains an array index pick it out. The assert checks
908 // that the constants for the maximum number of digits for an array index
909 // cached in the hash field and the number of bits reserved for it does not
910 // conflict.
911 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
912 (1 << String::kArrayIndexValueBits));
913 __ bind(&index_string);
914 // r0: key (string)
915 // r1: receiver
916 // r3: hash field
917 // We want the smi-tagged index in r0. kArrayIndexValueMask has zeros in
918 // the low kHashShift bits.
919 ASSERT(String::kHashShift >= kSmiTagSize);
920 __ and_(r3, r3, Operand(String::kArrayIndexValueMask));
921 // Here we actually clobber the key (r0) which will be used if calling into
922 // runtime later. However as the new key is the numeric value of a string key
923 // there is no difference in using either key.
924 __ mov(r0, Operand(r3, ASR, String::kHashShift - kSmiTagSize));
925 // Now jump to the place where smi keys are handled.
926 __ jmp(&index_smi);
808 } 927 }
809 928
810 929
811 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 930 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
812 // ---------- S t a t e -------------- 931 // ---------- S t a t e --------------
813 // -- lr : return address 932 // -- lr : return address
814 // -- r0 : key (index) 933 // -- r0 : key (index)
815 // -- r1 : receiver 934 // -- r1 : receiver
816 // ----------------------------------- 935 // -----------------------------------
817 Label miss; 936 Label miss;
(...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after
1806 GenerateMiss(masm); 1925 GenerateMiss(masm);
1807 } 1926 }
1808 1927
1809 1928
1810 #undef __ 1929 #undef __
1811 1930
1812 1931
1813 } } // namespace v8::internal 1932 } } // namespace v8::internal
1814 1933
1815 #endif // V8_TARGET_ARCH_ARM 1934 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698