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

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

Issue 483683005: Move IC code into a subdir and move ic-compilation related code from stub-cache into ic-compiler (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix BUILD.gn Created 6 years, 4 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/ic/ia32/ic-compiler-ia32.cc ('k') | src/ic/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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_IA32 7 #if V8_TARGET_ARCH_IA32
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, kDontSaveFPRegs); 135 __ RecordWrite(elements, r0, r1, kDontSaveFPRegs);
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));
209 if (not_fast_array != NULL) { 185 if (not_fast_array != NULL) {
210 // Check that the object is in fast mode and writable. 186 // Check that the object is in fast mode and writable.
211 __ CheckMap(scratch, 187 __ CheckMap(scratch, masm->isolate()->factory()->fixed_array_map(),
212 masm->isolate()->factory()->fixed_array_map(), 188 not_fast_array, DONT_DO_SMI_CHECK);
213 not_fast_array,
214 DONT_DO_SMI_CHECK);
215 } else { 189 } else {
216 __ AssertFastElements(scratch); 190 __ AssertFastElements(scratch);
217 } 191 }
218 // Check that the key (index) is within bounds. 192 // Check that the key (index) is within bounds.
219 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); 193 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
220 __ j(above_equal, out_of_range); 194 __ j(above_equal, out_of_range);
221 // Fast case: Do the load. 195 // Fast case: Do the load.
222 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 196 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
223 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); 197 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
224 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value())); 198 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value()));
225 // In case the loaded value is the_hole we have to consult GetProperty 199 // In case the loaded value is the_hole we have to consult GetProperty
226 // to ensure the prototype chain is searched. 200 // to ensure the prototype chain is searched.
227 __ j(equal, out_of_range); 201 __ j(equal, out_of_range);
228 if (!result.is(scratch)) { 202 if (!result.is(scratch)) {
229 __ mov(result, scratch); 203 __ mov(result, scratch);
230 } 204 }
231 } 205 }
232 206
233 207
234 // Checks whether a key is an array index string or a unique name. 208 // Checks whether a key is an array index string or a unique name.
235 // Falls through if the key is a unique name. 209 // Falls through if the key is a unique name.
236 static void GenerateKeyNameCheck(MacroAssembler* masm, 210 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
237 Register key, 211 Register map, Register hash,
238 Register map, 212 Label* index_string, Label* not_unique) {
239 Register hash,
240 Label* index_string,
241 Label* not_unique) {
242 // Register use: 213 // Register use:
243 // key - holds the key and is unchanged. Assumed to be non-smi. 214 // key - holds the key and is unchanged. Assumed to be non-smi.
244 // Scratch registers: 215 // Scratch registers:
245 // map - used to hold the map of the key. 216 // map - used to hold the map of the key.
246 // hash - used to hold the hash of the key. 217 // hash - used to hold the hash of the key.
247 Label unique; 218 Label unique;
248 __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map); 219 __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map);
249 __ j(above, not_unique); 220 __ j(above, not_unique);
250 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); 221 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
251 __ j(equal, &unique); 222 __ j(equal, &unique);
252 223
253 // Is the string an array index, with cached numeric value? 224 // Is the string an array index, with cached numeric value?
254 __ mov(hash, FieldOperand(key, Name::kHashFieldOffset)); 225 __ mov(hash, FieldOperand(key, Name::kHashFieldOffset));
255 __ test(hash, Immediate(Name::kContainsCachedArrayIndexMask)); 226 __ test(hash, Immediate(Name::kContainsCachedArrayIndexMask));
256 __ j(zero, index_string); 227 __ j(zero, index_string);
257 228
258 // Is the string internalized? We already know it's a string so a single 229 // Is the string internalized? We already know it's a string so a single
259 // bit test is enough. 230 // bit test is enough.
260 STATIC_ASSERT(kNotInternalizedTag != 0); 231 STATIC_ASSERT(kNotInternalizedTag != 0);
261 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), 232 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset),
262 kIsNotInternalizedMask); 233 kIsNotInternalizedMask);
263 __ j(not_zero, not_unique); 234 __ j(not_zero, not_unique);
264 235
265 __ bind(&unique); 236 __ bind(&unique);
266 } 237 }
267 238
268 239
269 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, 240 static Operand GenerateMappedArgumentsLookup(
270 Register object, 241 MacroAssembler* masm, Register object, Register key, Register scratch1,
271 Register key, 242 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(); 243 Heap* heap = masm->isolate()->heap();
277 Factory* factory = masm->isolate()->factory(); 244 Factory* factory = masm->isolate()->factory();
278 245
279 // Check that the receiver is a JSObject. Because of the elements 246 // Check that the receiver is a JSObject. Because of the elements
280 // map check later, we do not need to check for interceptors or 247 // map check later, we do not need to check for interceptors or
281 // whether it requires access checks. 248 // whether it requires access checks.
282 __ JumpIfSmi(object, slow_case); 249 __ JumpIfSmi(object, slow_case);
283 // Check that the object is some kind of JSObject. 250 // Check that the object is some kind of JSObject.
284 __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1); 251 __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1);
285 __ j(below, slow_case); 252 __ j(below, slow_case);
286 253
287 // Check that the key is a positive smi. 254 // Check that the key is a positive smi.
288 __ test(key, Immediate(0x80000001)); 255 __ test(key, Immediate(0x80000001));
289 __ j(not_zero, slow_case); 256 __ j(not_zero, slow_case);
290 257
291 // Load the elements into scratch1 and check its map. 258 // Load the elements into scratch1 and check its map.
292 Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); 259 Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
293 __ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset)); 260 __ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset));
294 __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK); 261 __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
295 262
296 // Check if element is in the range of mapped arguments. If not, jump 263 // Check if element is in the range of mapped arguments. If not, jump
297 // to the unmapped lookup with the parameter map in scratch1. 264 // to the unmapped lookup with the parameter map in scratch1.
298 __ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset)); 265 __ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset));
299 __ sub(scratch2, Immediate(Smi::FromInt(2))); 266 __ sub(scratch2, Immediate(Smi::FromInt(2)));
300 __ cmp(key, scratch2); 267 __ cmp(key, scratch2);
301 __ j(above_equal, unmapped_case); 268 __ j(above_equal, unmapped_case);
302 269
303 // Load element index and check whether it is the hole. 270 // Load element index and check whether it is the hole.
304 const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize; 271 const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize;
305 __ mov(scratch2, FieldOperand(scratch1, 272 __ mov(scratch2,
306 key, 273 FieldOperand(scratch1, key, times_half_pointer_size, kHeaderSize));
307 times_half_pointer_size,
308 kHeaderSize));
309 __ cmp(scratch2, factory->the_hole_value()); 274 __ cmp(scratch2, factory->the_hole_value());
310 __ j(equal, unmapped_case); 275 __ j(equal, unmapped_case);
311 276
312 // Load value from context and return it. We can reuse scratch1 because 277 // 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 278 // we do not jump to the unmapped lookup (which requires the parameter
314 // map in scratch1). 279 // map in scratch1).
315 const int kContextOffset = FixedArray::kHeaderSize; 280 const int kContextOffset = FixedArray::kHeaderSize;
316 __ mov(scratch1, FieldOperand(scratch1, kContextOffset)); 281 __ mov(scratch1, FieldOperand(scratch1, kContextOffset));
317 return FieldOperand(scratch1, 282 return FieldOperand(scratch1, scratch2, times_half_pointer_size,
318 scratch2,
319 times_half_pointer_size,
320 Context::kHeaderSize); 283 Context::kHeaderSize);
321 } 284 }
322 285
323 286
324 static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, 287 static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
325 Register key, 288 Register key,
326 Register parameter_map, 289 Register parameter_map,
327 Register scratch, 290 Register scratch,
328 Label* slow_case) { 291 Label* slow_case) {
329 // Element is in arguments backing store, which is referenced by the 292 // Element is in arguments backing store, which is referenced by the
330 // second element of the parameter_map. 293 // second element of the parameter_map.
331 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; 294 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
332 Register backing_store = parameter_map; 295 Register backing_store = parameter_map;
333 __ mov(backing_store, FieldOperand(parameter_map, kBackingStoreOffset)); 296 __ mov(backing_store, FieldOperand(parameter_map, kBackingStoreOffset));
334 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); 297 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
335 __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); 298 __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK);
336 __ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset)); 299 __ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset));
337 __ cmp(key, scratch); 300 __ cmp(key, scratch);
338 __ j(greater_equal, slow_case); 301 __ j(greater_equal, slow_case);
339 return FieldOperand(backing_store, 302 return FieldOperand(backing_store, key, times_half_pointer_size,
340 key,
341 times_half_pointer_size,
342 FixedArray::kHeaderSize); 303 FixedArray::kHeaderSize);
343 } 304 }
344 305
345 306
346 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 307 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
347 // The return address is on the stack. 308 // The return address is on the stack.
348 Label slow, check_name, index_smi, index_name, property_array_property; 309 Label slow, check_name, index_smi, index_name, property_array_property;
349 Label probe_dictionary, check_number_dictionary; 310 Label probe_dictionary, check_number_dictionary;
350 311
351 Register receiver = ReceiverRegister(); 312 Register receiver = ReceiverRegister();
352 Register key = NameRegister(); 313 Register key = NameRegister();
353 DCHECK(receiver.is(edx)); 314 DCHECK(receiver.is(edx));
354 DCHECK(key.is(ecx)); 315 DCHECK(key.is(ecx));
355 316
356 // Check that the key is a smi. 317 // Check that the key is a smi.
357 __ JumpIfNotSmi(key, &check_name); 318 __ JumpIfNotSmi(key, &check_name);
358 __ bind(&index_smi); 319 __ bind(&index_smi);
359 // Now the key is known to be a smi. This place is also jumped to from 320 // 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. 321 // where a numeric string is converted to a smi.
361 322
362 GenerateKeyedLoadReceiverCheck( 323 GenerateKeyedLoadReceiverCheck(masm, receiver, eax,
363 masm, receiver, eax, Map::kHasIndexedInterceptor, &slow); 324 Map::kHasIndexedInterceptor, &slow);
364 325
365 // Check the receiver's map to see if it has fast elements. 326 // Check the receiver's map to see if it has fast elements.
366 __ CheckFastElements(eax, &check_number_dictionary); 327 __ CheckFastElements(eax, &check_number_dictionary);
367 328
368 GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow); 329 GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow);
369 Isolate* isolate = masm->isolate(); 330 Isolate* isolate = masm->isolate();
370 Counters* counters = isolate->counters(); 331 Counters* counters = isolate->counters();
371 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); 332 __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
372 __ ret(0); 333 __ ret(0);
373 334
374 __ bind(&check_number_dictionary); 335 __ bind(&check_number_dictionary);
375 __ mov(ebx, key); 336 __ mov(ebx, key);
376 __ SmiUntag(ebx); 337 __ SmiUntag(ebx);
377 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); 338 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset));
378 339
379 // Check whether the elements is a number dictionary. 340 // Check whether the elements is a number dictionary.
380 // ebx: untagged index 341 // ebx: untagged index
381 // eax: elements 342 // eax: elements
382 __ CheckMap(eax, 343 __ CheckMap(eax, isolate->factory()->hash_table_map(), &slow,
383 isolate->factory()->hash_table_map(),
384 &slow,
385 DONT_DO_SMI_CHECK); 344 DONT_DO_SMI_CHECK);
386 Label slow_pop_receiver; 345 Label slow_pop_receiver;
387 // Push receiver on the stack to free up a register for the dictionary 346 // Push receiver on the stack to free up a register for the dictionary
388 // probing. 347 // probing.
389 __ push(receiver); 348 __ push(receiver);
390 __ LoadFromNumberDictionary(&slow_pop_receiver, eax, key, ebx, edx, edi, eax); 349 __ LoadFromNumberDictionary(&slow_pop_receiver, eax, key, ebx, edx, edi, eax);
391 // Pop receiver before returning. 350 // Pop receiver before returning.
392 __ pop(receiver); 351 __ pop(receiver);
393 __ ret(0); 352 __ ret(0);
394 353
395 __ bind(&slow_pop_receiver); 354 __ bind(&slow_pop_receiver);
396 // Pop the receiver from the stack and jump to runtime. 355 // Pop the receiver from the stack and jump to runtime.
397 __ pop(receiver); 356 __ pop(receiver);
398 357
399 __ bind(&slow); 358 __ bind(&slow);
400 // Slow case: jump to runtime. 359 // Slow case: jump to runtime.
401 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); 360 __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
402 GenerateRuntimeGetProperty(masm); 361 GenerateRuntimeGetProperty(masm);
403 362
404 __ bind(&check_name); 363 __ bind(&check_name);
405 GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow); 364 GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
406 365
407 GenerateKeyedLoadReceiverCheck( 366 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, Map::kHasNamedInterceptor,
408 masm, receiver, eax, Map::kHasNamedInterceptor, &slow); 367 &slow);
409 368
410 // If the receiver is a fast-case object, check the keyed lookup 369 // If the receiver is a fast-case object, check the keyed lookup
411 // cache. Otherwise probe the dictionary. 370 // cache. Otherwise probe the dictionary.
412 __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset)); 371 __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset));
413 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 372 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
414 Immediate(isolate->factory()->hash_table_map())); 373 Immediate(isolate->factory()->hash_table_map()));
415 __ j(equal, &probe_dictionary); 374 __ j(equal, &probe_dictionary);
416 375
417 // The receiver's map is still in eax, compute the keyed lookup cache hash 376 // 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. 377 // 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); 444 __ bind(&load_in_object_property);
486 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset)); 445 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset));
487 __ add(eax, edi); 446 __ add(eax, edi);
488 __ mov(eax, FieldOperand(receiver, eax, times_pointer_size, 0)); 447 __ mov(eax, FieldOperand(receiver, eax, times_pointer_size, 0));
489 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); 448 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
490 __ ret(0); 449 __ ret(0);
491 450
492 // Load property array property. 451 // Load property array property.
493 __ bind(&property_array_property); 452 __ bind(&property_array_property);
494 __ mov(eax, FieldOperand(receiver, JSObject::kPropertiesOffset)); 453 __ mov(eax, FieldOperand(receiver, JSObject::kPropertiesOffset));
495 __ mov(eax, FieldOperand(eax, edi, times_pointer_size, 454 __ mov(eax,
496 FixedArray::kHeaderSize)); 455 FieldOperand(eax, edi, times_pointer_size, FixedArray::kHeaderSize));
497 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); 456 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
498 __ ret(0); 457 __ ret(0);
499 458
500 // Do a quick inline probe of the receiver's dictionary, if it 459 // Do a quick inline probe of the receiver's dictionary, if it
501 // exists. 460 // exists.
502 __ bind(&probe_dictionary); 461 __ bind(&probe_dictionary);
503 462
504 __ mov(eax, FieldOperand(receiver, JSObject::kMapOffset)); 463 __ mov(eax, FieldOperand(receiver, JSObject::kMapOffset));
505 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); 464 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
506 GenerateGlobalInstanceTypeCheck(masm, eax, &slow); 465 GenerateGlobalInstanceTypeCheck(masm, eax, &slow);
(...skipping 13 matching lines...) Expand all
520 // Return address is on the stack. 479 // Return address is on the stack.
521 Label miss; 480 Label miss;
522 481
523 Register receiver = ReceiverRegister(); 482 Register receiver = ReceiverRegister();
524 Register index = NameRegister(); 483 Register index = NameRegister();
525 Register scratch = ebx; 484 Register scratch = ebx;
526 DCHECK(!scratch.is(receiver) && !scratch.is(index)); 485 DCHECK(!scratch.is(receiver) && !scratch.is(index));
527 Register result = eax; 486 Register result = eax;
528 DCHECK(!result.is(scratch)); 487 DCHECK(!result.is(scratch));
529 488
530 StringCharAtGenerator char_at_generator(receiver, 489 StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
531 index,
532 scratch,
533 result,
534 &miss, // When not a string. 490 &miss, // When not a string.
535 &miss, // When not a number. 491 &miss, // When not a number.
536 &miss, // When index out of range. 492 &miss, // When index out of range.
537 STRING_INDEX_IS_ARRAY_INDEX); 493 STRING_INDEX_IS_ARRAY_INDEX);
538 char_at_generator.GenerateFast(masm); 494 char_at_generator.GenerateFast(masm);
539 __ ret(0); 495 __ ret(0);
540 496
541 StubRuntimeCallHelper call_helper; 497 StubRuntimeCallHelper call_helper;
542 char_at_generator.GenerateSlow(masm, call_helper); 498 char_at_generator.GenerateSlow(masm, call_helper);
543 499
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 546
591 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { 547 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
592 // The return address is on the stack. 548 // The return address is on the stack.
593 Register receiver = ReceiverRegister(); 549 Register receiver = ReceiverRegister();
594 Register key = NameRegister(); 550 Register key = NameRegister();
595 DCHECK(receiver.is(edx)); 551 DCHECK(receiver.is(edx));
596 DCHECK(key.is(ecx)); 552 DCHECK(key.is(ecx));
597 553
598 Label slow, notin; 554 Label slow, notin;
599 Factory* factory = masm->isolate()->factory(); 555 Factory* factory = masm->isolate()->factory();
600 Operand mapped_location = 556 Operand mapped_location = GenerateMappedArgumentsLookup(
601 GenerateMappedArgumentsLookup( 557 masm, receiver, key, ebx, eax, &notin, &slow);
602 masm, receiver, key, ebx, eax, &notin, &slow);
603 __ mov(eax, mapped_location); 558 __ mov(eax, mapped_location);
604 __ Ret(); 559 __ Ret();
605 __ bind(&notin); 560 __ bind(&notin);
606 // The unmapped lookup expects that the parameter map is in ebx. 561 // The unmapped lookup expects that the parameter map is in ebx.
607 Operand unmapped_location = 562 Operand unmapped_location =
608 GenerateUnmappedArgumentsLookup(masm, key, ebx, eax, &slow); 563 GenerateUnmappedArgumentsLookup(masm, key, ebx, eax, &slow);
609 __ cmp(unmapped_location, factory->the_hole_value()); 564 __ cmp(unmapped_location, factory->the_hole_value());
610 __ j(equal, &slow); 565 __ j(equal, &slow);
611 __ mov(eax, unmapped_location); 566 __ mov(eax, unmapped_location);
612 __ Ret(); 567 __ Ret();
613 __ bind(&slow); 568 __ bind(&slow);
614 GenerateMiss(masm); 569 GenerateMiss(masm);
615 } 570 }
616 571
617 572
618 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { 573 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
619 // Return address is on the stack. 574 // Return address is on the stack.
620 Label slow, notin; 575 Label slow, notin;
621 Register receiver = ReceiverRegister(); 576 Register receiver = ReceiverRegister();
622 Register name = NameRegister(); 577 Register name = NameRegister();
623 Register value = ValueRegister(); 578 Register value = ValueRegister();
624 DCHECK(receiver.is(edx)); 579 DCHECK(receiver.is(edx));
625 DCHECK(name.is(ecx)); 580 DCHECK(name.is(ecx));
626 DCHECK(value.is(eax)); 581 DCHECK(value.is(eax));
627 582
628 Operand mapped_location = 583 Operand mapped_location = GenerateMappedArgumentsLookup(
629 GenerateMappedArgumentsLookup(masm, receiver, name, ebx, edi, &notin, 584 masm, receiver, name, ebx, edi, &notin, &slow);
630 &slow);
631 __ mov(mapped_location, value); 585 __ mov(mapped_location, value);
632 __ lea(ecx, mapped_location); 586 __ lea(ecx, mapped_location);
633 __ mov(edx, value); 587 __ mov(edx, value);
634 __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs); 588 __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs);
635 __ Ret(); 589 __ Ret();
636 __ bind(&notin); 590 __ bind(&notin);
637 // The unmapped lookup expects that the parameter map is in ebx. 591 // The unmapped lookup expects that the parameter map is in ebx.
638 Operand unmapped_location = 592 Operand unmapped_location =
639 GenerateUnmappedArgumentsLookup(masm, name, ebx, edi, &slow); 593 GenerateUnmappedArgumentsLookup(masm, name, ebx, edi, &slow);
640 __ mov(unmapped_location, value); 594 __ mov(unmapped_location, value);
641 __ lea(edi, unmapped_location); 595 __ lea(edi, unmapped_location);
642 __ mov(edx, value); 596 __ mov(edx, value);
643 __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs); 597 __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs);
644 __ Ret(); 598 __ Ret();
645 __ bind(&slow); 599 __ bind(&slow);
646 GenerateMiss(masm); 600 GenerateMiss(masm);
647 } 601 }
648 602
649 603
650 static void KeyedStoreGenerateGenericHelper( 604 static void KeyedStoreGenerateGenericHelper(
651 MacroAssembler* masm, 605 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
652 Label* fast_object, 606 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; 607 Label transition_smi_elements;
658 Label finish_object_store, non_double_value, transition_double_elements; 608 Label finish_object_store, non_double_value, transition_double_elements;
659 Label fast_double_without_map_check; 609 Label fast_double_without_map_check;
660 Register receiver = KeyedStoreIC::ReceiverRegister(); 610 Register receiver = KeyedStoreIC::ReceiverRegister();
661 Register key = KeyedStoreIC::NameRegister(); 611 Register key = KeyedStoreIC::NameRegister();
662 Register value = KeyedStoreIC::ValueRegister(); 612 Register value = KeyedStoreIC::ValueRegister();
663 DCHECK(receiver.is(edx)); 613 DCHECK(receiver.is(edx));
664 DCHECK(key.is(ecx)); 614 DCHECK(key.is(ecx));
665 DCHECK(value.is(eax)); 615 DCHECK(value.is(eax));
666 // key is a smi. 616 // 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. 656 // Fast elements array, store the value to the elements backing store.
707 __ bind(&finish_object_store); 657 __ bind(&finish_object_store);
708 if (increment_length == kIncrementLength) { 658 if (increment_length == kIncrementLength) {
709 // Add 1 to receiver->length. 659 // Add 1 to receiver->length.
710 __ add(FieldOperand(receiver, JSArray::kLengthOffset), 660 __ add(FieldOperand(receiver, JSArray::kLengthOffset),
711 Immediate(Smi::FromInt(1))); 661 Immediate(Smi::FromInt(1)));
712 } 662 }
713 __ mov(FixedArrayElementOperand(ebx, key), value); 663 __ mov(FixedArrayElementOperand(ebx, key), value);
714 // Update write barrier for the elements array address. 664 // Update write barrier for the elements array address.
715 __ mov(edx, value); // Preserve the value which is returned. 665 __ mov(edx, value); // Preserve the value which is returned.
716 __ RecordWriteArray( 666 __ RecordWriteArray(ebx, edx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
717 ebx, edx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 667 OMIT_SMI_CHECK);
718 __ ret(0); 668 __ ret(0);
719 669
720 __ bind(fast_double); 670 __ bind(fast_double);
721 if (check_map == kCheckMap) { 671 if (check_map == kCheckMap) {
722 // Check for fast double array case. If this fails, call through to the 672 // Check for fast double array case. If this fails, call through to the
723 // runtime. 673 // runtime.
724 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); 674 __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map());
725 __ j(not_equal, slow); 675 __ j(not_equal, slow);
726 // If the value is a number, store it as a double in the FastDoubleElements 676 // If the value is a number, store it as a double in the FastDoubleElements
727 // array. 677 // array.
(...skipping 15 matching lines...) Expand all
743 // Add 1 to receiver->length. 693 // Add 1 to receiver->length.
744 __ add(FieldOperand(receiver, JSArray::kLengthOffset), 694 __ add(FieldOperand(receiver, JSArray::kLengthOffset),
745 Immediate(Smi::FromInt(1))); 695 Immediate(Smi::FromInt(1)));
746 } 696 }
747 __ ret(0); 697 __ ret(0);
748 698
749 __ bind(&transition_smi_elements); 699 __ bind(&transition_smi_elements);
750 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); 700 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset));
751 701
752 // Transition the array appropriately depending on the value type. 702 // Transition the array appropriately depending on the value type.
753 __ CheckMap(value, 703 __ CheckMap(value, masm->isolate()->factory()->heap_number_map(),
754 masm->isolate()->factory()->heap_number_map(), 704 &non_double_value, DONT_DO_SMI_CHECK);
755 &non_double_value,
756 DONT_DO_SMI_CHECK);
757 705
758 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS 706 // Value is a double. Transition FAST_SMI_ELEMENTS -> FAST_DOUBLE_ELEMENTS
759 // and complete the store. 707 // and complete the store.
760 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, 708 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
761 FAST_DOUBLE_ELEMENTS, 709 FAST_DOUBLE_ELEMENTS, ebx, edi, slow);
762 ebx, 710 AllocationSiteMode mode =
763 edi, 711 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS);
764 slow); 712 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value,
765 AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, 713 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)); 714 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
770 __ jmp(&fast_double_without_map_check); 715 __ jmp(&fast_double_without_map_check);
771 716
772 __ bind(&non_double_value); 717 __ bind(&non_double_value);
773 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS 718 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
774 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, 719 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, ebx,
775 FAST_ELEMENTS, 720 edi, slow);
776 ebx,
777 edi,
778 slow);
779 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); 721 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS);
780 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( 722 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
781 masm, receiver, key, value, ebx, mode, slow); 723 masm, receiver, key, value, ebx, mode, slow);
782 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); 724 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
783 __ jmp(&finish_object_store); 725 __ jmp(&finish_object_store);
784 726
785 __ bind(&transition_double_elements); 727 __ bind(&transition_double_elements);
786 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a 728 // 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 729 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
788 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS 730 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
789 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); 731 __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset));
790 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, 732 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS,
791 FAST_ELEMENTS, 733 ebx, edi, slow);
792 ebx,
793 edi,
794 slow);
795 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); 734 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS);
796 ElementsTransitionGenerator::GenerateDoubleToObject( 735 ElementsTransitionGenerator::GenerateDoubleToObject(masm, receiver, key,
797 masm, receiver, key, value, ebx, mode, slow); 736 value, ebx, mode, slow);
798 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); 737 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
799 __ jmp(&finish_object_store); 738 __ jmp(&finish_object_store);
800 } 739 }
801 740
802 741
803 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 742 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
804 StrictMode strict_mode) { 743 StrictMode strict_mode) {
805 // Return address is on the stack. 744 // Return address is on the stack.
806 Label slow, fast_object, fast_object_grow; 745 Label slow, fast_object, fast_object_grow;
807 Label fast_double, fast_double_grow; 746 Label fast_double, fast_double_grow;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 // receiver is a JSArray. 809 // receiver is a JSArray.
871 // key is a smi. 810 // key is a smi.
872 // edi: receiver map 811 // edi: receiver map
873 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset)); 812 __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
874 813
875 // Check the key against the length in the array and fall through to the 814 // Check the key against the length in the array and fall through to the
876 // common store code. 815 // common store code.
877 __ cmp(key, FieldOperand(receiver, JSArray::kLengthOffset)); // Compare smis. 816 __ cmp(key, FieldOperand(receiver, JSArray::kLengthOffset)); // Compare smis.
878 __ j(above_equal, &extra); 817 __ j(above_equal, &extra);
879 818
880 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, 819 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, &slow,
881 &slow, kCheckMap, kDontIncrementLength); 820 kCheckMap, kDontIncrementLength);
882 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, 821 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
883 &slow, kDontCheckMap, kIncrementLength); 822 &slow, kDontCheckMap, kIncrementLength);
884 } 823 }
885 824
886 825
887 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 826 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
888 // The return address is on the stack. 827 // The return address is on the stack.
889 Register receiver = ReceiverRegister(); 828 Register receiver = ReceiverRegister();
890 Register name = NameRegister(); 829 Register name = NameRegister();
891 DCHECK(receiver.is(edx)); 830 DCHECK(receiver.is(edx));
892 DCHECK(name.is(ecx)); 831 DCHECK(name.is(ecx));
893 832
894 // Probe the stub cache. 833 // Probe the stub cache.
895 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 834 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
896 Code::ComputeHandlerFlags(Code::LOAD_IC)); 835 Code::ComputeHandlerFlags(Code::LOAD_IC));
897 masm->isolate()->stub_cache()->GenerateProbe( 836 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, ebx,
898 masm, flags, receiver, name, ebx, eax); 837 eax);
899 838
900 // Cache miss: Jump to runtime. 839 // Cache miss: Jump to runtime.
901 GenerateMiss(masm); 840 GenerateMiss(masm);
902 } 841 }
903 842
904 843
905 void LoadIC::GenerateNormal(MacroAssembler* masm) { 844 void LoadIC::GenerateNormal(MacroAssembler* masm) {
906 Register dictionary = eax; 845 Register dictionary = eax;
907 DCHECK(!dictionary.is(ReceiverRegister())); 846 DCHECK(!dictionary.is(ReceiverRegister()));
908 DCHECK(!dictionary.is(NameRegister())); 847 DCHECK(!dictionary.is(NameRegister()));
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 DCHECK(FLAG_vector_ics); 922 DCHECK(FLAG_vector_ics);
984 return ebx; 923 return ebx;
985 } 924 }
986 925
987 926
988 const Register StoreIC::ReceiverRegister() { return edx; } 927 const Register StoreIC::ReceiverRegister() { return edx; }
989 const Register StoreIC::NameRegister() { return ecx; } 928 const Register StoreIC::NameRegister() { return ecx; }
990 const Register StoreIC::ValueRegister() { return eax; } 929 const Register StoreIC::ValueRegister() { return eax; }
991 930
992 931
993 const Register KeyedStoreIC::MapRegister() { 932 const Register KeyedStoreIC::MapRegister() { return ebx; }
994 return ebx;
995 }
996 933
997 934
998 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 935 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
999 // Return address is on the stack. 936 // Return address is on the stack.
1000 LoadIC_PushArgs(masm); 937 LoadIC_PushArgs(masm);
1001 938
1002 // Perform tail call to the entry. 939 // Perform tail call to the entry.
1003 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 940 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
1004 } 941 }
1005 942
1006 943
1007 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 944 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
1008 // Return address is on the stack. 945 // Return address is on the stack.
1009 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 946 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
1010 Code::ComputeHandlerFlags(Code::STORE_IC)); 947 Code::ComputeHandlerFlags(Code::STORE_IC));
1011 masm->isolate()->stub_cache()->GenerateProbe( 948 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, ReceiverRegister(),
1012 masm, flags, ReceiverRegister(), NameRegister(), 949 NameRegister(), ebx, no_reg);
1013 ebx, no_reg);
1014 950
1015 // Cache miss: Jump to runtime. 951 // Cache miss: Jump to runtime.
1016 GenerateMiss(masm); 952 GenerateMiss(masm);
1017 } 953 }
1018 954
1019 955
1020 static void StoreIC_PushArgs(MacroAssembler* masm) { 956 static void StoreIC_PushArgs(MacroAssembler* masm) {
1021 Register receiver = StoreIC::ReceiverRegister(); 957 Register receiver = StoreIC::ReceiverRegister();
1022 Register name = StoreIC::NameRegister(); 958 Register name = StoreIC::NameRegister();
1023 Register value = StoreIC::ValueRegister(); 959 Register value = StoreIC::ValueRegister();
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1179 if (*test_instruction_address != Assembler::kTestAlByte) { 1115 if (*test_instruction_address != Assembler::kTestAlByte) {
1180 DCHECK(*test_instruction_address == Assembler::kNopByte); 1116 DCHECK(*test_instruction_address == Assembler::kNopByte);
1181 return; 1117 return;
1182 } 1118 }
1183 1119
1184 Address delta_address = test_instruction_address + 1; 1120 Address delta_address = test_instruction_address + 1;
1185 // The delta to the start of the map check instruction and the 1121 // The delta to the start of the map check instruction and the
1186 // condition code uses at the patched jump. 1122 // condition code uses at the patched jump.
1187 uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address); 1123 uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
1188 if (FLAG_trace_ic) { 1124 if (FLAG_trace_ic) {
1189 PrintF("[ patching ic at %p, test=%p, delta=%d\n", 1125 PrintF("[ patching ic at %p, test=%p, delta=%d\n", address,
1190 address, test_instruction_address, delta); 1126 test_instruction_address, delta);
1191 } 1127 }
1192 1128
1193 // Patch with a short conditional jump. Enabling means switching from a short 1129 // 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 1130 // jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the
1195 // reverse operation of that. 1131 // reverse operation of that.
1196 Address jmp_address = test_instruction_address - delta; 1132 Address jmp_address = test_instruction_address - delta;
1197 DCHECK((check == ENABLE_INLINED_SMI_CHECK) 1133 DCHECK((check == ENABLE_INLINED_SMI_CHECK)
1198 ? (*jmp_address == Assembler::kJncShortOpcode || 1134 ? (*jmp_address == Assembler::kJncShortOpcode ||
1199 *jmp_address == Assembler::kJcShortOpcode) 1135 *jmp_address == Assembler::kJcShortOpcode)
1200 : (*jmp_address == Assembler::kJnzShortOpcode || 1136 : (*jmp_address == Assembler::kJnzShortOpcode ||
1201 *jmp_address == Assembler::kJzShortOpcode)); 1137 *jmp_address == Assembler::kJzShortOpcode));
1202 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) 1138 Condition cc =
1203 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) 1139 (check == ENABLE_INLINED_SMI_CHECK)
1204 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); 1140 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
1141 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
1205 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1142 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1206 } 1143 }
1207 1144 }
1208 1145 } // namespace v8::internal
1209 } } // namespace v8::internal
1210 1146
1211 #endif // V8_TARGET_ARCH_IA32 1147 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ic/ia32/ic-compiler-ia32.cc ('k') | src/ic/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698