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

Side by Side Diff: src/arm/stub-cache-arm.cc

Issue 7060010: Merge bleeding edge into the GC branch up to 7948. The asserts (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 7 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/simulator-arm.cc ('k') | src/assembler.h » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 // Miss: fall through. 88 // Miss: fall through.
89 __ bind(&miss); 89 __ bind(&miss);
90 } 90 }
91 91
92 92
93 // Helper function used to check that the dictionary doesn't contain 93 // Helper function used to check that the dictionary doesn't contain
94 // the property. This function may return false negatives, so miss_label 94 // the property. This function may return false negatives, so miss_label
95 // must always call a backup property check that is complete. 95 // must always call a backup property check that is complete.
96 // This function is safe to call if the receiver has fast properties. 96 // This function is safe to call if the receiver has fast properties.
97 // Name must be a symbol and receiver must be a heap object. 97 // Name must be a symbol and receiver must be a heap object.
98 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 98 MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup(
99 Label* miss_label, 99 MacroAssembler* masm,
100 Register receiver, 100 Label* miss_label,
101 String* name, 101 Register receiver,
102 Register scratch0, 102 String* name,
103 Register scratch1) { 103 Register scratch0,
104 Register scratch1) {
104 ASSERT(name->IsSymbol()); 105 ASSERT(name->IsSymbol());
105 Counters* counters = masm->isolate()->counters(); 106 Counters* counters = masm->isolate()->counters();
106 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 107 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
107 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 108 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
108 109
109 Label done; 110 Label done;
110 111
111 const int kInterceptorOrAccessCheckNeededMask = 112 const int kInterceptorOrAccessCheckNeededMask =
112 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 113 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
113 114
(...skipping 15 matching lines...) Expand all
129 // Check that the properties array is a dictionary. 130 // Check that the properties array is a dictionary.
130 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 131 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset));
131 Register tmp = properties; 132 Register tmp = properties;
132 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 133 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
133 __ cmp(map, tmp); 134 __ cmp(map, tmp);
134 __ b(ne, miss_label); 135 __ b(ne, miss_label);
135 136
136 // Restore the temporarily used register. 137 // Restore the temporarily used register.
137 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 138 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
138 139
139 // Compute the capacity mask.
140 const int kCapacityOffset =
141 StringDictionary::kHeaderSize +
142 StringDictionary::kCapacityIndex * kPointerSize;
143 140
144 // Generate an unrolled loop that performs a few probes before 141 MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup(
145 // giving up. 142 masm,
146 static const int kProbes = 4; 143 miss_label,
147 const int kElementsStartOffset = 144 &done,
148 StringDictionary::kHeaderSize + 145 receiver,
149 StringDictionary::kElementsStartIndex * kPointerSize; 146 properties,
147 name,
148 scratch1);
149 if (result->IsFailure()) return result;
150 150
151 // If names of slots in range from 1 to kProbes - 1 for the hash value are
152 // not equal to the name and kProbes-th slot is not used (its name is the
153 // undefined value), it guarantees the hash table doesn't contain the
154 // property. It's true even if some slots represent deleted properties
155 // (their names are the null value).
156 for (int i = 0; i < kProbes; i++) {
157 // scratch0 points to properties hash.
158 // Compute the masked index: (hash + i + i * i) & mask.
159 Register index = scratch1;
160 // Capacity is smi 2^n.
161 __ ldr(index, FieldMemOperand(properties, kCapacityOffset));
162 __ sub(index, index, Operand(1));
163 __ and_(index, index, Operand(
164 Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i))));
165
166 // Scale the index by multiplying by the entry size.
167 ASSERT(StringDictionary::kEntrySize == 3);
168 __ add(index, index, Operand(index, LSL, 1)); // index *= 3.
169
170 Register entity_name = scratch1;
171 // Having undefined at this place means the name is not contained.
172 ASSERT_EQ(kSmiTagSize, 1);
173 Register tmp = properties;
174 __ add(tmp, properties, Operand(index, LSL, 1));
175 __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
176
177 ASSERT(!tmp.is(entity_name));
178 __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
179 __ cmp(entity_name, tmp);
180 if (i != kProbes - 1) {
181 __ b(eq, &done);
182
183 // Stop if found the property.
184 __ cmp(entity_name, Operand(Handle<String>(name)));
185 __ b(eq, miss_label);
186
187 // Check if the entry name is not a symbol.
188 __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
189 __ ldrb(entity_name,
190 FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
191 __ tst(entity_name, Operand(kIsSymbolMask));
192 __ b(eq, miss_label);
193
194 // Restore the properties.
195 __ ldr(properties,
196 FieldMemOperand(receiver, JSObject::kPropertiesOffset));
197 } else {
198 // Give up probing if still not found the undefined value.
199 __ b(ne, miss_label);
200 }
201 }
202 __ bind(&done); 151 __ bind(&done);
203 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 152 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
153
154 return result;
204 } 155 }
205 156
206 157
207 void StubCache::GenerateProbe(MacroAssembler* masm, 158 void StubCache::GenerateProbe(MacroAssembler* masm,
208 Code::Flags flags, 159 Code::Flags flags,
209 Register receiver, 160 Register receiver,
210 Register name, 161 Register name,
211 Register scratch, 162 Register scratch,
212 Register extra, 163 Register extra,
213 Register extra2) { 164 Register extra2) {
(...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 Object* lookup_result = NULL; // Initialization to please compiler. 1050 Object* lookup_result = NULL; // Initialization to please compiler.
1100 if (!maybe_lookup_result->ToObject(&lookup_result)) { 1051 if (!maybe_lookup_result->ToObject(&lookup_result)) {
1101 set_failure(Failure::cast(maybe_lookup_result)); 1052 set_failure(Failure::cast(maybe_lookup_result));
1102 return reg; 1053 return reg;
1103 } 1054 }
1104 name = String::cast(lookup_result); 1055 name = String::cast(lookup_result);
1105 } 1056 }
1106 ASSERT(current->property_dictionary()->FindEntry(name) == 1057 ASSERT(current->property_dictionary()->FindEntry(name) ==
1107 StringDictionary::kNotFound); 1058 StringDictionary::kNotFound);
1108 1059
1109 GenerateDictionaryNegativeLookup(masm(), 1060 MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(),
1110 miss, 1061 miss,
1111 reg, 1062 reg,
1112 name, 1063 name,
1113 scratch1, 1064 scratch1,
1114 scratch2); 1065 scratch2);
1066 if (negative_lookup->IsFailure()) {
1067 set_failure(Failure::cast(negative_lookup));
1068 return reg;
1069 }
1070
1115 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 1071 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
1116 reg = holder_reg; // from now the object is in holder_reg 1072 reg = holder_reg; // from now the object is in holder_reg
1117 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 1073 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
1118 } else if (heap()->InNewSpace(prototype)) { 1074 } else if (heap()->InNewSpace(prototype)) {
1119 // Get the map of the current object. 1075 // Get the map of the current object.
1120 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 1076 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
1121 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); 1077 __ cmp(scratch1, Operand(Handle<Map>(current->map())));
1122 1078
1123 // Branch on the result of the map check. 1079 // Branch on the result of the map check.
1124 __ b(ne, miss); 1080 __ b(ne, miss);
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
1591 } else { 1547 } else {
1592 Label call_builtin; 1548 Label call_builtin;
1593 1549
1594 Register elements = r3; 1550 Register elements = r3;
1595 Register end_elements = r5; 1551 Register end_elements = r5;
1596 1552
1597 // Get the elements array of the object. 1553 // Get the elements array of the object.
1598 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 1554 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
1599 1555
1600 // Check that the elements are in fast mode and writable. 1556 // Check that the elements are in fast mode and writable.
1601 __ CheckMap(elements, r0, 1557 __ CheckMap(elements,
1602 Heap::kFixedArrayMapRootIndex, &call_builtin, true); 1558 r0,
1559 Heap::kFixedArrayMapRootIndex,
1560 &call_builtin,
1561 DONT_DO_SMI_CHECK);
1603 1562
1604 if (argc == 1) { // Otherwise fall through to call the builtin. 1563 if (argc == 1) { // Otherwise fall through to call the builtin.
1605 Label exit, attempt_to_grow_elements; 1564 Label exit, attempt_to_grow_elements;
1606 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER 1565 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER
1607 Label with_write_barrier; 1566 Label with_write_barrier;
1608 #endif 1567 #endif
1609 1568
1610 // Get the array's length into r0 and calculate new length. 1569 // Get the array's length into r0 and calculate new length.
1611 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1570 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
1612 STATIC_ASSERT(kSmiTagSize == 1); 1571 STATIC_ASSERT(kSmiTagSize == 1);
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1748 __ JumpIfSmi(receiver, &miss); 1707 __ JumpIfSmi(receiver, &miss);
1749 1708
1750 // Check that the maps haven't changed. 1709 // Check that the maps haven't changed.
1751 CheckPrototypes(JSObject::cast(object), 1710 CheckPrototypes(JSObject::cast(object),
1752 receiver, holder, elements, r4, r0, name, &miss); 1711 receiver, holder, elements, r4, r0, name, &miss);
1753 1712
1754 // Get the elements array of the object. 1713 // Get the elements array of the object.
1755 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 1714 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
1756 1715
1757 // Check that the elements are in fast mode and writable. 1716 // Check that the elements are in fast mode and writable.
1758 __ CheckMap(elements, r0, Heap::kFixedArrayMapRootIndex, &call_builtin, true); 1717 __ CheckMap(elements,
1718 r0,
1719 Heap::kFixedArrayMapRootIndex,
1720 &call_builtin,
1721 DONT_DO_SMI_CHECK);
1759 1722
1760 // Get the array's length into r4 and calculate new length. 1723 // Get the array's length into r4 and calculate new length.
1761 __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1724 __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
1762 __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC); 1725 __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC);
1763 __ b(lt, &return_undefined); 1726 __ b(lt, &return_undefined);
1764 1727
1765 // Get the last element. 1728 // Get the last element.
1766 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); 1729 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
1767 STATIC_ASSERT(kSmiTagSize == 1); 1730 STATIC_ASSERT(kSmiTagSize == 1);
1768 STATIC_ASSERT(kSmiTag == 0); 1731 STATIC_ASSERT(kSmiTag == 0);
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
2090 2053
2091 // Load the (only) argument into r0. 2054 // Load the (only) argument into r0.
2092 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); 2055 __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
2093 2056
2094 // If the argument is a smi, just return. 2057 // If the argument is a smi, just return.
2095 STATIC_ASSERT(kSmiTag == 0); 2058 STATIC_ASSERT(kSmiTag == 0);
2096 __ tst(r0, Operand(kSmiTagMask)); 2059 __ tst(r0, Operand(kSmiTagMask));
2097 __ Drop(argc + 1, eq); 2060 __ Drop(argc + 1, eq);
2098 __ Ret(eq); 2061 __ Ret(eq);
2099 2062
2100 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, true); 2063 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2101 2064
2102 Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return; 2065 Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return;
2103 2066
2104 // If vfp3 is enabled, we use the fpu rounding with the RM (round towards 2067 // If vfp3 is enabled, we use the fpu rounding with the RM (round towards
2105 // minus infinity) mode. 2068 // minus infinity) mode.
2106 2069
2107 // Load the HeapNumber value. 2070 // Load the HeapNumber value.
2108 // We will need access to the value in the core registers, so we load it 2071 // We will need access to the value in the core registers, so we load it
2109 // with ldrd and move it to the fpu. It also spares a sub instruction for 2072 // with ldrd and move it to the fpu. It also spares a sub instruction for
2110 // updating the HeapNumber value address, as vldr expects a multiple 2073 // updating the HeapNumber value address, as vldr expects a multiple
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
2251 Label slow; 2214 Label slow;
2252 __ b(mi, &slow); 2215 __ b(mi, &slow);
2253 2216
2254 // Smi case done. 2217 // Smi case done.
2255 __ Drop(argc + 1); 2218 __ Drop(argc + 1);
2256 __ Ret(); 2219 __ Ret();
2257 2220
2258 // Check if the argument is a heap number and load its exponent and 2221 // Check if the argument is a heap number and load its exponent and
2259 // sign. 2222 // sign.
2260 __ bind(&not_smi); 2223 __ bind(&not_smi);
2261 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, true); 2224 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
2262 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2225 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2263 2226
2264 // Check the sign of the argument. If the argument is positive, 2227 // Check the sign of the argument. If the argument is positive,
2265 // just return it. 2228 // just return it.
2266 Label negative_sign; 2229 Label negative_sign;
2267 __ tst(r1, Operand(HeapNumber::kSignMask)); 2230 __ tst(r1, Operand(HeapNumber::kSignMask));
2268 __ b(ne, &negative_sign); 2231 __ b(ne, &negative_sign);
2269 __ Drop(argc + 1); 2232 __ Drop(argc + 1);
2270 __ Ret(); 2233 __ Ret();
2271 2234
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2303 JSGlobalPropertyCell* cell, 2266 JSGlobalPropertyCell* cell,
2304 JSFunction* function, 2267 JSFunction* function,
2305 String* name) { 2268 String* name) {
2306 Counters* counters = isolate()->counters(); 2269 Counters* counters = isolate()->counters();
2307 2270
2308 ASSERT(optimization.is_simple_api_call()); 2271 ASSERT(optimization.is_simple_api_call());
2309 // Bail out if object is a global object as we don't want to 2272 // Bail out if object is a global object as we don't want to
2310 // repatch it to global receiver. 2273 // repatch it to global receiver.
2311 if (object->IsGlobalObject()) return heap()->undefined_value(); 2274 if (object->IsGlobalObject()) return heap()->undefined_value();
2312 if (cell != NULL) return heap()->undefined_value(); 2275 if (cell != NULL) return heap()->undefined_value();
2276 if (!object->IsJSObject()) return heap()->undefined_value();
2313 int depth = optimization.GetPrototypeDepthOfExpectedType( 2277 int depth = optimization.GetPrototypeDepthOfExpectedType(
2314 JSObject::cast(object), holder); 2278 JSObject::cast(object), holder);
2315 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); 2279 if (depth == kInvalidProtoDepth) return heap()->undefined_value();
2316 2280
2317 Label miss, miss_before_stack_reserved; 2281 Label miss, miss_before_stack_reserved;
2318 2282
2319 GenerateNameCheck(name, &miss_before_stack_reserved); 2283 GenerateNameCheck(name, &miss_before_stack_reserved);
2320 2284
2321 // Get the receiver from the stack. 2285 // Get the receiver from the stack.
2322 const int argc = arguments().immediate(); 2286 const int argc = arguments().immediate();
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after
3132 3096
3133 GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); 3097 GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
3134 __ bind(&miss); 3098 __ bind(&miss);
3135 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); 3099 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
3136 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3100 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3137 3101
3138 return GetCode(CALLBACKS, name); 3102 return GetCode(CALLBACKS, name);
3139 } 3103 }
3140 3104
3141 3105
3142 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { 3106 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
3107 // ----------- S t a t e -------------
3108 // -- lr : return address
3109 // -- r0 : key
3110 // -- r1 : receiver
3111 // -----------------------------------
3112 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
3113 Code* stub;
3114 if (!maybe_stub->To(&stub)) return maybe_stub;
3115 __ DispatchMap(r1,
3116 r2,
3117 Handle<Map>(receiver_map),
3118 Handle<Code>(stub),
3119 DO_SMI_CHECK);
3120
3121 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3122 __ Jump(ic, RelocInfo::CODE_TARGET);
3123
3124 // Return the generated code.
3125 return GetCode(NORMAL, NULL);
3126 }
3127
3128
3129 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
3130 MapList* receiver_maps,
3131 CodeList* handler_ics) {
3143 // ----------- S t a t e ------------- 3132 // ----------- S t a t e -------------
3144 // -- lr : return address 3133 // -- lr : return address
3145 // -- r0 : key 3134 // -- r0 : key
3146 // -- r1 : receiver 3135 // -- r1 : receiver
3147 // ----------------------------------- 3136 // -----------------------------------
3148 Label miss; 3137 Label miss;
3138 __ JumpIfSmi(r1, &miss);
3149 3139
3150 // Check that the receiver isn't a smi. 3140 int receiver_count = receiver_maps->length();
3151 __ tst(r1, Operand(kSmiTagMask));
3152 __ b(eq, &miss);
3153
3154 // Check that the map matches.
3155 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3141 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
3156 __ cmp(r2, Operand(Handle<Map>(receiver->map()))); 3142 for (int current = 0; current < receiver_count; ++current) {
3157 __ b(ne, &miss); 3143 Handle<Map> map(receiver_maps->at(current));
3158 3144 Handle<Code> code(handler_ics->at(current));
3159 // Check that the key is a smi. 3145 __ mov(ip, Operand(map));
3160 __ tst(r0, Operand(kSmiTagMask)); 3146 __ cmp(r2, ip);
3161 __ b(ne, &miss); 3147 __ Jump(code, RelocInfo::CODE_TARGET, eq);
3162 3148 }
3163 // Get the elements array.
3164 __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
3165 __ AssertFastElements(r2);
3166
3167 // Check that the key is within bounds.
3168 __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
3169 __ cmp(r0, Operand(r3));
3170 __ b(hs, &miss);
3171
3172 // Load the result and make sure it's not the hole.
3173 __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3174 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
3175 __ ldr(r4,
3176 MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
3177 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3178 __ cmp(r4, ip);
3179 __ b(eq, &miss);
3180 __ mov(r0, r4);
3181 __ Ret();
3182 3149
3183 __ bind(&miss); 3150 __ bind(&miss);
3184 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3151 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss();
3152 __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3185 3153
3186 // Return the generated code. 3154 // Return the generated code.
3187 return GetCode(NORMAL, NULL); 3155 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3188 } 3156 }
3189 3157
3190 3158
3191 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, 3159 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
3192 int index, 3160 int index,
3193 Map* transition, 3161 Map* transition,
3194 String* name) { 3162 String* name) {
3195 // ----------- S t a t e ------------- 3163 // ----------- S t a t e -------------
3196 // -- r0 : value 3164 // -- r0 : value
3197 // -- r1 : name 3165 // -- r1 : name
(...skipping 21 matching lines...) Expand all
3219 3187
3220 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4); 3188 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4);
3221 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); 3189 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
3222 __ Jump(ic, RelocInfo::CODE_TARGET); 3190 __ Jump(ic, RelocInfo::CODE_TARGET);
3223 3191
3224 // Return the generated code. 3192 // Return the generated code.
3225 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 3193 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
3226 } 3194 }
3227 3195
3228 3196
3229 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( 3197 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
3230 JSObject* receiver) { 3198 Map* receiver_map) {
3231 // ----------- S t a t e ------------- 3199 // ----------- S t a t e -------------
3232 // -- r0 : value 3200 // -- r0 : value
3233 // -- r1 : key 3201 // -- r1 : key
3234 // -- r2 : receiver 3202 // -- r2 : receiver
3235 // -- lr : return address 3203 // -- lr : return address
3236 // -- r3 : scratch 3204 // -- r3 : scratch
3237 // -- r4 : scratch (elements)
3238 // ----------------------------------- 3205 // -----------------------------------
3239 Label miss; 3206 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
3207 MaybeObject* maybe_stub =
3208 KeyedStoreFastElementStub(is_js_array).TryGetCode();
3209 Code* stub;
3210 if (!maybe_stub->To(&stub)) return maybe_stub;
3211 __ DispatchMap(r2,
3212 r3,
3213 Handle<Map>(receiver_map),
3214 Handle<Code>(stub),
3215 DO_SMI_CHECK);
3240 3216
3241 Register value_reg = r0; 3217 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3242 Register key_reg = r1;
3243 Register receiver_reg = r2;
3244 Register scratch = r3;
3245 Register elements_reg = r4;
3246
3247 // Check that the receiver isn't a smi.
3248 __ tst(receiver_reg, Operand(kSmiTagMask));
3249 __ b(eq, &miss);
3250
3251 // Check that the map matches.
3252 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
3253 __ cmp(scratch, Operand(Handle<Map>(receiver->map())));
3254 __ b(ne, &miss);
3255
3256 // Check that the key is a smi.
3257 __ tst(key_reg, Operand(kSmiTagMask));
3258 __ b(ne, &miss);
3259
3260 // Get the elements array and make sure it is a fast element array, not 'cow'.
3261 __ ldr(elements_reg,
3262 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
3263 __ ldr(scratch, FieldMemOperand(elements_reg, HeapObject::kMapOffset));
3264 __ cmp(scratch, Operand(Handle<Map>(factory()->fixed_array_map())));
3265 __ b(ne, &miss);
3266
3267 // Check that the key is within bounds.
3268 if (receiver->IsJSArray()) {
3269 __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
3270 } else {
3271 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
3272 }
3273 // Compare smis.
3274 __ cmp(key_reg, scratch);
3275 __ b(hs, &miss);
3276
3277 __ add(scratch,
3278 elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3279 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
3280 __ str(value_reg,
3281 MemOperand(scratch, key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
3282 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER
3283 __ RecordWrite(scratch,
3284 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize),
3285 receiver_reg , elements_reg);
3286 #endif
3287
3288 // value_reg (r0) is preserved.
3289 // Done.
3290 __ Ret();
3291
3292 __ bind(&miss);
3293 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
3294 __ Jump(ic, RelocInfo::CODE_TARGET); 3218 __ Jump(ic, RelocInfo::CODE_TARGET);
3295 3219
3296 // Return the generated code. 3220 // Return the generated code.
3297 return GetCode(NORMAL, NULL); 3221 return GetCode(NORMAL, NULL);
3298 } 3222 }
3299 3223
3300 3224
3225 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
3226 MapList* receiver_maps,
3227 CodeList* handler_ics) {
3228 // ----------- S t a t e -------------
3229 // -- r0 : value
3230 // -- r1 : key
3231 // -- r2 : receiver
3232 // -- lr : return address
3233 // -- r3 : scratch
3234 // -----------------------------------
3235 Label miss;
3236 __ JumpIfSmi(r2, &miss);
3237
3238 int receiver_count = receiver_maps->length();
3239 __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
3240 for (int current = 0; current < receiver_count; ++current) {
3241 Handle<Map> map(receiver_maps->at(current));
3242 Handle<Code> code(handler_ics->at(current));
3243 __ mov(ip, Operand(map));
3244 __ cmp(r3, ip);
3245 __ Jump(code, RelocInfo::CODE_TARGET, eq);
3246 }
3247
3248 __ bind(&miss);
3249 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
3250 __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3251
3252 // Return the generated code.
3253 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3254 }
3255
3256
3301 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3257 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3302 // ----------- S t a t e ------------- 3258 // ----------- S t a t e -------------
3303 // -- r0 : argc 3259 // -- r0 : argc
3304 // -- r1 : constructor 3260 // -- r1 : constructor
3305 // -- lr : return address 3261 // -- lr : return address
3306 // -- [sp] : last argument 3262 // -- [sp] : last argument
3307 // ----------------------------------- 3263 // -----------------------------------
3308 Label generic_stub_call; 3264 Label generic_stub_call;
3309 3265
3310 // Use r7 for holding undefined which is used in several places below. 3266 // Use r7 for holding undefined which is used in several places below.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
3435 // construction. 3391 // construction.
3436 __ bind(&generic_stub_call); 3392 __ bind(&generic_stub_call);
3437 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric(); 3393 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric();
3438 __ Jump(code, RelocInfo::CODE_TARGET); 3394 __ Jump(code, RelocInfo::CODE_TARGET);
3439 3395
3440 // Return the generated code. 3396 // Return the generated code.
3441 return GetCode(); 3397 return GetCode();
3442 } 3398 }
3443 3399
3444 3400
3401 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3402 JSObject*receiver, ExternalArrayType array_type) {
3403 // ----------- S t a t e -------------
3404 // -- lr : return address
3405 // -- r0 : key
3406 // -- r1 : receiver
3407 // -----------------------------------
3408 MaybeObject* maybe_stub =
3409 KeyedLoadExternalArrayStub(array_type).TryGetCode();
3410 Code* stub;
3411 if (!maybe_stub->To(&stub)) return maybe_stub;
3412 __ DispatchMap(r1,
3413 r2,
3414 Handle<Map>(receiver->map()),
3415 Handle<Code>(stub),
3416 DO_SMI_CHECK);
3417
3418 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3419 __ Jump(ic, RelocInfo::CODE_TARGET);
3420
3421 // Return the generated code.
3422 return GetCode();
3423 }
3424
3425
3426 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3427 JSObject* receiver, ExternalArrayType array_type) {
3428 // ----------- S t a t e -------------
3429 // -- r0 : value
3430 // -- r1 : name
3431 // -- r2 : receiver
3432 // -- lr : return address
3433 // -----------------------------------
3434 MaybeObject* maybe_stub =
3435 KeyedStoreExternalArrayStub(array_type).TryGetCode();
3436 Code* stub;
3437 if (!maybe_stub->To(&stub)) return maybe_stub;
3438 __ DispatchMap(r2,
3439 r3,
3440 Handle<Map>(receiver->map()),
3441 Handle<Code>(stub),
3442 DONT_DO_SMI_CHECK);
3443
3444 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3445 __ Jump(ic, RelocInfo::CODE_TARGET);
3446
3447 return GetCode();
3448 }
3449
3450
3451 #undef __
3452 #define __ ACCESS_MASM(masm)
3453
3454
3445 static bool IsElementTypeSigned(ExternalArrayType array_type) { 3455 static bool IsElementTypeSigned(ExternalArrayType array_type) {
3446 switch (array_type) { 3456 switch (array_type) {
3447 case kExternalByteArray: 3457 case kExternalByteArray:
3448 case kExternalShortArray: 3458 case kExternalShortArray:
3449 case kExternalIntArray: 3459 case kExternalIntArray:
3450 return true; 3460 return true;
3451 3461
3452 case kExternalUnsignedByteArray: 3462 case kExternalUnsignedByteArray:
3453 case kExternalUnsignedShortArray: 3463 case kExternalUnsignedShortArray:
3454 case kExternalUnsignedIntArray: 3464 case kExternalUnsignedIntArray:
3455 return false; 3465 return false;
3456 3466
3457 default: 3467 default:
3458 UNREACHABLE(); 3468 UNREACHABLE();
3459 return false; 3469 return false;
3460 } 3470 }
3461 } 3471 }
3462 3472
3463 3473
3464 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3474 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3465 JSObject* receiver_object, 3475 MacroAssembler* masm,
3466 ExternalArrayType array_type, 3476 ExternalArrayType array_type) {
3467 Code::Flags flags) {
3468 // ---------- S t a t e -------------- 3477 // ---------- S t a t e --------------
3469 // -- lr : return address 3478 // -- lr : return address
3470 // -- r0 : key 3479 // -- r0 : key
3471 // -- r1 : receiver 3480 // -- r1 : receiver
3472 // ----------------------------------- 3481 // -----------------------------------
3473 Label slow, failed_allocation; 3482 Label miss_force_generic, slow, failed_allocation;
3474 3483
3475 Register key = r0; 3484 Register key = r0;
3476 Register receiver = r1; 3485 Register receiver = r1;
3477 3486
3478 // Check that the object isn't a smi 3487 // This stub is meant to be tail-jumped to, the receiver must already
3479 __ JumpIfSmi(receiver, &slow); 3488 // have been verified by the caller to not be a smi.
3480 3489
3481 // Check that the key is a smi. 3490 // Check that the key is a smi.
3482 __ JumpIfNotSmi(key, &slow); 3491 __ JumpIfNotSmi(key, &miss_force_generic);
3483
3484 // Make sure that we've got the right map.
3485 __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
3486 __ cmp(r2, Operand(Handle<Map>(receiver_object->map())));
3487 __ b(ne, &slow);
3488 3492
3489 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 3493 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
3490 // r3: elements array 3494 // r3: elements array
3491 3495
3492 // Check that the index is in range. 3496 // Check that the index is in range.
3493 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 3497 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
3494 __ cmp(ip, Operand(key, ASR, kSmiTagSize)); 3498 __ cmp(ip, Operand(key, ASR, kSmiTagSize));
3495 // Unsigned comparison catches both negative and too-large values. 3499 // Unsigned comparison catches both negative and too-large values.
3496 __ b(lo, &slow); 3500 __ b(lo, &miss_force_generic);
3497 3501
3498 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 3502 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
3499 // r3: base pointer of external storage 3503 // r3: base pointer of external storage
3500 3504
3501 // We are not untagging smi key and instead work with it 3505 // We are not untagging smi key and instead work with it
3502 // as if it was premultiplied by 2. 3506 // as if it was premultiplied by 2.
3503 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); 3507 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
3504 3508
3505 Register value = r2; 3509 Register value = r2;
3506 switch (array_type) { 3510 switch (array_type) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3623 __ b(ne, &box_int_1); 3627 __ b(ne, &box_int_1);
3624 // Tag integer as smi and return it. 3628 // Tag integer as smi and return it.
3625 __ mov(r0, Operand(value, LSL, kSmiTagSize)); 3629 __ mov(r0, Operand(value, LSL, kSmiTagSize));
3626 __ Ret(); 3630 __ Ret();
3627 3631
3628 Register hiword = value; // r2. 3632 Register hiword = value; // r2.
3629 Register loword = r3; 3633 Register loword = r3;
3630 3634
3631 __ bind(&box_int_0); 3635 __ bind(&box_int_0);
3632 // Integer does not have leading zeros. 3636 // Integer does not have leading zeros.
3633 GenerateUInt2Double(masm(), hiword, loword, r4, 0); 3637 GenerateUInt2Double(masm, hiword, loword, r4, 0);
3634 __ b(&done); 3638 __ b(&done);
3635 3639
3636 __ bind(&box_int_1); 3640 __ bind(&box_int_1);
3637 // Integer has one leading zero. 3641 // Integer has one leading zero.
3638 GenerateUInt2Double(masm(), hiword, loword, r4, 1); 3642 GenerateUInt2Double(masm, hiword, loword, r4, 1);
3639 3643
3640 3644
3641 __ bind(&done); 3645 __ bind(&done);
3642 // Integer was converted to double in registers hiword:loword. 3646 // Integer was converted to double in registers hiword:loword.
3643 // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber 3647 // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber
3644 // clobbers all registers - also when jumping due to exhausted young 3648 // clobbers all registers - also when jumping due to exhausted young
3645 // space. 3649 // space.
3646 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 3650 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
3647 __ AllocateHeapNumber(r4, r5, r7, r6, &slow); 3651 __ AllocateHeapNumber(r4, r5, r7, r6, &slow);
3648 3652
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
3750 3754
3751 } else { 3755 } else {
3752 // Tag integer as smi and return it. 3756 // Tag integer as smi and return it.
3753 __ mov(r0, Operand(value, LSL, kSmiTagSize)); 3757 __ mov(r0, Operand(value, LSL, kSmiTagSize));
3754 __ Ret(); 3758 __ Ret();
3755 } 3759 }
3756 3760
3757 // Slow case, key and receiver still in r0 and r1. 3761 // Slow case, key and receiver still in r0 and r1.
3758 __ bind(&slow); 3762 __ bind(&slow);
3759 __ IncrementCounter( 3763 __ IncrementCounter(
3760 masm()->isolate()->counters()->keyed_load_external_array_slow(), 3764 masm->isolate()->counters()->keyed_load_external_array_slow(),
3761 1, r2, r3); 3765 1, r2, r3);
3762 3766
3763 // ---------- S t a t e -------------- 3767 // ---------- S t a t e --------------
3764 // -- lr : return address 3768 // -- lr : return address
3765 // -- r0 : key 3769 // -- r0 : key
3766 // -- r1 : receiver 3770 // -- r1 : receiver
3767 // ----------------------------------- 3771 // -----------------------------------
3768 3772
3769 __ Push(r1, r0); 3773 __ Push(r1, r0);
3770 3774
3771 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3775 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
3772 3776
3773 return GetCode(flags); 3777 __ bind(&miss_force_generic);
3778 Code* stub = masm->isolate()->builtins()->builtin(
3779 Builtins::kKeyedLoadIC_MissForceGeneric);
3780 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
3774 } 3781 }
3775 3782
3776 3783
3777 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3784 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3778 JSObject* receiver_object, 3785 MacroAssembler* masm,
3779 ExternalArrayType array_type, 3786 ExternalArrayType array_type) {
3780 Code::Flags flags) {
3781 // ---------- S t a t e -------------- 3787 // ---------- S t a t e --------------
3782 // -- r0 : value 3788 // -- r0 : value
3783 // -- r1 : key 3789 // -- r1 : key
3784 // -- r2 : receiver 3790 // -- r2 : receiver
3785 // -- lr : return address 3791 // -- lr : return address
3786 // ----------------------------------- 3792 // -----------------------------------
3787 Label slow, check_heap_number; 3793 Label slow, check_heap_number, miss_force_generic;
3788 3794
3789 // Register usage. 3795 // Register usage.
3790 Register value = r0; 3796 Register value = r0;
3791 Register key = r1; 3797 Register key = r1;
3792 Register receiver = r2; 3798 Register receiver = r2;
3793 // r3 mostly holds the elements array or the destination external array. 3799 // r3 mostly holds the elements array or the destination external array.
3794 3800
3795 // Check that the object isn't a smi. 3801 // This stub is meant to be tail-jumped to, the receiver must already
3796 __ JumpIfSmi(receiver, &slow); 3802 // have been verified by the caller to not be a smi.
3797
3798 // Make sure that we've got the right map.
3799 __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
3800 __ cmp(r3, Operand(Handle<Map>(receiver_object->map())));
3801 __ b(ne, &slow);
3802 3803
3803 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 3804 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
3804 3805
3805 // Check that the key is a smi. 3806 // Check that the key is a smi.
3806 __ JumpIfNotSmi(key, &slow); 3807 __ JumpIfNotSmi(key, &miss_force_generic);
3807 3808
3808 // Check that the index is in range 3809 // Check that the index is in range
3809 __ SmiUntag(r4, key); 3810 __ SmiUntag(r4, key);
3810 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 3811 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
3811 __ cmp(r4, ip); 3812 __ cmp(r4, ip);
3812 // Unsigned comparison catches both negative and too-large values. 3813 // Unsigned comparison catches both negative and too-large values.
3813 __ b(hs, &slow); 3814 __ b(hs, &miss_force_generic);
3814 3815
3815 // Handle both smis and HeapNumbers in the fast path. Go to the 3816 // Handle both smis and HeapNumbers in the fast path. Go to the
3816 // runtime for all other kinds of values. 3817 // runtime for all other kinds of values.
3817 // r3: external array. 3818 // r3: external array.
3818 // r4: key (integer). 3819 // r4: key (integer).
3819 if (array_type == kExternalPixelArray) { 3820 if (array_type == kExternalPixelArray) {
3820 // Double to pixel conversion is only implemented in the runtime for now. 3821 // Double to pixel conversion is only implemented in the runtime for now.
3821 __ JumpIfNotSmi(value, &slow); 3822 __ JumpIfNotSmi(value, &slow);
3822 } else { 3823 } else {
3823 __ JumpIfNotSmi(value, &check_heap_number); 3824 __ JumpIfNotSmi(value, &check_heap_number);
(...skipping 17 matching lines...) Expand all
3841 case kExternalShortArray: 3842 case kExternalShortArray:
3842 case kExternalUnsignedShortArray: 3843 case kExternalUnsignedShortArray:
3843 __ strh(r5, MemOperand(r3, r4, LSL, 1)); 3844 __ strh(r5, MemOperand(r3, r4, LSL, 1));
3844 break; 3845 break;
3845 case kExternalIntArray: 3846 case kExternalIntArray:
3846 case kExternalUnsignedIntArray: 3847 case kExternalUnsignedIntArray:
3847 __ str(r5, MemOperand(r3, r4, LSL, 2)); 3848 __ str(r5, MemOperand(r3, r4, LSL, 2));
3848 break; 3849 break;
3849 case kExternalFloatArray: 3850 case kExternalFloatArray:
3850 // Perform int-to-float conversion and store to memory. 3851 // Perform int-to-float conversion and store to memory.
3851 StoreIntAsFloat(masm(), r3, r4, r5, r6, r7, r9); 3852 StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9);
3852 break; 3853 break;
3853 case kExternalDoubleArray: 3854 case kExternalDoubleArray:
3854 __ add(r3, r3, Operand(r4, LSL, 3)); 3855 __ add(r3, r3, Operand(r4, LSL, 3));
3855 // r3: effective address of the double element 3856 // r3: effective address of the double element
3856 FloatingPointHelper::Destination destination; 3857 FloatingPointHelper::Destination destination;
3857 if (CpuFeatures::IsSupported(VFP3)) { 3858 if (CpuFeatures::IsSupported(VFP3)) {
3858 destination = FloatingPointHelper::kVFPRegisters; 3859 destination = FloatingPointHelper::kVFPRegisters;
3859 } else { 3860 } else {
3860 destination = FloatingPointHelper::kCoreRegisters; 3861 destination = FloatingPointHelper::kCoreRegisters;
3861 } 3862 }
3862 FloatingPointHelper::ConvertIntToDouble( 3863 FloatingPointHelper::ConvertIntToDouble(
3863 masm(), r5, destination, 3864 masm, r5, destination,
3864 d0, r6, r7, // These are: double_dst, dst1, dst2. 3865 d0, r6, r7, // These are: double_dst, dst1, dst2.
3865 r4, s2); // These are: scratch2, single_scratch. 3866 r4, s2); // These are: scratch2, single_scratch.
3866 if (destination == FloatingPointHelper::kVFPRegisters) { 3867 if (destination == FloatingPointHelper::kVFPRegisters) {
3867 CpuFeatures::Scope scope(VFP3); 3868 CpuFeatures::Scope scope(VFP3);
3868 __ vstr(d0, r3, 0); 3869 __ vstr(d0, r3, 0);
3869 } else { 3870 } else {
3870 __ str(r6, MemOperand(r3, 0)); 3871 __ str(r6, MemOperand(r3, 0));
3871 __ str(r7, MemOperand(r3, Register::kSizeInBytes)); 3872 __ str(r7, MemOperand(r3, Register::kSizeInBytes));
3872 } 3873 }
3873 break; 3874 break;
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
4080 __ str(r5, MemOperand(r3, r4, LSL, 2)); 4081 __ str(r5, MemOperand(r3, r4, LSL, 2));
4081 break; 4082 break;
4082 default: 4083 default:
4083 UNREACHABLE(); 4084 UNREACHABLE();
4084 break; 4085 break;
4085 } 4086 }
4086 } 4087 }
4087 } 4088 }
4088 } 4089 }
4089 4090
4090 // Slow case: call runtime. 4091 // Slow case, key and receiver still in r0 and r1.
4091 __ bind(&slow); 4092 __ bind(&slow);
4093 __ IncrementCounter(
4094 masm->isolate()->counters()->keyed_load_external_array_slow(),
4095 1, r2, r3);
4092 4096
4093 // Entry registers are intact.
4094 // ---------- S t a t e -------------- 4097 // ---------- S t a t e --------------
4095 // -- r0 : value
4096 // -- r1 : key
4097 // -- r2 : receiver
4098 // -- lr : return address 4098 // -- lr : return address
4099 // -- r0 : key
4100 // -- r1 : receiver
4101 // -----------------------------------
4102 Handle<Code> slow_ic =
4103 masm->isolate()->builtins()->KeyedStoreIC_Slow();
4104 __ Jump(slow_ic, RelocInfo::CODE_TARGET);
4105
4106 // Miss case, call the runtime.
4107 __ bind(&miss_force_generic);
4108
4109 // ---------- S t a t e --------------
4110 // -- lr : return address
4111 // -- r0 : key
4112 // -- r1 : receiver
4099 // ----------------------------------- 4113 // -----------------------------------
4100 4114
4101 // Push receiver, key and value for runtime call. 4115 Handle<Code> miss_ic =
4102 __ Push(r2, r1, r0); 4116 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4117 __ Jump(miss_ic, RelocInfo::CODE_TARGET);
4118 }
4103 4119
4104 __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes
4105 __ mov(r0, Operand(Smi::FromInt(
4106 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
4107 __ Push(r1, r0);
4108 4120
4109 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 4121 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
4122 // ----------- S t a t e -------------
4123 // -- lr : return address
4124 // -- r0 : key
4125 // -- r1 : receiver
4126 // -----------------------------------
4127 Label miss_force_generic;
4110 4128
4111 return GetCode(flags); 4129 // This stub is meant to be tail-jumped to, the receiver must already
4130 // have been verified by the caller to not be a smi.
4131
4132 // Check that the key is a smi.
4133 __ JumpIfNotSmi(r0, &miss_force_generic);
4134
4135 // Get the elements array.
4136 __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
4137 __ AssertFastElements(r2);
4138
4139 // Check that the key is within bounds.
4140 __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
4141 __ cmp(r0, Operand(r3));
4142 __ b(hs, &miss_force_generic);
4143
4144 // Load the result and make sure it's not the hole.
4145 __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4146 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4147 __ ldr(r4,
4148 MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
4149 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
4150 __ cmp(r4, ip);
4151 __ b(eq, &miss_force_generic);
4152 __ mov(r0, r4);
4153 __ Ret();
4154
4155 __ bind(&miss_force_generic);
4156 Code* stub = masm->isolate()->builtins()->builtin(
4157 Builtins::kKeyedLoadIC_MissForceGeneric);
4158 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
4159 }
4160
4161
4162 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
4163 bool is_js_array) {
4164 // ----------- S t a t e -------------
4165 // -- r0 : value
4166 // -- r1 : key
4167 // -- r2 : receiver
4168 // -- lr : return address
4169 // -- r3 : scratch
4170 // -- r4 : scratch (elements)
4171 // -----------------------------------
4172 Label miss_force_generic;
4173
4174 Register value_reg = r0;
4175 Register key_reg = r1;
4176 Register receiver_reg = r2;
4177 Register scratch = r3;
4178 Register elements_reg = r4;
4179
4180 // This stub is meant to be tail-jumped to, the receiver must already
4181 // have been verified by the caller to not be a smi.
4182
4183 // Check that the key is a smi.
4184 __ JumpIfNotSmi(r0, &miss_force_generic);
4185
4186 // Get the elements array and make sure it is a fast element array, not 'cow'.
4187 __ ldr(elements_reg,
4188 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4189 __ CheckMap(elements_reg,
4190 scratch,
4191 Heap::kFixedArrayMapRootIndex,
4192 &miss_force_generic,
4193 DONT_DO_SMI_CHECK);
4194
4195 // Check that the key is within bounds.
4196 if (is_js_array) {
4197 __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4198 } else {
4199 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4200 }
4201 // Compare smis.
4202 __ cmp(key_reg, scratch);
4203 __ b(hs, &miss_force_generic);
4204
4205 __ add(scratch,
4206 elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4207 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4208 __ str(value_reg,
4209 MemOperand(scratch, key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
4210 __ RecordWrite(scratch,
4211 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize),
4212 receiver_reg , elements_reg);
4213
4214 // value_reg (r0) is preserved.
4215 // Done.
4216 __ Ret();
4217
4218 __ bind(&miss_force_generic);
4219 Handle<Code> ic =
4220 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4221 __ Jump(ic, RelocInfo::CODE_TARGET);
4112 } 4222 }
4113 4223
4114 4224
4115 #undef __ 4225 #undef __
4116 4226
4117 } } // namespace v8::internal 4227 } } // namespace v8::internal
4118 4228
4119 #endif // V8_TARGET_ARCH_ARM 4229 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/simulator-arm.cc ('k') | src/assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698