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

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

Issue 500923002: x87: Move IC code into a subdir and move ic-compilation related code from stub-cache into ic-compil… (Closed) Base URL: https://chromium.googlesource.com/external/v8.git@bleeding_edge
Patch Set: Created 6 years, 3 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
« no previous file with comments | « src/ic/x87/ic-compiler-x87.cc ('k') | src/ic/x87/stub-cache-x87.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_X87 7 #if V8_TARGET_ARCH_X87
8 8
9 #include "src/codegen.h" 9 #include "src/codegen.h"
10 #include "src/ic-inl.h" 10 #include "src/ic/ic.h"
11 #include "src/runtime.h" 11 #include "src/ic/stub-cache.h"
12 #include "src/stub-cache.h"
13 12
14 namespace v8 { 13 namespace v8 {
15 namespace internal { 14 namespace internal {
16 15
17 // ---------------------------------------------------------------------------- 16 // ----------------------------------------------------------------------------
18 // Static IC stub generators. 17 // Static IC stub generators.
19 // 18 //
20 19
21 #define __ ACCESS_MASM(masm) 20 #define __ ACCESS_MASM(masm)
22 21
23 22
24 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, 23 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type,
25 Register type,
26 Label* global_object) { 24 Label* global_object) {
27 // Register usage: 25 // Register usage:
28 // type: holds the receiver instance type on entry. 26 // type: holds the receiver instance type on entry.
29 __ cmp(type, JS_GLOBAL_OBJECT_TYPE); 27 __ cmp(type, JS_GLOBAL_OBJECT_TYPE);
30 __ j(equal, global_object); 28 __ j(equal, global_object);
31 __ cmp(type, JS_BUILTINS_OBJECT_TYPE); 29 __ cmp(type, JS_BUILTINS_OBJECT_TYPE);
32 __ j(equal, global_object); 30 __ j(equal, global_object);
33 __ cmp(type, JS_GLOBAL_PROXY_TYPE); 31 __ cmp(type, JS_GLOBAL_PROXY_TYPE);
34 __ j(equal, global_object); 32 __ j(equal, global_object);
35 } 33 }
36 34
37 35
38 // Helper function used to load a property from a dictionary backing 36 // Helper function used to load a property from a dictionary backing
39 // storage. This function may fail to load a property even though it is 37 // storage. This function may fail to load a property even though it is
40 // in the dictionary, so code at miss_label must always call a backup 38 // in the dictionary, so code at miss_label must always call a backup
41 // property load that is complete. This function is safe to call if 39 // property load that is complete. This function is safe to call if
42 // name is not internalized, and will jump to the miss_label in that 40 // name is not internalized, and will jump to the miss_label in that
43 // case. The generated code assumes that the receiver has slow 41 // case. The generated code assumes that the receiver has slow
44 // properties, is not a global object and does not have interceptors. 42 // properties, is not a global object and does not have interceptors.
45 static void GenerateDictionaryLoad(MacroAssembler* masm, 43 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
46 Label* miss_label, 44 Register elements, Register name,
47 Register elements, 45 Register r0, Register r1, Register result) {
48 Register name,
49 Register r0,
50 Register r1,
51 Register result) {
52 // Register use: 46 // Register use:
53 // 47 //
54 // elements - holds the property dictionary on entry and is unchanged. 48 // elements - holds the property dictionary on entry and is unchanged.
55 // 49 //
56 // name - holds the name of the property on entry and is unchanged. 50 // name - holds the name of the property on entry and is unchanged.
57 // 51 //
58 // Scratch registers: 52 // Scratch registers:
59 // 53 //
60 // r0 - used for the index into the property dictionary 54 // r0 - used for the index into the property dictionary
61 // 55 //
62 // r1 - used to hold the capacity of the property dictionary. 56 // r1 - used to hold the capacity of the property dictionary.
63 // 57 //
64 // result - holds the result on exit. 58 // result - holds the result on exit.
65 59
66 Label done; 60 Label done;
67 61
68 // Probe the dictionary. 62 // Probe the dictionary.
69 NameDictionaryLookupStub::GeneratePositiveLookup(masm, 63 NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss_label, &done,
70 miss_label, 64 elements, name, r0, r1);
71 &done,
72 elements,
73 name,
74 r0,
75 r1);
76 65
77 // If probing finds an entry in the dictionary, r0 contains the 66 // If probing finds an entry in the dictionary, r0 contains the
78 // index into the dictionary. Check that the value is a normal 67 // index into the dictionary. Check that the value is a normal
79 // property. 68 // property.
80 __ bind(&done); 69 __ bind(&done);
81 const int kElementsStartOffset = 70 const int kElementsStartOffset =
82 NameDictionary::kHeaderSize + 71 NameDictionary::kHeaderSize +
83 NameDictionary::kElementsStartIndex * kPointerSize; 72 NameDictionary::kElementsStartIndex * kPointerSize;
84 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 73 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
85 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 74 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
86 Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); 75 Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
87 __ j(not_zero, miss_label); 76 __ j(not_zero, miss_label);
88 77
89 // Get the value at the masked, scaled index. 78 // Get the value at the masked, scaled index.
90 const int kValueOffset = kElementsStartOffset + kPointerSize; 79 const int kValueOffset = kElementsStartOffset + kPointerSize;
91 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 80 __ mov(result, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
92 } 81 }
93 82
94 83
95 // Helper function used to store a property to a dictionary backing 84 // Helper function used to store a property to a dictionary backing
96 // storage. This function may fail to store a property eventhough it 85 // storage. This function may fail to store a property eventhough it
97 // is in the dictionary, so code at miss_label must always call a 86 // is in the dictionary, so code at miss_label must always call a
98 // backup property store that is complete. This function is safe to 87 // backup property store that is complete. This function is safe to
99 // call if name is not internalized, and will jump to the miss_label in 88 // call if name is not internalized, and will jump to the miss_label in
100 // that case. The generated code assumes that the receiver has slow 89 // that case. The generated code assumes that the receiver has slow
101 // properties, is not a global object and does not have interceptors. 90 // properties, is not a global object and does not have interceptors.
102 static void GenerateDictionaryStore(MacroAssembler* masm, 91 static void GenerateDictionaryStore(MacroAssembler* masm, Label* miss_label,
103 Label* miss_label, 92 Register elements, Register name,
104 Register elements, 93 Register value, Register r0, Register r1) {
105 Register name,
106 Register value,
107 Register r0,
108 Register r1) {
109 // Register use: 94 // Register use:
110 // 95 //
111 // elements - holds the property dictionary on entry and is clobbered. 96 // elements - holds the property dictionary on entry and is clobbered.
112 // 97 //
113 // name - holds the name of the property on entry and is unchanged. 98 // name - holds the name of the property on entry and is unchanged.
114 // 99 //
115 // value - holds the value to store and is unchanged. 100 // value - holds the value to store and is unchanged.
116 // 101 //
117 // r0 - used for index into the property dictionary and is clobbered. 102 // r0 - used for index into the property dictionary and is clobbered.
118 // 103 //
119 // r1 - used to hold the capacity of the property dictionary and is clobbered. 104 // r1 - used to hold the capacity of the property dictionary and is clobbered.
120 Label done; 105 Label done;
121 106
122 107
123 // Probe the dictionary. 108 // Probe the dictionary.
124 NameDictionaryLookupStub::GeneratePositiveLookup(masm, 109 NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss_label, &done,
125 miss_label, 110 elements, name, r0, r1);
126 &done,
127 elements,
128 name,
129 r0,
130 r1);
131 111
132 // If probing finds an entry in the dictionary, r0 contains the 112 // If probing finds an entry in the dictionary, r0 contains the
133 // index into the dictionary. Check that the value is a normal 113 // index into the dictionary. Check that the value is a normal
134 // property that is not read only. 114 // property that is not read only.
135 __ bind(&done); 115 __ bind(&done);
136 const int kElementsStartOffset = 116 const int kElementsStartOffset =
137 NameDictionary::kHeaderSize + 117 NameDictionary::kHeaderSize +
138 NameDictionary::kElementsStartIndex * kPointerSize; 118 NameDictionary::kElementsStartIndex * kPointerSize;
139 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 119 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
140 const int kTypeAndReadOnlyMask = 120 const int kTypeAndReadOnlyMask =
141 (PropertyDetails::TypeField::kMask | 121 (PropertyDetails::TypeField::kMask |
142 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; 122 PropertyDetails::AttributesField::encode(READ_ONLY))
123 << kSmiTagSize;
143 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), 124 __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
144 Immediate(kTypeAndReadOnlyMask)); 125 Immediate(kTypeAndReadOnlyMask));
145 __ j(not_zero, miss_label); 126 __ j(not_zero, miss_label);
146 127
147 // Store the value at the masked, scaled index. 128 // Store the value at the masked, scaled index.
148 const int kValueOffset = kElementsStartOffset + kPointerSize; 129 const int kValueOffset = kElementsStartOffset + kPointerSize;
149 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 130 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
150 __ mov(Operand(r0, 0), value); 131 __ mov(Operand(r0, 0), value);
151 132
152 // Update write barrier. Make sure not to clobber the value. 133 // Update write barrier. Make sure not to clobber the value.
153 __ mov(r1, value); 134 __ mov(r1, value);
154 __ RecordWrite(elements, r0, r1); 135 __ RecordWrite(elements, r0, r1);
155 } 136 }
156 137
157 138
158 // Checks the receiver for special cases (value type, slow case bits). 139 // Checks the receiver for special cases (value type, slow case bits).
159 // Falls through for regular JS object. 140 // Falls through for regular JS object.
160 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 141 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
161 Register receiver, 142 Register receiver, Register map,
162 Register map, 143 int interceptor_bit, Label* slow) {
163 int interceptor_bit,
164 Label* slow) {
165 // Register use: 144 // Register use:
166 // receiver - holds the receiver and is unchanged. 145 // receiver - holds the receiver and is unchanged.
167 // Scratch registers: 146 // Scratch registers:
168 // map - used to hold the map of the receiver. 147 // map - used to hold the map of the receiver.
169 148
170 // Check that the object isn't a smi. 149 // Check that the object isn't a smi.
171 __ JumpIfSmi(receiver, slow); 150 __ JumpIfSmi(receiver, slow);
172 151
173 // Get the map of the receiver. 152 // Get the map of the receiver.
174 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); 153 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset));
175 154
176 // Check bit field. 155 // Check bit field.
177 __ test_b(FieldOperand(map, Map::kBitFieldOffset), 156 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
178 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); 157 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit));
179 __ j(not_zero, slow); 158 __ j(not_zero, slow);
180 // Check that the object is some kind of JS object EXCEPT JS Value type. 159 // Check that the object is some kind of JS object EXCEPT JS Value type.
181 // In the case that the object is a value-wrapper object, 160 // In the case that the object is a value-wrapper object,
182 // we enter the runtime system to make sure that indexing 161 // we enter the runtime system to make sure that indexing
183 // into string objects works as intended. 162 // into string objects works as intended.
184 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); 163 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE);
185 164
186 __ CmpInstanceType(map, JS_OBJECT_TYPE); 165 __ CmpInstanceType(map, JS_OBJECT_TYPE);
187 __ j(below, slow); 166 __ j(below, slow);
188 } 167 }
189 168
190 169
191 // Loads an indexed element from a fast case array. 170 // Loads an indexed element from a fast case array.
192 // If not_fast_array is NULL, doesn't perform the elements map check. 171 // If not_fast_array is NULL, doesn't perform the elements map check.
193 static void GenerateFastArrayLoad(MacroAssembler* masm, 172 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
194 Register receiver, 173 Register key, Register scratch,
195 Register key, 174 Register result, Label* not_fast_array,
196 Register scratch,
197 Register result,
198 Label* not_fast_array,
199 Label* out_of_range) { 175 Label* out_of_range) {
200 // Register use: 176 // Register use:
201 // receiver - holds the receiver and is unchanged. 177 // receiver - holds the receiver and is unchanged.
202 // key - holds the key and is unchanged (must be a smi). 178 // key - holds the key and is unchanged (must be a smi).
203 // Scratch registers: 179 // Scratch registers:
204 // scratch - used to hold elements of the receiver and the loaded value. 180 // scratch - used to hold elements of the receiver and the loaded value.
205 // result - holds the result on exit if the load succeeds and 181 // result - holds the result on exit if the load succeeds and
206 // we fall through. 182 // we fall through.
207 183
208 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); 184 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
(...skipping 17 matching lines...) Expand all
226 // to ensure the prototype chain is searched. 202 // to ensure the prototype chain is searched.
227 __ j(equal, out_of_range); 203 __ j(equal, out_of_range);
228 if (!result.is(scratch)) { 204 if (!result.is(scratch)) {
229 __ mov(result, scratch); 205 __ mov(result, scratch);
230 } 206 }
231 } 207 }
232 208
233 209
234 // Checks whether a key is an array index string or a unique name. 210 // Checks whether a key is an array index string or a unique name.
235 // Falls through if the key is a unique name. 211 // Falls through if the key is a unique name.
236 static void GenerateKeyNameCheck(MacroAssembler* masm, 212 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
237 Register key, 213 Register map, Register hash,
238 Register map, 214 Label* index_string, Label* not_unique) {
239 Register hash,
240 Label* index_string,
241 Label* not_unique) {
242 // Register use: 215 // Register use:
243 // key - holds the key and is unchanged. Assumed to be non-smi. 216 // key - holds the key and is unchanged. Assumed to be non-smi.
244 // Scratch registers: 217 // Scratch registers:
245 // map - used to hold the map of the key. 218 // map - used to hold the map of the key.
246 // hash - used to hold the hash of the key. 219 // hash - used to hold the hash of the key.
247 Label unique; 220 Label unique;
248 __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map); 221 __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map);
249 __ j(above, not_unique); 222 __ j(above, not_unique);
250 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); 223 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
251 __ j(equal, &unique); 224 __ j(equal, &unique);
252 225
253 // Is the string an array index, with cached numeric value? 226 // Is the string an array index, with cached numeric value?
254 __ mov(hash, FieldOperand(key, Name::kHashFieldOffset)); 227 __ mov(hash, FieldOperand(key, Name::kHashFieldOffset));
255 __ test(hash, Immediate(Name::kContainsCachedArrayIndexMask)); 228 __ test(hash, Immediate(Name::kContainsCachedArrayIndexMask));
256 __ j(zero, index_string); 229 __ j(zero, index_string);
257 230
258 // Is the string internalized? We already know it's a string so a single 231 // Is the string internalized? We already know it's a string so a single
259 // bit test is enough. 232 // bit test is enough.
260 STATIC_ASSERT(kNotInternalizedTag != 0); 233 STATIC_ASSERT(kNotInternalizedTag != 0);
261 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), 234 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset),
262 kIsNotInternalizedMask); 235 kIsNotInternalizedMask);
263 __ j(not_zero, not_unique); 236 __ j(not_zero, not_unique);
264 237
265 __ bind(&unique); 238 __ bind(&unique);
266 } 239 }
267 240
268 241
269 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, 242 static Operand GenerateMappedArgumentsLookup(
270 Register object, 243 MacroAssembler* masm, Register object, Register key, Register scratch1,
271 Register key, 244 Register scratch2, Label* unmapped_case, Label* slow_case) {
272 Register scratch1,
273 Register scratch2,
274 Label* unmapped_case,
275 Label* slow_case) {
276 Heap* heap = masm->isolate()->heap(); 245 Heap* heap = masm->isolate()->heap();
277 Factory* factory = masm->isolate()->factory(); 246 Factory* factory = masm->isolate()->factory();
278 247
279 // Check that the receiver is a JSObject. Because of the elements 248 // Check that the receiver is a JSObject. Because of the elements
280 // map check later, we do not need to check for interceptors or 249 // map check later, we do not need to check for interceptors or
281 // whether it requires access checks. 250 // whether it requires access checks.
282 __ JumpIfSmi(object, slow_case); 251 __ JumpIfSmi(object, slow_case);
283 // Check that the object is some kind of JSObject. 252 // Check that the object is some kind of JSObject.
284 __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1); 253 __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1);
285 __ j(below, slow_case); 254 __ j(below, slow_case);
286 255
287 // Check that the key is a positive smi. 256 // Check that the key is a positive smi.
288 __ test(key, Immediate(0x80000001)); 257 __ test(key, Immediate(0x80000001));
289 __ j(not_zero, slow_case); 258 __ j(not_zero, slow_case);
290 259
291 // Load the elements into scratch1 and check its map. 260 // Load the elements into scratch1 and check its map.
292 Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); 261 Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
293 __ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset)); 262 __ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset));
294 __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK); 263 __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
295 264
296 // Check if element is in the range of mapped arguments. If not, jump 265 // Check if element is in the range of mapped arguments. If not, jump
297 // to the unmapped lookup with the parameter map in scratch1. 266 // to the unmapped lookup with the parameter map in scratch1.
298 __ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset)); 267 __ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset));
299 __ sub(scratch2, Immediate(Smi::FromInt(2))); 268 __ sub(scratch2, Immediate(Smi::FromInt(2)));
300 __ cmp(key, scratch2); 269 __ cmp(key, scratch2);
301 __ j(above_equal, unmapped_case); 270 __ j(above_equal, unmapped_case);
302 271
303 // Load element index and check whether it is the hole. 272 // Load element index and check whether it is the hole.
304 const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize; 273 const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize;
305 __ mov(scratch2, FieldOperand(scratch1, 274 __ mov(scratch2,
306 key, 275 FieldOperand(scratch1, key, times_half_pointer_size, kHeaderSize));
307 times_half_pointer_size,
308 kHeaderSize));
309 __ cmp(scratch2, factory->the_hole_value()); 276 __ cmp(scratch2, factory->the_hole_value());
310 __ j(equal, unmapped_case); 277 __ j(equal, unmapped_case);
311 278
312 // Load value from context and return it. We can reuse scratch1 because 279 // Load value from context and return it. We can reuse scratch1 because
313 // we do not jump to the unmapped lookup (which requires the parameter 280 // we do not jump to the unmapped lookup (which requires the parameter
314 // map in scratch1). 281 // map in scratch1).
315 const int kContextOffset = FixedArray::kHeaderSize; 282 const int kContextOffset = FixedArray::kHeaderSize;
316 __ mov(scratch1, FieldOperand(scratch1, kContextOffset)); 283 __ mov(scratch1, FieldOperand(scratch1, kContextOffset));
317 return FieldOperand(scratch1, 284 return FieldOperand(scratch1, scratch2, times_half_pointer_size,
318 scratch2,
319 times_half_pointer_size,
320 Context::kHeaderSize); 285 Context::kHeaderSize);
321 } 286 }
322 287
323 288
324 static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, 289 static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
325 Register key, 290 Register key,
326 Register parameter_map, 291 Register parameter_map,
327 Register scratch, 292 Register scratch,
328 Label* slow_case) { 293 Label* slow_case) {
329 // Element is in arguments backing store, which is referenced by the 294 // Element is in arguments backing store, which is referenced by the
330 // second element of the parameter_map. 295 // second element of the parameter_map.
331 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; 296 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
332 Register backing_store = parameter_map; 297 Register backing_store = parameter_map;
333 __ mov(backing_store, FieldOperand(parameter_map, kBackingStoreOffset)); 298 __ mov(backing_store, FieldOperand(parameter_map, kBackingStoreOffset));
334 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); 299 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
335 __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); 300 __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK);
336 __ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset)); 301 __ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset));
337 __ cmp(key, scratch); 302 __ cmp(key, scratch);
338 __ j(greater_equal, slow_case); 303 __ j(greater_equal, slow_case);
339 return FieldOperand(backing_store, 304 return FieldOperand(backing_store, key, times_half_pointer_size,
340 key,
341 times_half_pointer_size,
342 FixedArray::kHeaderSize); 305 FixedArray::kHeaderSize);
343 } 306 }
344 307
345 308
346 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 309 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
347 // The return address is on the stack. 310 // The return address is on the stack.
348 Label slow, check_name, index_smi, index_name, property_array_property; 311 Label slow, check_name, index_smi, index_name, property_array_property;
349 Label probe_dictionary, check_number_dictionary; 312 Label probe_dictionary, check_number_dictionary;
350 313
351 Register receiver = ReceiverRegister(); 314 Register receiver = ReceiverRegister();
352 Register key = NameRegister(); 315 Register key = NameRegister();
353 DCHECK(receiver.is(edx)); 316 DCHECK(receiver.is(edx));
354 DCHECK(key.is(ecx)); 317 DCHECK(key.is(ecx));
355 318
356 // Check that the key is a smi. 319 // Check that the key is a smi.
357 __ JumpIfNotSmi(key, &check_name); 320 __ JumpIfNotSmi(key, &check_name);
358 __ bind(&index_smi); 321 __ bind(&index_smi);
359 // Now the key is known to be a smi. This place is also jumped to from 322 // Now the key is known to be a smi. This place is also jumped to from
360 // where a numeric string is converted to a smi. 323 // where a numeric string is converted to a smi.
361 324
362 GenerateKeyedLoadReceiverCheck( 325 GenerateKeyedLoadReceiverCheck(masm, receiver, eax,
363 masm, receiver, eax, Map::kHasIndexedInterceptor, &slow); 326 Map::kHasIndexedInterceptor, &slow);
364 327
365 // Check the receiver's map to see if it has fast elements. 328 // Check the receiver's map to see if it has fast elements.
366 __ CheckFastElements(eax, &check_number_dictionary); 329 __ CheckFastElements(eax, &check_number_dictionary);
367 330
368 GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow); 331 GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow);
369 Isolate* isolate = masm->isolate(); 332 Isolate* isolate = masm->isolate();
370 Counters* counters = isolate->counters(); 333 Counters* counters = isolate->counters();
371 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); 334 __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
372 __ ret(0); 335 __ ret(0);
373 336
374 __ bind(&check_number_dictionary); 337 __ bind(&check_number_dictionary);
375 __ mov(ebx, key); 338 __ mov(ebx, key);
376 __ SmiUntag(ebx); 339 __ SmiUntag(ebx);
377 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); 340 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset));
378 341
379 // Check whether the elements is a number dictionary. 342 // Check whether the elements is a number dictionary.
380 // ebx: untagged index 343 // ebx: untagged index
381 // eax: elements 344 // eax: elements
382 __ CheckMap(eax, 345 __ CheckMap(eax, isolate->factory()->hash_table_map(), &slow,
383 isolate->factory()->hash_table_map(),
384 &slow,
385 DONT_DO_SMI_CHECK); 346 DONT_DO_SMI_CHECK);
386 Label slow_pop_receiver; 347 Label slow_pop_receiver;
387 // Push receiver on the stack to free up a register for the dictionary 348 // Push receiver on the stack to free up a register for the dictionary
388 // probing. 349 // probing.
389 __ push(receiver); 350 __ push(receiver);
390 __ LoadFromNumberDictionary(&slow_pop_receiver, eax, key, ebx, edx, edi, eax); 351 __ LoadFromNumberDictionary(&slow_pop_receiver, eax, key, ebx, edx, edi, eax);
391 // Pop receiver before returning. 352 // Pop receiver before returning.
392 __ pop(receiver); 353 __ pop(receiver);
393 __ ret(0); 354 __ ret(0);
394 355
395 __ bind(&slow_pop_receiver); 356 __ bind(&slow_pop_receiver);
396 // Pop the receiver from the stack and jump to runtime. 357 // Pop the receiver from the stack and jump to runtime.
397 __ pop(receiver); 358 __ pop(receiver);
398 359
399 __ bind(&slow); 360 __ bind(&slow);
400 // Slow case: jump to runtime. 361 // Slow case: jump to runtime.
401 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); 362 __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
402 GenerateRuntimeGetProperty(masm); 363 GenerateRuntimeGetProperty(masm);
403 364
404 __ bind(&check_name); 365 __ bind(&check_name);
405 GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow); 366 GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
406 367
407 GenerateKeyedLoadReceiverCheck( 368 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, Map::kHasNamedInterceptor,
408 masm, receiver, eax, Map::kHasNamedInterceptor, &slow); 369 &slow);
409 370
410 // If the receiver is a fast-case object, check the keyed lookup 371 // If the receiver is a fast-case object, check the keyed lookup
411 // cache. Otherwise probe the dictionary. 372 // cache. Otherwise probe the dictionary.
412 __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset)); 373 __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset));
413 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 374 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
414 Immediate(isolate->factory()->hash_table_map())); 375 Immediate(isolate->factory()->hash_table_map()));
415 __ j(equal, &probe_dictionary); 376 __ j(equal, &probe_dictionary);
416 377
417 // The receiver's map is still in eax, compute the keyed lookup cache hash 378 // The receiver's map is still in eax, compute the keyed lookup cache hash
418 // based on 32 bits of the map pointer and the string hash. 379 // based on 32 bits of the map pointer and the string hash.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 __ bind(&load_in_object_property); 446 __ bind(&load_in_object_property);
486 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset)); 447 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset));
487 __ add(eax, edi); 448 __ add(eax, edi);
488 __ mov(eax, FieldOperand(receiver, eax, times_pointer_size, 0)); 449 __ mov(eax, FieldOperand(receiver, eax, times_pointer_size, 0));
489 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); 450 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
490 __ ret(0); 451 __ ret(0);
491 452
492 // Load property array property. 453 // Load property array property.
493 __ bind(&property_array_property); 454 __ bind(&property_array_property);
494 __ mov(eax, FieldOperand(receiver, JSObject::kPropertiesOffset)); 455 __ mov(eax, FieldOperand(receiver, JSObject::kPropertiesOffset));
495 __ mov(eax, FieldOperand(eax, edi, times_pointer_size, 456 __ mov(eax,
496 FixedArray::kHeaderSize)); 457 FieldOperand(eax, edi, times_pointer_size, FixedArray::kHeaderSize));
497 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); 458 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
498 __ ret(0); 459 __ ret(0);
499 460
500 // Do a quick inline probe of the receiver's dictionary, if it 461 // Do a quick inline probe of the receiver's dictionary, if it
501 // exists. 462 // exists.
502 __ bind(&probe_dictionary); 463 __ bind(&probe_dictionary);
503 464
504 __ mov(eax, FieldOperand(receiver, JSObject::kMapOffset)); 465 __ mov(eax, FieldOperand(receiver, JSObject::kMapOffset));
505 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); 466 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
506 GenerateGlobalInstanceTypeCheck(masm, eax, &slow); 467 GenerateGlobalInstanceTypeCheck(masm, eax, &slow);
(...skipping 13 matching lines...) Expand all
520 // Return address is on the stack. 481 // Return address is on the stack.
521 Label miss; 482 Label miss;
522 483
523 Register receiver = ReceiverRegister(); 484 Register receiver = ReceiverRegister();
524 Register index = NameRegister(); 485 Register index = NameRegister();
525 Register scratch = ebx; 486 Register scratch = ebx;
526 DCHECK(!scratch.is(receiver) && !scratch.is(index)); 487 DCHECK(!scratch.is(receiver) && !scratch.is(index));
527 Register result = eax; 488 Register result = eax;
528 DCHECK(!result.is(scratch)); 489 DCHECK(!result.is(scratch));
529 490
530 StringCharAtGenerator char_at_generator(receiver, 491 StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
531 index,
532 scratch,
533 result,
534 &miss, // When not a string. 492 &miss, // When not a string.
535 &miss, // When not a number. 493 &miss, // When not a number.
536 &miss, // When index out of range. 494 &miss, // When index out of range.
537 STRING_INDEX_IS_ARRAY_INDEX); 495 STRING_INDEX_IS_ARRAY_INDEX);
538 char_at_generator.GenerateFast(masm); 496 char_at_generator.GenerateFast(masm);
539 __ ret(0); 497 __ ret(0);
540 498
541 StubRuntimeCallHelper call_helper; 499 StubRuntimeCallHelper call_helper;
542 char_at_generator.GenerateSlow(masm, call_helper); 500 char_at_generator.GenerateSlow(masm, call_helper);
543 501
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 548
591 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { 549 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
592 // The return address is on the stack. 550 // The return address is on the stack.
593 Register receiver = ReceiverRegister(); 551 Register receiver = ReceiverRegister();
594 Register key = NameRegister(); 552 Register key = NameRegister();
595 DCHECK(receiver.is(edx)); 553 DCHECK(receiver.is(edx));
596 DCHECK(key.is(ecx)); 554 DCHECK(key.is(ecx));
597 555
598 Label slow, notin; 556 Label slow, notin;
599 Factory* factory = masm->isolate()->factory(); 557 Factory* factory = masm->isolate()->factory();
600 Operand mapped_location = 558 Operand mapped_location = GenerateMappedArgumentsLookup(
601 GenerateMappedArgumentsLookup( 559 masm, receiver, key, ebx, eax, &notin, &slow);
602 masm, receiver, key, ebx, eax, &notin, &slow);
603 __ mov(eax, mapped_location); 560 __ mov(eax, mapped_location);
604 __ Ret(); 561 __ Ret();
605 __ bind(&notin); 562 __ bind(&notin);
606 // The unmapped lookup expects that the parameter map is in ebx. 563 // The unmapped lookup expects that the parameter map is in ebx.
607 Operand unmapped_location = 564 Operand unmapped_location =
608 GenerateUnmappedArgumentsLookup(masm, key, ebx, eax, &slow); 565 GenerateUnmappedArgumentsLookup(masm, key, ebx, eax, &slow);
609 __ cmp(unmapped_location, factory->the_hole_value()); 566 __ cmp(unmapped_location, factory->the_hole_value());
610 __ j(equal, &slow); 567 __ j(equal, &slow);
611 __ mov(eax, unmapped_location); 568 __ mov(eax, unmapped_location);
612 __ Ret(); 569 __ Ret();
613 __ bind(&slow); 570 __ bind(&slow);
614 GenerateMiss(masm); 571 GenerateMiss(masm);
615 } 572 }
616 573
617 574
618 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { 575 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
619 // Return address is on the stack. 576 // Return address is on the stack.
620 Label slow, notin; 577 Label slow, notin;
621 Register receiver = ReceiverRegister(); 578 Register receiver = ReceiverRegister();
622 Register name = NameRegister(); 579 Register name = NameRegister();
623 Register value = ValueRegister(); 580 Register value = ValueRegister();
624 DCHECK(receiver.is(edx)); 581 DCHECK(receiver.is(edx));
625 DCHECK(name.is(ecx)); 582 DCHECK(name.is(ecx));
626 DCHECK(value.is(eax)); 583 DCHECK(value.is(eax));
627 584
628 Operand mapped_location = 585 Operand mapped_location = GenerateMappedArgumentsLookup(
629 GenerateMappedArgumentsLookup(masm, receiver, name, ebx, edi, &notin, 586 masm, receiver, name, ebx, edi, &notin, &slow);
630 &slow);
631 __ mov(mapped_location, value); 587 __ mov(mapped_location, value);
632 __ lea(ecx, mapped_location); 588 __ lea(ecx, mapped_location);
633 __ mov(edx, value); 589 __ mov(edx, value);
634 __ RecordWrite(ebx, ecx, edx); 590 __ RecordWrite(ebx, ecx, edx);
635 __ Ret(); 591 __ Ret();
636 __ bind(&notin); 592 __ bind(&notin);
637 // The unmapped lookup expects that the parameter map is in ebx. 593 // The unmapped lookup expects that the parameter map is in ebx.
638 Operand unmapped_location = 594 Operand unmapped_location =
639 GenerateUnmappedArgumentsLookup(masm, name, ebx, edi, &slow); 595 GenerateUnmappedArgumentsLookup(masm, name, ebx, edi, &slow);
640 __ mov(unmapped_location, value); 596 __ mov(unmapped_location, value);
641 __ lea(edi, unmapped_location); 597 __ lea(edi, unmapped_location);
642 __ mov(edx, value); 598 __ mov(edx, value);
643 __ RecordWrite(ebx, edi, edx); 599 __ RecordWrite(ebx, edi, edx);
644 __ Ret(); 600 __ Ret();
645 __ bind(&slow); 601 __ bind(&slow);
646 GenerateMiss(masm); 602 GenerateMiss(masm);
647 } 603 }
648 604
649 605
650 static void KeyedStoreGenerateGenericHelper( 606 static void KeyedStoreGenerateGenericHelper(
651 MacroAssembler* masm, 607 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
652 Label* fast_object, 608 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) {
653 Label* fast_double,
654 Label* slow,
655 KeyedStoreCheckMap check_map,
656 KeyedStoreIncrementLength increment_length) {
657 Label transition_smi_elements; 609 Label transition_smi_elements;
658 Label finish_object_store, non_double_value, transition_double_elements; 610 Label finish_object_store, non_double_value, transition_double_elements;
659 Label fast_double_without_map_check; 611 Label fast_double_without_map_check;
660 Register receiver = KeyedStoreIC::ReceiverRegister(); 612 Register receiver = KeyedStoreIC::ReceiverRegister();
661 Register key = KeyedStoreIC::NameRegister(); 613 Register key = KeyedStoreIC::NameRegister();
662 Register value = KeyedStoreIC::ValueRegister(); 614 Register value = KeyedStoreIC::ValueRegister();
663 DCHECK(receiver.is(edx)); 615 DCHECK(receiver.is(edx));
664 DCHECK(key.is(ecx)); 616 DCHECK(key.is(ecx));
665 DCHECK(value.is(eax)); 617 DCHECK(value.is(eax));
666 // key is a smi. 618 // key is a smi.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 // Fast elements array, store the value to the elements backing store. 658 // Fast elements array, store the value to the elements backing store.
707 __ bind(&finish_object_store); 659 __ bind(&finish_object_store);
708 if (increment_length == kIncrementLength) { 660 if (increment_length == kIncrementLength) {
709 // Add 1 to receiver->length. 661 // Add 1 to receiver->length.
710 __ add(FieldOperand(receiver, JSArray::kLengthOffset), 662 __ add(FieldOperand(receiver, JSArray::kLengthOffset),
711 Immediate(Smi::FromInt(1))); 663 Immediate(Smi::FromInt(1)));
712 } 664 }
713 __ mov(FixedArrayElementOperand(ebx, key), value); 665 __ mov(FixedArrayElementOperand(ebx, key), value);
714 // Update write barrier for the elements array address. 666 // Update write barrier for the elements array address.
715 __ mov(edx, value); // Preserve the value which is returned. 667 __ mov(edx, value); // Preserve the value which is returned.
716 __ RecordWriteArray( 668 __ RecordWriteArray(ebx, edx, key, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
717 ebx, edx, key, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
718 __ ret(0); 669 __ ret(0);
719 670
720 __ bind(fast_double); 671 __ bind(fast_double);
721 if (check_map == kCheckMap) { 672 if (check_map == kCheckMap) {
722 // Check for fast double array case. If this fails, call through to the 673 // Check for fast double array case. If this fails, call through to the
723 // runtime. 674 // runtime.
724 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); 675 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
725 __ j(not_equal, slow); 676 __ j(not_equal, slow);
726 // If the value is a number, store it as a double in the FastDoubleElements 677 // If the value is a number, store it as a double in the FastDoubleElements
727 // array. 678 // array.
(...skipping 15 matching lines...) Expand all
743 // Add 1 to receiver->length. 694 // Add 1 to receiver->length.
744 __ add(FieldOperand(receiver, JSArray::kLengthOffset), 695 __ add(FieldOperand(receiver, JSArray::kLengthOffset),
745 Immediate(Smi::FromInt(1))); 696 Immediate(Smi::FromInt(1)));
746 } 697 }
747 __ ret(0); 698 __ ret(0);
748 699
749 __ bind(&transition_smi_elements); 700 __ bind(&transition_smi_elements);
750 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); 701 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset));
751 702
752 // Transition the array appropriately depending on the value type. 703 // Transition the array appropriately depending on the value type.
753 __ CheckMap(value, 704 __ CheckMap(value, masm->isolate()->factory()->heap_number_map(),
754 masm->isolate()->factory()->heap_number_map(), 705 &non_double_value, DONT_DO_SMI_CHECK);
755 &non_double_value,
756 DONT_DO_SMI_CHECK);
757 706
758 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS 707 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS
759 // and complete the store. 708 // and complete the store.
760 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, 709 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
761 FAST_DOUBLE_ELEMENTS, 710 FAST_DOUBLE_ELEMENTS, ebx, edi, slow);
762 ebx, 711 AllocationSiteMode mode =
763 edi, 712 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS);
764 slow); 713 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value,
765 AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, 714 ebx, mode, slow);
766 FAST_DOUBLE_ELEMENTS);
767 ElementsTransitionGenerator::GenerateSmiToDouble(
768 masm, receiver, key, value, ebx, mode, slow);
769 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); 715 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
770 __ jmp(&fast_double_without_map_check); 716 __ jmp(&fast_double_without_map_check);
771 717
772 __ bind(&non_double_value); 718 __ bind(&non_double_value);
773 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS 719 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
774 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, 720 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, ebx,
775 FAST_ELEMENTS, 721 edi, slow);
776 ebx,
777 edi,
778 slow);
779 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); 722 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS);
780 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( 723 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
781 masm, receiver, key, value, ebx, mode, slow); 724 masm, receiver, key, value, ebx, mode, slow);
782 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); 725 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
783 __ jmp(&finish_object_store); 726 __ jmp(&finish_object_store);
784 727
785 __ bind(&transition_double_elements); 728 __ bind(&transition_double_elements);
786 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a 729 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
787 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and 730 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
788 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS 731 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
789 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); 732 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset));
790 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, 733 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS,
791 FAST_ELEMENTS, 734 ebx, edi, slow);
792 ebx,
793 edi,
794 slow);
795 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); 735 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS);
796 ElementsTransitionGenerator::GenerateDoubleToObject( 736 ElementsTransitionGenerator::GenerateDoubleToObject(masm, receiver, key,
797 masm, receiver, key, value, ebx, mode, slow); 737 value, ebx, mode, slow);
798 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); 738 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
799 __ jmp(&finish_object_store); 739 __ jmp(&finish_object_store);
800 } 740 }
801 741
802 742
803 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 743 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
804 StrictMode strict_mode) { 744 StrictMode strict_mode) {
805 // Return address is on the stack. 745 // Return address is on the stack.
806 Label slow, fast_object, fast_object_grow; 746 Label slow, fast_object, fast_object_grow;
807 Label fast_double, fast_double_grow; 747 Label fast_double, fast_double_grow;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 // receiver is a JSArray. 810 // receiver is a JSArray.
871 // key is a smi. 811 // key is a smi.
872 // edi: receiver map 812 // edi: receiver map
873 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); 813 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
874 814
875 // Check the key against the length in the array and fall through to the 815 // Check the key against the length in the array and fall through to the
876 // common store code. 816 // common store code.
877 __ cmp(key, FieldOperand(receiver, JSArray::kLengthOffset)); // Compare smis. 817 __ cmp(key, FieldOperand(receiver, JSArray::kLengthOffset)); // Compare smis.
878 __ j(above_equal, &extra); 818 __ j(above_equal, &extra);
879 819
880 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, 820 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, &slow,
881 &slow, kCheckMap, kDontIncrementLength); 821 kCheckMap, kDontIncrementLength);
882 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, 822 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
883 &slow, kDontCheckMap, kIncrementLength); 823 &slow, kDontCheckMap, kIncrementLength);
884 } 824 }
885 825
886 826
887 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 827 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
888 // The return address is on the stack. 828 // The return address is on the stack.
889 Register receiver = ReceiverRegister(); 829 Register receiver = ReceiverRegister();
890 Register name = NameRegister(); 830 Register name = NameRegister();
891 DCHECK(receiver.is(edx)); 831 DCHECK(receiver.is(edx));
892 DCHECK(name.is(ecx)); 832 DCHECK(name.is(ecx));
893 833
894 // Probe the stub cache. 834 // Probe the stub cache.
895 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 835 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
896 Code::ComputeHandlerFlags(Code::LOAD_IC)); 836 Code::ComputeHandlerFlags(Code::LOAD_IC));
897 masm->isolate()->stub_cache()->GenerateProbe( 837 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, ebx,
898 masm, flags, receiver, name, ebx, eax); 838 eax);
899 839
900 // Cache miss: Jump to runtime. 840 // Cache miss: Jump to runtime.
901 GenerateMiss(masm); 841 GenerateMiss(masm);
902 } 842 }
903 843
904 844
905 void LoadIC::GenerateNormal(MacroAssembler* masm) { 845 void LoadIC::GenerateNormal(MacroAssembler* masm) {
906 Register dictionary = eax; 846 Register dictionary = eax;
907 DCHECK(!dictionary.is(ReceiverRegister())); 847 DCHECK(!dictionary.is(ReceiverRegister()));
908 DCHECK(!dictionary.is(NameRegister())); 848 DCHECK(!dictionary.is(NameRegister()));
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 DCHECK(FLAG_vector_ics); 923 DCHECK(FLAG_vector_ics);
984 return ebx; 924 return ebx;
985 } 925 }
986 926
987 927
988 const Register StoreIC::ReceiverRegister() { return edx; } 928 const Register StoreIC::ReceiverRegister() { return edx; }
989 const Register StoreIC::NameRegister() { return ecx; } 929 const Register StoreIC::NameRegister() { return ecx; }
990 const Register StoreIC::ValueRegister() { return eax; } 930 const Register StoreIC::ValueRegister() { return eax; }
991 931
992 932
993 const Register KeyedStoreIC::MapRegister() { 933 const Register KeyedStoreIC::MapRegister() { return ebx; }
994 return ebx;
995 }
996 934
997 935
998 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 936 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
999 // Return address is on the stack. 937 // Return address is on the stack.
1000 LoadIC_PushArgs(masm); 938 LoadIC_PushArgs(masm);
1001 939
1002 // Perform tail call to the entry. 940 // Perform tail call to the entry.
1003 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 941 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
1004 } 942 }
1005 943
1006 944
1007 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 945 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
1008 // Return address is on the stack. 946 // Return address is on the stack.
1009 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 947 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
1010 Code::ComputeHandlerFlags(Code::STORE_IC)); 948 Code::ComputeHandlerFlags(Code::STORE_IC));
1011 masm->isolate()->stub_cache()->GenerateProbe( 949 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, ReceiverRegister(),
1012 masm, flags, ReceiverRegister(), NameRegister(), 950 NameRegister(), ebx, no_reg);
1013 ebx, no_reg);
1014 951
1015 // Cache miss: Jump to runtime. 952 // Cache miss: Jump to runtime.
1016 GenerateMiss(masm); 953 GenerateMiss(masm);
1017 } 954 }
1018 955
1019 956
1020 static void StoreIC_PushArgs(MacroAssembler* masm) { 957 static void StoreIC_PushArgs(MacroAssembler* masm) {
1021 Register receiver = StoreIC::ReceiverRegister(); 958 Register receiver = StoreIC::ReceiverRegister();
1022 Register name = StoreIC::NameRegister(); 959 Register name = StoreIC::NameRegister();
1023 Register value = StoreIC::ValueRegister(); 960 Register value = StoreIC::ValueRegister();
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1179 if (*test_instruction_address != Assembler::kTestAlByte) { 1116 if (*test_instruction_address != Assembler::kTestAlByte) {
1180 DCHECK(*test_instruction_address == Assembler::kNopByte); 1117 DCHECK(*test_instruction_address == Assembler::kNopByte);
1181 return; 1118 return;
1182 } 1119 }
1183 1120
1184 Address delta_address = test_instruction_address + 1; 1121 Address delta_address = test_instruction_address + 1;
1185 // The delta to the start of the map check instruction and the 1122 // The delta to the start of the map check instruction and the
1186 // condition code uses at the patched jump. 1123 // condition code uses at the patched jump.
1187 uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address); 1124 uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
1188 if (FLAG_trace_ic) { 1125 if (FLAG_trace_ic) {
1189 PrintF("[ patching ic at %p, test=%p, delta=%d\n", 1126 PrintF("[ patching ic at %p, test=%p, delta=%d\n", address,
1190 address, test_instruction_address, delta); 1127 test_instruction_address, delta);
1191 } 1128 }
1192 1129
1193 // Patch with a short conditional jump. Enabling means switching from a short 1130 // Patch with a short conditional jump. Enabling means switching from a short
1194 // jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the 1131 // jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the
1195 // reverse operation of that. 1132 // reverse operation of that.
1196 Address jmp_address = test_instruction_address - delta; 1133 Address jmp_address = test_instruction_address - delta;
1197 DCHECK((check == ENABLE_INLINED_SMI_CHECK) 1134 DCHECK((check == ENABLE_INLINED_SMI_CHECK)
1198 ? (*jmp_address == Assembler::kJncShortOpcode || 1135 ? (*jmp_address == Assembler::kJncShortOpcode ||
1199 *jmp_address == Assembler::kJcShortOpcode) 1136 *jmp_address == Assembler::kJcShortOpcode)
1200 : (*jmp_address == Assembler::kJnzShortOpcode || 1137 : (*jmp_address == Assembler::kJnzShortOpcode ||
1201 *jmp_address == Assembler::kJzShortOpcode)); 1138 *jmp_address == Assembler::kJzShortOpcode));
1202 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) 1139 Condition cc =
1203 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) 1140 (check == ENABLE_INLINED_SMI_CHECK)
1204 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); 1141 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
1142 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
1205 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1143 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1206 } 1144 }
1207 1145 }
1208 1146 } // namespace v8::internal
1209 } } // namespace v8::internal
1210 1147
1211 #endif // V8_TARGET_ARCH_X87 1148 #endif // V8_TARGET_ARCH_X87
OLDNEW
« no previous file with comments | « src/ic/x87/ic-compiler-x87.cc ('k') | src/ic/x87/stub-cache-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698