| OLD | NEW |
| 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 __ b(eq, global_object); | 57 __ b(eq, global_object); |
| 58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); | 58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); |
| 59 __ b(eq, global_object); | 59 __ b(eq, global_object); |
| 60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); | 60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); |
| 61 __ b(eq, global_object); | 61 __ b(eq, global_object); |
| 62 } | 62 } |
| 63 | 63 |
| 64 | 64 |
| 65 // Generated code falls through if the receiver is a regular non-global | 65 // Generated code falls through if the receiver is a regular non-global |
| 66 // JS object with slow properties and no interceptors. | 66 // JS object with slow properties and no interceptors. |
| 67 static void GenerateDictionaryLoadReceiverCheck(MacroAssembler* masm, | 67 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, |
| 68 Register receiver, | 68 Register receiver, |
| 69 Register elements, | 69 Register elements, |
| 70 Register t0, | 70 Register t0, |
| 71 Register t1, | 71 Register t1, |
| 72 Label* miss) { | 72 Label* miss) { |
| 73 // Register usage: | 73 // Register usage: |
| 74 // receiver: holds the receiver on entry and is unchanged. | 74 // receiver: holds the receiver on entry and is unchanged. |
| 75 // elements: holds the property dictionary on fall through. | 75 // elements: holds the property dictionary on fall through. |
| 76 // Scratch registers: | 76 // Scratch registers: |
| 77 // t0: used to holds the receiver map. | 77 // t0: used to holds the receiver map. |
| 78 // t1: used to holds the receiver instance type, receiver bit mask and | 78 // t1: used to holds the receiver instance type, receiver bit mask and |
| 79 // elements map. | 79 // elements map. |
| 80 | 80 |
| 81 // Check that the receiver isn't a smi. | 81 // Check that the receiver isn't a smi. |
| 82 __ tst(receiver, Operand(kSmiTagMask)); | 82 __ tst(receiver, Operand(kSmiTagMask)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 98 __ b(nz, miss); | 98 __ b(nz, miss); |
| 99 | 99 |
| 100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 101 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset)); | 101 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset)); |
| 102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
| 103 __ cmp(t1, ip); | 103 __ cmp(t1, ip); |
| 104 __ b(nz, miss); | 104 __ b(nz, miss); |
| 105 } | 105 } |
| 106 | 106 |
| 107 | 107 |
| 108 // Helper function used from LoadIC/CallIC GenerateNormal. | 108 // Probe the string dictionary in the |elements| register. Jump to the |
| 109 // | 109 // |done| label if a property with the given name is found. Jump to |
| 110 // elements: Property dictionary. It is not clobbered if a jump to the miss | 110 // the |miss| label otherwise. |
| 111 // label is done. | 111 static void GenerateStringDictionaryProbes(MacroAssembler* masm, |
| 112 // name: Property name. It is not clobbered if a jump to the miss label is | 112 Label* miss, |
| 113 // done | 113 Label* done, |
| 114 // result: Register for the result. It is only updated if a jump to the miss | 114 Register elements, |
| 115 // label is not done. Can be the same as elements or name clobbering | 115 Register name, |
| 116 // one of these in the case of not jumping to the miss label. | 116 Register scratch1, |
| 117 // The two scratch registers need to be different from elements, name and | 117 Register scratch2) { |
| 118 // result. | |
| 119 // The generated code assumes that the receiver has slow properties, | |
| 120 // is not a global object and does not have interceptors. | |
| 121 static void GenerateDictionaryLoad(MacroAssembler* masm, | |
| 122 Label* miss, | |
| 123 Register elements, | |
| 124 Register name, | |
| 125 Register result, | |
| 126 Register scratch1, | |
| 127 Register scratch2) { | |
| 128 // Main use of the scratch registers. | |
| 129 // scratch1: Used as temporary and to hold the capacity of the property | |
| 130 // dictionary. | |
| 131 // scratch2: Used as temporary. | |
| 132 | |
| 133 Label done; | |
| 134 | |
| 135 // Compute the capacity mask. | 118 // Compute the capacity mask. |
| 136 const int kCapacityOffset = StringDictionary::kHeaderSize + | 119 const int kCapacityOffset = StringDictionary::kHeaderSize + |
| 137 StringDictionary::kCapacityIndex * kPointerSize; | 120 StringDictionary::kCapacityIndex * kPointerSize; |
| 138 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); | 121 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); |
| 139 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int | 122 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int |
| 140 __ sub(scratch1, scratch1, Operand(1)); | 123 __ sub(scratch1, scratch1, Operand(1)); |
| 141 | 124 |
| 142 const int kElementsStartOffset = StringDictionary::kHeaderSize + | 125 const int kElementsStartOffset = StringDictionary::kHeaderSize + |
| 143 StringDictionary::kElementsStartIndex * kPointerSize; | 126 StringDictionary::kElementsStartIndex * kPointerSize; |
| 144 | 127 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 163 // Scale the index by multiplying by the element size. | 146 // Scale the index by multiplying by the element size. |
| 164 ASSERT(StringDictionary::kEntrySize == 3); | 147 ASSERT(StringDictionary::kEntrySize == 3); |
| 165 // scratch2 = scratch2 * 3. | 148 // scratch2 = scratch2 * 3. |
| 166 __ add(scratch2, scratch2, Operand(scratch2, LSL, 1)); | 149 __ add(scratch2, scratch2, Operand(scratch2, LSL, 1)); |
| 167 | 150 |
| 168 // Check if the key is identical to the name. | 151 // Check if the key is identical to the name. |
| 169 __ add(scratch2, elements, Operand(scratch2, LSL, 2)); | 152 __ add(scratch2, elements, Operand(scratch2, LSL, 2)); |
| 170 __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset)); | 153 __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset)); |
| 171 __ cmp(name, Operand(ip)); | 154 __ cmp(name, Operand(ip)); |
| 172 if (i != kProbes - 1) { | 155 if (i != kProbes - 1) { |
| 173 __ b(eq, &done); | 156 __ b(eq, done); |
| 174 } else { | 157 } else { |
| 175 __ b(ne, miss); | 158 __ b(ne, miss); |
| 176 } | 159 } |
| 177 } | 160 } |
| 161 } |
| 178 | 162 |
| 179 // Check that the value is a normal property. | 163 |
| 164 // Helper function used from LoadIC/CallIC GenerateNormal. |
| 165 // |
| 166 // elements: Property dictionary. It is not clobbered if a jump to the miss |
| 167 // label is done. |
| 168 // name: Property name. It is not clobbered if a jump to the miss label is |
| 169 // done |
| 170 // result: Register for the result. It is only updated if a jump to the miss |
| 171 // label is not done. Can be the same as elements or name clobbering |
| 172 // one of these in the case of not jumping to the miss label. |
| 173 // The two scratch registers need to be different from elements, name and |
| 174 // result. |
| 175 // The generated code assumes that the receiver has slow properties, |
| 176 // is not a global object and does not have interceptors. |
| 177 static void GenerateDictionaryLoad(MacroAssembler* masm, |
| 178 Label* miss, |
| 179 Register elements, |
| 180 Register name, |
| 181 Register result, |
| 182 Register scratch1, |
| 183 Register scratch2) { |
| 184 // Main use of the scratch registers. |
| 185 // scratch1: Used as temporary and to hold the capacity of the property |
| 186 // dictionary. |
| 187 // scratch2: Used as temporary. |
| 188 Label done; |
| 189 |
| 190 // Probe the dictionary. |
| 191 GenerateStringDictionaryProbes(masm, |
| 192 miss, |
| 193 &done, |
| 194 elements, |
| 195 name, |
| 196 scratch1, |
| 197 scratch2); |
| 198 |
| 199 // If probing finds an entry check that the value is a normal |
| 200 // property. |
| 180 __ bind(&done); // scratch2 == elements + 4 * index | 201 __ bind(&done); // scratch2 == elements + 4 * index |
| 181 __ ldr(scratch1, | 202 const int kElementsStartOffset = StringDictionary::kHeaderSize + |
| 182 FieldMemOperand(scratch2, kElementsStartOffset + 2 * kPointerSize)); | 203 StringDictionary::kElementsStartIndex * kPointerSize; |
| 204 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 205 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
| 183 __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); | 206 __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); |
| 184 __ b(ne, miss); | 207 __ b(ne, miss); |
| 185 | 208 |
| 186 // Get the value at the masked, scaled index and return. | 209 // Get the value at the masked, scaled index and return. |
| 187 __ ldr(result, | 210 __ ldr(result, |
| 188 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); | 211 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); |
| 189 } | 212 } |
| 190 | 213 |
| 191 | 214 |
| 215 // Helper function used from StoreIC::GenerateNormal. |
| 216 // |
| 217 // elements: Property dictionary. It is not clobbered if a jump to the miss |
| 218 // label is done. |
| 219 // name: Property name. It is not clobbered if a jump to the miss label is |
| 220 // done |
| 221 // value: The value to store. |
| 222 // The two scratch registers need to be different from elements, name and |
| 223 // result. |
| 224 // The generated code assumes that the receiver has slow properties, |
| 225 // is not a global object and does not have interceptors. |
| 226 static void GenerateDictionaryStore(MacroAssembler* masm, |
| 227 Label* miss, |
| 228 Register elements, |
| 229 Register name, |
| 230 Register value, |
| 231 Register scratch1, |
| 232 Register scratch2) { |
| 233 // Main use of the scratch registers. |
| 234 // scratch1: Used as temporary and to hold the capacity of the property |
| 235 // dictionary. |
| 236 // scratch2: Used as temporary. |
| 237 Label done; |
| 238 |
| 239 // Probe the dictionary. |
| 240 GenerateStringDictionaryProbes(masm, |
| 241 miss, |
| 242 &done, |
| 243 elements, |
| 244 name, |
| 245 scratch1, |
| 246 scratch2); |
| 247 |
| 248 // If probing finds an entry in the dictionary check that the value |
| 249 // is a normal property that is not read only. |
| 250 __ bind(&done); // scratch2 == elements + 4 * index |
| 251 const int kElementsStartOffset = StringDictionary::kHeaderSize + |
| 252 StringDictionary::kElementsStartIndex * kPointerSize; |
| 253 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
| 254 const int kTypeAndReadOnlyMask |
| 255 = (PropertyDetails::TypeField::mask() | |
| 256 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; |
| 257 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
| 258 __ tst(scratch1, Operand(kTypeAndReadOnlyMask)); |
| 259 __ b(ne, miss); |
| 260 |
| 261 // Store the value at the masked, scaled index and return. |
| 262 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 263 __ add(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag)); |
| 264 __ str(value, MemOperand(scratch2)); |
| 265 |
| 266 // Update the write barrier. Make sure not to clobber the value. |
| 267 __ mov(scratch1, value); |
| 268 __ RecordWrite(elements, scratch2, scratch1); |
| 269 } |
| 270 |
| 271 |
| 192 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, | 272 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, |
| 193 Label* miss, | 273 Label* miss, |
| 194 Register elements, | 274 Register elements, |
| 195 Register key, | 275 Register key, |
| 196 Register result, | 276 Register result, |
| 197 Register t0, | 277 Register t0, |
| 198 Register t1, | 278 Register t1, |
| 199 Register t2) { | 279 Register t2) { |
| 200 // Register use: | 280 // Register use: |
| 201 // | 281 // |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 static void GenerateCallNormal(MacroAssembler* masm, int argc) { | 633 static void GenerateCallNormal(MacroAssembler* masm, int argc) { |
| 554 // ----------- S t a t e ------------- | 634 // ----------- S t a t e ------------- |
| 555 // -- r2 : name | 635 // -- r2 : name |
| 556 // -- lr : return address | 636 // -- lr : return address |
| 557 // ----------------------------------- | 637 // ----------------------------------- |
| 558 Label miss; | 638 Label miss; |
| 559 | 639 |
| 560 // Get the receiver of the function from the stack into r1. | 640 // Get the receiver of the function from the stack into r1. |
| 561 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 641 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 562 | 642 |
| 563 GenerateDictionaryLoadReceiverCheck(masm, r1, r0, r3, r4, &miss); | 643 GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); |
| 564 | 644 |
| 565 // r0: elements | 645 // r0: elements |
| 566 // Search the dictionary - put result in register r1. | 646 // Search the dictionary - put result in register r1. |
| 567 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); | 647 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); |
| 568 | 648 |
| 569 GenerateFunctionTailCall(masm, argc, &miss, r4); | 649 GenerateFunctionTailCall(masm, argc, &miss, r4); |
| 570 | 650 |
| 571 __ bind(&miss); | 651 __ bind(&miss); |
| 572 } | 652 } |
| 573 | 653 |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 | 888 |
| 809 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 889 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 810 // ----------- S t a t e ------------- | 890 // ----------- S t a t e ------------- |
| 811 // -- r2 : name | 891 // -- r2 : name |
| 812 // -- lr : return address | 892 // -- lr : return address |
| 813 // -- r0 : receiver | 893 // -- r0 : receiver |
| 814 // -- sp[0] : receiver | 894 // -- sp[0] : receiver |
| 815 // ----------------------------------- | 895 // ----------------------------------- |
| 816 Label miss; | 896 Label miss; |
| 817 | 897 |
| 818 GenerateDictionaryLoadReceiverCheck(masm, r0, r1, r3, r4, &miss); | 898 GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss); |
| 819 | 899 |
| 820 // r1: elements | 900 // r1: elements |
| 821 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); | 901 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); |
| 822 __ Ret(); | 902 __ Ret(); |
| 823 | 903 |
| 824 // Cache miss: Jump to runtime. | 904 // Cache miss: Jump to runtime. |
| 825 __ bind(&miss); | 905 __ bind(&miss); |
| 826 GenerateMiss(masm); | 906 GenerateMiss(masm); |
| 827 } | 907 } |
| 828 | 908 |
| (...skipping 1302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2131 | 2211 |
| 2132 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); | 2212 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); |
| 2133 __ TailCallExternalReference(ref, 2, 1); | 2213 __ TailCallExternalReference(ref, 2, 1); |
| 2134 | 2214 |
| 2135 __ bind(&miss); | 2215 __ bind(&miss); |
| 2136 | 2216 |
| 2137 GenerateMiss(masm); | 2217 GenerateMiss(masm); |
| 2138 } | 2218 } |
| 2139 | 2219 |
| 2140 | 2220 |
| 2221 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 2222 // ----------- S t a t e ------------- |
| 2223 // -- r0 : value |
| 2224 // -- r1 : receiver |
| 2225 // -- r2 : name |
| 2226 // -- lr : return address |
| 2227 // ----------------------------------- |
| 2228 Label miss; |
| 2229 |
| 2230 GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss); |
| 2231 |
| 2232 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5); |
| 2233 __ IncrementCounter(&Counters::store_normal_hit, 1, r4, r5); |
| 2234 __ Ret(); |
| 2235 |
| 2236 __ bind(&miss); |
| 2237 __ IncrementCounter(&Counters::store_normal_miss, 1, r4, r5); |
| 2238 GenerateMiss(masm); |
| 2239 } |
| 2240 |
| 2241 |
| 2141 #undef __ | 2242 #undef __ |
| 2142 | 2243 |
| 2143 | 2244 |
| 2144 } } // namespace v8::internal | 2245 } } // namespace v8::internal |
| 2145 | 2246 |
| 2146 #endif // V8_TARGET_ARCH_ARM | 2247 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |