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

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

Issue 660095: Merge revision 3813 to 3930 from bleeding_edge to partial snapshots branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: '' Created 10 years, 10 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/ia32/full-codegen-ia32.cc ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 #define __ ACCESS_MASM(masm) 43 #define __ ACCESS_MASM(masm)
44 44
45 45
46 // Helper function used to load a property from a dictionary backing storage. 46 // Helper function used to load a property from a dictionary backing storage.
47 // This function may return false negatives, so miss_label 47 // This function may return false negatives, so miss_label
48 // must always call a backup property load that is complete. 48 // must always call a backup property load that is complete.
49 // This function is safe to call if the receiver has fast properties, 49 // This function is safe to call if the receiver has fast properties,
50 // or if name is not a symbol, and will jump to the miss_label in that case. 50 // or if name is not a symbol, and will jump to the miss_label in that case.
51 static void GenerateDictionaryLoad(MacroAssembler* masm, 51 static void GenerateDictionaryLoad(MacroAssembler* masm,
52 Label* miss_label, 52 Label* miss_label,
53 Register receiver,
54 Register name,
53 Register r0, 55 Register r0,
54 Register r1, 56 Register r1,
55 Register r2, 57 Register r2,
56 Register name,
57 DictionaryCheck check_dictionary) { 58 DictionaryCheck check_dictionary) {
58 // Register use: 59 // Register use:
59 // 60 //
61 // name - holds the name of the property and is unchanged.
62 // receiver - holds the receiver and is unchanged.
63 // Scratch registers:
60 // r0 - used to hold the property dictionary. 64 // r0 - used to hold the property dictionary.
61 // 65 //
62 // r1 - initially the receiver 66 // r1 - used for the index into the property dictionary
63 // - used for the index into the property dictionary
64 // - holds the result on exit. 67 // - holds the result on exit.
65 // 68 //
66 // r2 - used to hold the capacity of the property dictionary. 69 // r2 - used to hold the capacity of the property dictionary.
67 //
68 // name - holds the name of the property and is unchanged.
69 70
70 Label done; 71 Label done;
71 72
72 // Check for the absence of an interceptor. 73 // Check for the absence of an interceptor.
73 // Load the map into r0. 74 // Load the map into r0.
74 __ mov(r0, FieldOperand(r1, JSObject::kMapOffset)); 75 __ mov(r0, FieldOperand(receiver, JSObject::kMapOffset));
75 // Test the has_named_interceptor bit in the map. 76 // Test the has_named_interceptor bit in the map.
76 __ test(FieldOperand(r0, Map::kInstanceAttributesOffset), 77 __ test(FieldOperand(r0, Map::kInstanceAttributesOffset),
77 Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8)))); 78 Immediate(1 << (Map::kHasNamedInterceptor + (3 * 8))));
78 79
79 // Jump to miss if the interceptor bit is set. 80 // Jump to miss if the interceptor bit is set.
80 __ j(not_zero, miss_label, not_taken); 81 __ j(not_zero, miss_label, not_taken);
81 82
82 // Bail out if we have a JS global proxy object. 83 // Bail out if we have a JS global proxy object.
83 __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset)); 84 __ movzx_b(r0, FieldOperand(r0, Map::kInstanceTypeOffset));
84 __ cmp(r0, JS_GLOBAL_PROXY_TYPE); 85 __ cmp(r0, JS_GLOBAL_PROXY_TYPE);
85 __ j(equal, miss_label, not_taken); 86 __ j(equal, miss_label, not_taken);
86 87
87 // Possible work-around for http://crbug.com/16276. 88 // Possible work-around for http://crbug.com/16276.
88 __ cmp(r0, JS_GLOBAL_OBJECT_TYPE); 89 __ cmp(r0, JS_GLOBAL_OBJECT_TYPE);
89 __ j(equal, miss_label, not_taken); 90 __ j(equal, miss_label, not_taken);
90 __ cmp(r0, JS_BUILTINS_OBJECT_TYPE); 91 __ cmp(r0, JS_BUILTINS_OBJECT_TYPE);
91 __ j(equal, miss_label, not_taken); 92 __ j(equal, miss_label, not_taken);
92 93
93 // Load properties array. 94 // Load properties array.
94 __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); 95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
95 96
96 // Check that the properties array is a dictionary. 97 // Check that the properties array is a dictionary.
97 if (check_dictionary == CHECK_DICTIONARY) { 98 if (check_dictionary == CHECK_DICTIONARY) {
98 __ cmp(FieldOperand(r0, HeapObject::kMapOffset), 99 __ cmp(FieldOperand(r0, HeapObject::kMapOffset),
99 Immediate(Factory::hash_table_map())); 100 Immediate(Factory::hash_table_map()));
100 __ j(not_equal, miss_label); 101 __ j(not_equal, miss_label);
101 } 102 }
102 103
103 // Compute the capacity mask. 104 // Compute the capacity mask.
104 const int kCapacityOffset = 105 const int kCapacityOffset =
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 153
153 154
154 // The offset from the inlined patch site to the start of the 155 // The offset from the inlined patch site to the start of the
155 // inlined load instruction. It is 7 bytes (test eax, imm) plus 156 // inlined load instruction. It is 7 bytes (test eax, imm) plus
156 // 6 bytes (jne slow_label). 157 // 6 bytes (jne slow_label).
157 const int LoadIC::kOffsetToLoadInstruction = 13; 158 const int LoadIC::kOffsetToLoadInstruction = 13;
158 159
159 160
160 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { 161 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
161 // ----------- S t a t e ------------- 162 // ----------- S t a t e -------------
163 // -- eax : receiver
162 // -- ecx : name 164 // -- ecx : name
163 // -- esp[0] : return address 165 // -- esp[0] : return address
164 // -- esp[4] : receiver
165 // ----------------------------------- 166 // -----------------------------------
166 Label miss; 167 Label miss;
167 168
168 __ mov(eax, Operand(esp, kPointerSize));
169
170 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); 169 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
171 __ bind(&miss); 170 __ bind(&miss);
172 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 171 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
173 } 172 }
174 173
175 174
176 void LoadIC::GenerateStringLength(MacroAssembler* masm) { 175 void LoadIC::GenerateStringLength(MacroAssembler* masm) {
177 // ----------- S t a t e ------------- 176 // ----------- S t a t e -------------
177 // -- eax : receiver
178 // -- ecx : name 178 // -- ecx : name
179 // -- esp[0] : return address 179 // -- esp[0] : return address
180 // -- esp[4] : receiver
181 // ----------------------------------- 180 // -----------------------------------
182 Label miss; 181 Label miss;
183 182
184 __ mov(eax, Operand(esp, kPointerSize)); 183 StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss);
185
186 StubCompiler::GenerateLoadStringLength(masm, eax, edx, &miss);
187 __ bind(&miss); 184 __ bind(&miss);
188 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 185 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
189 } 186 }
190 187
191 188
192 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { 189 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
193 // ----------- S t a t e ------------- 190 // ----------- S t a t e -------------
191 // -- eax : receiver
194 // -- ecx : name 192 // -- ecx : name
195 // -- esp[0] : return address 193 // -- esp[0] : return address
196 // -- esp[4] : receiver
197 // ----------------------------------- 194 // -----------------------------------
198 Label miss; 195 Label miss;
199 196
200 __ mov(eax, Operand(esp, kPointerSize));
201
202 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); 197 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
203 __ bind(&miss); 198 __ bind(&miss);
204 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 199 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
205 } 200 }
206 201
207 202
208 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 203 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
209 // ----------- S t a t e ------------- 204 // ----------- S t a t e -------------
205 // -- eax : key
206 // -- edx : receiver
210 // -- esp[0] : return address 207 // -- esp[0] : return address
211 // -- esp[4] : name
212 // -- esp[8] : receiver
213 // ----------------------------------- 208 // -----------------------------------
214 Label slow, check_string, index_int, index_string; 209 Label slow, check_string, index_int, index_string;
215 Label check_pixel_array, probe_dictionary; 210 Label check_pixel_array, probe_dictionary;
216 211
217 // Load name and receiver.
218 __ mov(eax, Operand(esp, kPointerSize));
219 __ mov(ecx, Operand(esp, 2 * kPointerSize));
220
221 // Check that the object isn't a smi. 212 // Check that the object isn't a smi.
222 __ test(ecx, Immediate(kSmiTagMask)); 213 __ test(edx, Immediate(kSmiTagMask));
223 __ j(zero, &slow, not_taken); 214 __ j(zero, &slow, not_taken);
224 215
225 // Get the map of the receiver. 216 // Get the map of the receiver.
226 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 217 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
227 218
228 // Check bit field. 219 // Check bit field.
229 __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset)); 220 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset));
230 __ test(ebx, Immediate(kSlowCaseBitFieldMask)); 221 __ test(ebx, Immediate(kSlowCaseBitFieldMask));
231 __ j(not_zero, &slow, not_taken); 222 __ j(not_zero, &slow, not_taken);
232 // Check that the object is some kind of JS object EXCEPT JS Value type. 223 // Check that the object is some kind of JS object EXCEPT JS Value type.
233 // In the case that the object is a value-wrapper object, 224 // In the case that the object is a value-wrapper object,
234 // we enter the runtime system to make sure that indexing 225 // we enter the runtime system to make sure that indexing
235 // into string objects work as intended. 226 // into string objects work as intended.
236 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 227 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
237 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); 228 __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
238 __ cmp(edx, JS_OBJECT_TYPE); 229 __ j(below, &slow, not_taken);
239 __ j(less, &slow, not_taken);
240 // Check that the key is a smi. 230 // Check that the key is a smi.
241 __ test(eax, Immediate(kSmiTagMask)); 231 __ test(eax, Immediate(kSmiTagMask));
242 __ j(not_zero, &check_string, not_taken); 232 __ j(not_zero, &check_string, not_taken);
243 __ sar(eax, kSmiTagSize); 233 __ mov(ebx, eax);
234 __ SmiUntag(ebx);
244 // Get the elements array of the object. 235 // Get the elements array of the object.
245 __ bind(&index_int); 236 __ bind(&index_int);
246 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); 237 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
247 // Check that the object is in fast mode (not dictionary). 238 // Check that the object is in fast mode (not dictionary).
248 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 239 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true);
249 Immediate(Factory::fixed_array_map()));
250 __ j(not_equal, &check_pixel_array);
251 // Check that the key (index) is within bounds. 240 // Check that the key (index) is within bounds.
252 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); 241 __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
253 __ j(above_equal, &slow); 242 __ j(above_equal, &slow);
254 // Fast case: Do the load. 243 // Fast case: Do the load.
255 __ mov(eax, 244 __ mov(ecx, FieldOperand(ecx, ebx, times_4, FixedArray::kHeaderSize));
256 Operand(ecx, eax, times_4, FixedArray::kHeaderSize - kHeapObjectTag)); 245 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value()));
257 __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
258 // In case the loaded value is the_hole we have to consult GetProperty 246 // In case the loaded value is the_hole we have to consult GetProperty
259 // to ensure the prototype chain is searched. 247 // to ensure the prototype chain is searched.
260 __ j(equal, &slow); 248 __ j(equal, &slow);
249 __ mov(eax, ecx);
261 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 250 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
262 __ ret(0); 251 __ ret(0);
263 252
253 __ bind(&check_pixel_array);
264 // Check whether the elements is a pixel array. 254 // Check whether the elements is a pixel array.
265 // eax: untagged index 255 // edx: receiver
266 // ecx: elements array 256 // ebx: untagged index
267 __ bind(&check_pixel_array); 257 // eax: key
268 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 258 // ecx: elements
269 Immediate(Factory::pixel_array_map())); 259 __ CheckMap(ecx, Factory::pixel_array_map(), &slow, true);
270 __ j(not_equal, &slow); 260 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset));
271 __ cmp(eax, FieldOperand(ecx, PixelArray::kLengthOffset));
272 __ j(above_equal, &slow); 261 __ j(above_equal, &slow);
273 __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); 262 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset));
274 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); 263 __ movzx_b(eax, Operand(eax, ebx, times_1, 0));
275 __ shl(eax, kSmiTagSize); 264 __ SmiTag(eax);
276 __ ret(0); 265 __ ret(0);
277 266
278 // Slow case: Load name and receiver from stack and jump to runtime.
279 __ bind(&slow); 267 __ bind(&slow);
268 // Slow case: jump to runtime.
269 // edx: receiver
270 // eax: key
280 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 271 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
281 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); 272 GenerateRuntimeGetProperty(masm);
282 273
283 __ bind(&check_string); 274 __ bind(&check_string);
284 // The key is not a smi. 275 // The key is not a smi.
285 // Is it a string? 276 // Is it a string?
286 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); 277 // edx: receiver
278 // eax: key
279 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx);
287 __ j(above_equal, &slow); 280 __ j(above_equal, &slow);
288 // Is the string an array index, with cached numeric value? 281 // Is the string an array index, with cached numeric value?
289 __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset)); 282 __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset));
290 __ test(ebx, Immediate(String::kIsArrayIndexMask)); 283 __ test(ebx, Immediate(String::kIsArrayIndexMask));
291 __ j(not_zero, &index_string, not_taken); 284 __ j(not_zero, &index_string, not_taken);
292 285
293 // Is the string a symbol? 286 // Is the string a symbol?
294 __ movzx_b(ebx, FieldOperand(edx, Map::kInstanceTypeOffset)); 287 __ movzx_b(ebx, FieldOperand(ecx, Map::kInstanceTypeOffset));
295 ASSERT(kSymbolTag != 0); 288 ASSERT(kSymbolTag != 0);
296 __ test(ebx, Immediate(kIsSymbolMask)); 289 __ test(ebx, Immediate(kIsSymbolMask));
297 __ j(zero, &slow, not_taken); 290 __ j(zero, &slow, not_taken);
298 291
299 // If the receiver is a fast-case object, check the keyed lookup 292 // If the receiver is a fast-case object, check the keyed lookup
300 // cache. Otherwise probe the dictionary leaving result in ecx. 293 // cache. Otherwise probe the dictionary.
301 __ mov(ebx, FieldOperand(ecx, JSObject::kPropertiesOffset)); 294 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
302 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 295 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
303 Immediate(Factory::hash_table_map())); 296 Immediate(Factory::hash_table_map()));
304 __ j(equal, &probe_dictionary); 297 __ j(equal, &probe_dictionary);
305 298
306 // Load the map of the receiver, compute the keyed lookup cache hash 299 // Load the map of the receiver, compute the keyed lookup cache hash
307 // based on 32 bits of the map pointer and the string hash. 300 // based on 32 bits of the map pointer and the string hash.
308 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); 301 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
309 __ mov(edx, ebx); 302 __ mov(ecx, ebx);
310 __ shr(edx, KeyedLookupCache::kMapHashShift); 303 __ shr(ecx, KeyedLookupCache::kMapHashShift);
311 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); 304 __ mov(edi, FieldOperand(eax, String::kHashFieldOffset));
312 __ shr(eax, String::kHashShift); 305 __ shr(edi, String::kHashShift);
313 __ xor_(edx, Operand(eax)); 306 __ xor_(ecx, Operand(edi));
314 __ and_(edx, KeyedLookupCache::kCapacityMask); 307 __ and_(ecx, KeyedLookupCache::kCapacityMask);
315 308
316 // Load the key (consisting of map and symbol) from the cache and 309 // Load the key (consisting of map and symbol) from the cache and
317 // check for match. 310 // check for match.
318 ExternalReference cache_keys 311 ExternalReference cache_keys
319 = ExternalReference::keyed_lookup_cache_keys(); 312 = ExternalReference::keyed_lookup_cache_keys();
320 __ mov(edi, edx); 313 __ mov(edi, ecx);
321 __ shl(edi, kPointerSizeLog2 + 1); 314 __ shl(edi, kPointerSizeLog2 + 1);
322 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); 315 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
323 __ j(not_equal, &slow); 316 __ j(not_equal, &slow);
324 __ add(Operand(edi), Immediate(kPointerSize)); 317 __ add(Operand(edi), Immediate(kPointerSize));
325 __ mov(edi, Operand::StaticArray(edi, times_1, cache_keys)); 318 __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
326 __ cmp(edi, Operand(esp, kPointerSize));
327 __ j(not_equal, &slow); 319 __ j(not_equal, &slow);
328 320
329 // Get field offset and check that it is an in-object property. 321 // Get field offset and check that it is an in-object property.
322 // edx : receiver
323 // ebx : receiver's map
324 // eax : key
325 // ecx : lookup cache index
330 ExternalReference cache_field_offsets 326 ExternalReference cache_field_offsets
331 = ExternalReference::keyed_lookup_cache_field_offsets(); 327 = ExternalReference::keyed_lookup_cache_field_offsets();
332 __ mov(eax, 328 __ mov(edi,
333 Operand::StaticArray(edx, times_pointer_size, cache_field_offsets)); 329 Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
334 __ movzx_b(edx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); 330 __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
335 __ cmp(eax, Operand(edx)); 331 __ cmp(edi, Operand(ecx));
336 __ j(above_equal, &slow); 332 __ j(above_equal, &slow);
337 333
338 // Load in-object property. 334 // Load in-object property.
339 __ sub(eax, Operand(edx)); 335 __ sub(edi, Operand(ecx));
340 __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 336 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
341 __ add(eax, Operand(edx)); 337 __ add(ecx, Operand(edi));
342 __ mov(eax, FieldOperand(ecx, eax, times_pointer_size, 0)); 338 __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));
343 __ ret(0); 339 __ ret(0);
344 340
345 // Do a quick inline probe of the receiver's dictionary, if it 341 // Do a quick inline probe of the receiver's dictionary, if it
346 // exists. 342 // exists.
347 __ bind(&probe_dictionary); 343 __ bind(&probe_dictionary);
348 GenerateDictionaryLoad(masm, 344 GenerateDictionaryLoad(masm,
349 &slow, 345 &slow,
346 edx,
347 eax,
350 ebx, 348 ebx,
351 ecx, 349 ecx,
352 edx, 350 edi,
353 eax,
354 DICTIONARY_CHECK_DONE); 351 DICTIONARY_CHECK_DONE);
355 __ mov(eax, Operand(ecx)); 352 __ mov(eax, Operand(ecx));
356 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 353 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
357 __ ret(0); 354 __ ret(0);
358 355
359 // If the hash field contains an array index pick it out. The assert checks 356 // If the hash field contains an array index pick it out. The assert checks
360 // that the constants for the maximum number of digits for an array index 357 // that the constants for the maximum number of digits for an array index
361 // cached in the hash field and the number of bits reserved for it does not 358 // cached in the hash field and the number of bits reserved for it does not
362 // conflict. 359 // conflict.
363 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 360 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
364 (1 << String::kArrayIndexValueBits)); 361 (1 << String::kArrayIndexValueBits));
365 __ bind(&index_string); 362 __ bind(&index_string);
366 __ mov(eax, Operand(ebx)); 363 __ and_(ebx, String::kArrayIndexHashMask);
367 __ and_(eax, String::kArrayIndexHashMask); 364 __ shr(ebx, String::kHashShift);
368 __ shr(eax, String::kHashShift);
369 __ jmp(&index_int); 365 __ jmp(&index_int);
370 } 366 }
371 367
372 368
373 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 369 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
374 // ----------- S t a t e ------------- 370 // ----------- S t a t e -------------
371 // -- eax : key
372 // -- edx : receiver
375 // -- esp[0] : return address 373 // -- esp[0] : return address
376 // -- esp[4] : key
377 // -- esp[8] : receiver
378 // ----------------------------------- 374 // -----------------------------------
379 Label miss, index_ok; 375 Label miss, index_ok;
380 376
381 // Pop return address. 377 // Pop return address.
382 // Performing the load early is better in the common case. 378 // Performing the load early is better in the common case.
383 __ pop(eax); 379 __ pop(ebx);
384 380
385 __ mov(ebx, Operand(esp, 1 * kPointerSize)); 381 __ test(edx, Immediate(kSmiTagMask));
386 __ test(ebx, Immediate(kSmiTagMask));
387 __ j(zero, &miss); 382 __ j(zero, &miss);
388 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); 383 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
389 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 384 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
390 __ test(ecx, Immediate(kIsNotStringMask)); 385 __ test(ecx, Immediate(kIsNotStringMask));
391 __ j(not_zero, &miss); 386 __ j(not_zero, &miss);
392 387
393 // Check if key is a smi or a heap number. 388 // Check if key is a smi or a heap number.
394 __ mov(edx, Operand(esp, 0)); 389 __ test(eax, Immediate(kSmiTagMask));
395 __ test(edx, Immediate(kSmiTagMask));
396 __ j(zero, &index_ok); 390 __ j(zero, &index_ok);
397 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); 391 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
398 __ cmp(ecx, Factory::heap_number_map()); 392 __ cmp(ecx, Factory::heap_number_map());
399 __ j(not_equal, &miss); 393 __ j(not_equal, &miss);
400 394
401 __ bind(&index_ok); 395 __ bind(&index_ok);
402 // Duplicate receiver and key since they are expected on the stack after 396 // Push receiver and key on the stack, and make a tail call.
403 // the KeyedLoadIC call. 397 __ push(edx); // receiver
404 __ push(ebx); // receiver 398 __ push(eax); // key
405 __ push(edx); // key 399 __ push(ebx); // return address
406 __ push(eax); // return address
407 __ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION); 400 __ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION);
408 401
409 __ bind(&miss); 402 __ bind(&miss);
410 __ push(eax); 403 __ push(ebx);
411 GenerateMiss(masm); 404 GenerateMiss(masm);
412 } 405 }
413 406
414 407
415 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, 408 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
416 ExternalArrayType array_type) { 409 ExternalArrayType array_type) {
417 // ----------- S t a t e ------------- 410 // ----------- S t a t e -------------
411 // -- eax : key
412 // -- edx : receiver
418 // -- esp[0] : return address 413 // -- esp[0] : return address
419 // -- esp[4] : key
420 // -- esp[8] : receiver
421 // ----------------------------------- 414 // -----------------------------------
422 Label slow, failed_allocation; 415 Label slow, failed_allocation;
423 416
424 // Load name and receiver.
425 __ mov(eax, Operand(esp, kPointerSize));
426 __ mov(ecx, Operand(esp, 2 * kPointerSize));
427
428 // Check that the object isn't a smi. 417 // Check that the object isn't a smi.
429 __ test(ecx, Immediate(kSmiTagMask)); 418 __ test(edx, Immediate(kSmiTagMask));
430 __ j(zero, &slow, not_taken); 419 __ j(zero, &slow, not_taken);
431 420
432 // Check that the key is a smi. 421 // Check that the key is a smi.
433 __ test(eax, Immediate(kSmiTagMask)); 422 __ test(eax, Immediate(kSmiTagMask));
434 __ j(not_zero, &slow, not_taken); 423 __ j(not_zero, &slow, not_taken);
435 424
436 // Get the map of the receiver. 425 // Get the map of the receiver.
437 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 426 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
438 // Check that the receiver does not require access checks. We need 427 // Check that the receiver does not require access checks. We need
439 // to check this explicitly since this generic stub does not perform 428 // to check this explicitly since this generic stub does not perform
440 // map checks. 429 // map checks.
441 __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset)); 430 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset));
442 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 431 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
443 __ j(not_zero, &slow, not_taken); 432 __ j(not_zero, &slow, not_taken);
444 433
445 // Get the instance type from the map of the receiver. 434 __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
446 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
447 // Check that the object is a JS object.
448 __ cmp(edx, JS_OBJECT_TYPE);
449 __ j(not_equal, &slow, not_taken); 435 __ j(not_equal, &slow, not_taken);
450 436
451 // Check that the elements array is the appropriate type of 437 // Check that the elements array is the appropriate type of
452 // ExternalArray. 438 // ExternalArray.
453 // eax: index (as a smi) 439 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
454 // ecx: JSObject
455 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
456 Handle<Map> map(Heap::MapForExternalArrayType(array_type)); 440 Handle<Map> map(Heap::MapForExternalArrayType(array_type));
457 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 441 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
458 Immediate(map)); 442 Immediate(map));
459 __ j(not_equal, &slow, not_taken); 443 __ j(not_equal, &slow, not_taken);
460 444
445 // eax: key, known to be a smi.
446 // edx: receiver, known to be a JSObject.
447 // ebx: elements object, known to be an external array.
461 // Check that the index is in range. 448 // Check that the index is in range.
462 __ sar(eax, kSmiTagSize); // Untag the index. 449 __ mov(ecx, eax);
463 __ cmp(eax, FieldOperand(ecx, ExternalArray::kLengthOffset)); 450 __ SmiUntag(ecx); // Untag the index.
451 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
464 // Unsigned comparison catches both negative and too-large values. 452 // Unsigned comparison catches both negative and too-large values.
465 __ j(above_equal, &slow); 453 __ j(above_equal, &slow);
466 454
467 // eax: untagged index 455 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
468 // ecx: elements array 456 // ebx: base pointer of external storage
469 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset));
470 // ecx: base pointer of external storage
471 switch (array_type) { 457 switch (array_type) {
472 case kExternalByteArray: 458 case kExternalByteArray:
473 __ movsx_b(eax, Operand(ecx, eax, times_1, 0)); 459 __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0));
474 break; 460 break;
475 case kExternalUnsignedByteArray: 461 case kExternalUnsignedByteArray:
476 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); 462 __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0));
477 break; 463 break;
478 case kExternalShortArray: 464 case kExternalShortArray:
479 __ movsx_w(eax, Operand(ecx, eax, times_2, 0)); 465 __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0));
480 break; 466 break;
481 case kExternalUnsignedShortArray: 467 case kExternalUnsignedShortArray:
482 __ movzx_w(eax, Operand(ecx, eax, times_2, 0)); 468 __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0));
483 break; 469 break;
484 case kExternalIntArray: 470 case kExternalIntArray:
485 case kExternalUnsignedIntArray: 471 case kExternalUnsignedIntArray:
486 __ mov(eax, Operand(ecx, eax, times_4, 0)); 472 __ mov(ecx, Operand(ebx, ecx, times_4, 0));
487 break; 473 break;
488 case kExternalFloatArray: 474 case kExternalFloatArray:
489 __ fld_s(Operand(ecx, eax, times_4, 0)); 475 __ fld_s(Operand(ebx, ecx, times_4, 0));
490 break; 476 break;
491 default: 477 default:
492 UNREACHABLE(); 478 UNREACHABLE();
493 break; 479 break;
494 } 480 }
495 481
496 // For integer array types: 482 // For integer array types:
497 // eax: value 483 // ecx: value
498 // For floating-point array type: 484 // For floating-point array type:
499 // FP(0): value 485 // FP(0): value
500 486
501 if (array_type == kExternalIntArray || 487 if (array_type == kExternalIntArray ||
502 array_type == kExternalUnsignedIntArray) { 488 array_type == kExternalUnsignedIntArray) {
503 // For the Int and UnsignedInt array types, we need to see whether 489 // For the Int and UnsignedInt array types, we need to see whether
504 // the value can be represented in a Smi. If not, we need to convert 490 // the value can be represented in a Smi. If not, we need to convert
505 // it to a HeapNumber. 491 // it to a HeapNumber.
506 Label box_int; 492 Label box_int;
507 if (array_type == kExternalIntArray) { 493 if (array_type == kExternalIntArray) {
508 // See Smi::IsValid for why this works. 494 __ cmp(ecx, 0xC0000000);
509 __ mov(ebx, eax); 495 __ j(sign, &box_int);
510 __ add(Operand(ebx), Immediate(0x40000000));
511 __ cmp(ebx, 0x80000000);
512 __ j(above_equal, &box_int);
513 } else { 496 } else {
514 ASSERT_EQ(array_type, kExternalUnsignedIntArray); 497 ASSERT_EQ(array_type, kExternalUnsignedIntArray);
515 // The test is different for unsigned int values. Since we need 498 // The test is different for unsigned int values. Since we need
516 // the Smi-encoded result to be treated as unsigned, we can't 499 // the value to be in the range of a positive smi, we can't
517 // handle either of the top two bits being set in the value. 500 // handle either of the top two bits being set in the value.
518 __ test(eax, Immediate(0xC0000000)); 501 __ test(ecx, Immediate(0xC0000000));
519 __ j(not_zero, &box_int); 502 __ j(not_zero, &box_int);
520 } 503 }
521 504
522 __ shl(eax, kSmiTagSize); 505 __ mov(eax, ecx);
506 __ SmiTag(eax);
523 __ ret(0); 507 __ ret(0);
524 508
525 __ bind(&box_int); 509 __ bind(&box_int);
526 510
527 // Allocate a HeapNumber for the int and perform int-to-double 511 // Allocate a HeapNumber for the int and perform int-to-double
528 // conversion. 512 // conversion.
529 if (array_type == kExternalIntArray) { 513 if (array_type == kExternalIntArray) {
530 __ push(eax); 514 __ push(ecx);
531 __ fild_s(Operand(esp, 0)); 515 __ fild_s(Operand(esp, 0));
532 __ pop(eax); 516 __ pop(ecx);
533 } else { 517 } else {
534 ASSERT(array_type == kExternalUnsignedIntArray); 518 ASSERT(array_type == kExternalUnsignedIntArray);
535 // Need to zero-extend the value. 519 // Need to zero-extend the value.
536 // There's no fild variant for unsigned values, so zero-extend 520 // There's no fild variant for unsigned values, so zero-extend
537 // to a 64-bit int manually. 521 // to a 64-bit int manually.
538 __ push(Immediate(0)); 522 __ push(Immediate(0));
539 __ push(eax); 523 __ push(ecx);
540 __ fild_d(Operand(esp, 0)); 524 __ fild_d(Operand(esp, 0));
541 __ pop(eax); 525 __ pop(ecx);
542 __ pop(eax); 526 __ pop(ecx);
543 } 527 }
544 // FP(0): value 528 // FP(0): value
545 __ AllocateHeapNumber(eax, ebx, ecx, &failed_allocation); 529 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
546 // Set the value. 530 // Set the value.
531 __ mov(eax, ecx);
547 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 532 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
548 __ ret(0); 533 __ ret(0);
549 } else if (array_type == kExternalFloatArray) { 534 } else if (array_type == kExternalFloatArray) {
550 // For the floating-point array type, we need to always allocate a 535 // For the floating-point array type, we need to always allocate a
551 // HeapNumber. 536 // HeapNumber.
552 __ AllocateHeapNumber(eax, ebx, ecx, &failed_allocation); 537 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
553 // Set the value. 538 // Set the value.
539 __ mov(eax, ecx);
554 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 540 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
555 __ ret(0); 541 __ ret(0);
556 } else { 542 } else {
557 __ shl(eax, kSmiTagSize); 543 __ mov(eax, ecx);
544 __ SmiTag(eax);
558 __ ret(0); 545 __ ret(0);
559 } 546 }
560 547
561 // If we fail allocation of the HeapNumber, we still have a value on 548 // If we fail allocation of the HeapNumber, we still have a value on
562 // top of the FPU stack. Remove it. 549 // top of the FPU stack. Remove it.
563 __ bind(&failed_allocation); 550 __ bind(&failed_allocation);
564 __ ffree(); 551 __ ffree();
565 __ fincstp(); 552 __ fincstp();
566 // Fall through to slow case. 553 // Fall through to slow case.
567 554
568 // Slow case: Load name and receiver from stack and jump to runtime. 555 // Slow case: Load key and receiver from stack and jump to runtime.
569 __ bind(&slow); 556 __ bind(&slow);
570 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); 557 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
571 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); 558 GenerateRuntimeGetProperty(masm);
559 }
560
561
562 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
563 // ----------- S t a t e -------------
564 // -- eax : key
565 // -- edx : receiver
566 // -- esp[0] : return address
567 // -----------------------------------
568 Label slow;
569
570 // Check that the receiver isn't a smi.
571 __ test(edx, Immediate(kSmiTagMask));
572 __ j(zero, &slow, not_taken);
573
574 // Check that the key is a smi.
575 __ test(eax, Immediate(kSmiTagMask));
576 __ j(not_zero, &slow, not_taken);
577
578 // Get the map of the receiver.
579 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
580
581 // Check that it has indexed interceptor and access checks
582 // are not enabled for this object.
583 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
584 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask));
585 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor));
586 __ j(not_zero, &slow, not_taken);
587
588 // Everything is fine, call runtime.
589 __ pop(ecx);
590 __ push(edx); // receiver
591 __ push(eax); // key
592 __ push(ecx); // return address
593
594 // Perform tail call to the entry.
595 __ TailCallRuntime(ExternalReference(
596 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1);
597
598 __ bind(&slow);
599 GenerateMiss(masm);
572 } 600 }
573 601
574 602
575 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { 603 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
576 // ----------- S t a t e ------------- 604 // ----------- S t a t e -------------
577 // -- eax : value 605 // -- eax : value
578 // -- esp[0] : return address 606 // -- esp[0] : return address
579 // -- esp[4] : key 607 // -- esp[4] : key
580 // -- esp[8] : receiver 608 // -- esp[8] : receiver
581 // ----------------------------------- 609 // -----------------------------------
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 __ mov(edx, Operand(ebx)); 648 __ mov(edx, Operand(ebx));
621 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison 649 __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison
622 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); 650 __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset));
623 // eax: value 651 // eax: value
624 // ecx: FixedArray 652 // ecx: FixedArray
625 // ebx: index (as a smi) 653 // ebx: index (as a smi)
626 __ j(below, &fast, taken); 654 __ j(below, &fast, taken);
627 655
628 // Slow case: call runtime. 656 // Slow case: call runtime.
629 __ bind(&slow); 657 __ bind(&slow);
630 Generate(masm, ExternalReference(Runtime::kSetProperty)); 658 GenerateRuntimeSetProperty(masm);
631 659
632 // Check whether the elements is a pixel array. 660 // Check whether the elements is a pixel array.
633 // eax: value 661 // eax: value
634 // ecx: elements array 662 // ecx: elements array
635 // ebx: index (as a smi) 663 // ebx: index (as a smi)
636 __ bind(&check_pixel_array); 664 __ bind(&check_pixel_array);
637 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 665 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
638 Immediate(Factory::pixel_array_map())); 666 Immediate(Factory::pixel_array_map()));
639 __ j(not_equal, &slow); 667 __ j(not_equal, &slow);
640 // Check that the value is a smi. If a conversion is needed call into the 668 // Check that the value is a smi. If a conversion is needed call into the
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 default: 921 default:
894 UNREACHABLE(); 922 UNREACHABLE();
895 break; 923 break;
896 } 924 }
897 __ mov(eax, edx); // Return the original value. 925 __ mov(eax, edx); // Return the original value.
898 __ ret(0); 926 __ ret(0);
899 } 927 }
900 928
901 // Slow case: call runtime. 929 // Slow case: call runtime.
902 __ bind(&slow); 930 __ bind(&slow);
903 Generate(masm, ExternalReference(Runtime::kSetProperty)); 931 GenerateRuntimeSetProperty(masm);
904 } 932 }
905 933
906 934
907 // Defined in ic.cc. 935 // Defined in ic.cc.
908 Object* CallIC_Miss(Arguments args); 936 Object* CallIC_Miss(Arguments args);
909 937
910 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 938 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
911 // ----------- S t a t e ------------- 939 // ----------- S t a t e -------------
912 // -- ecx : name 940 // -- ecx : name
913 // -- esp[0] : return address 941 // -- esp[0] : return address
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 // -- ecx : name 1004 // -- ecx : name
977 // -- edx : receiver 1005 // -- edx : receiver
978 // -- esp[0] : return address 1006 // -- esp[0] : return address
979 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1007 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
980 // -- ... 1008 // -- ...
981 // -- esp[(argc + 1) * 4] : receiver 1009 // -- esp[(argc + 1) * 4] : receiver
982 // ----------------------------------- 1010 // -----------------------------------
983 1011
984 // Search dictionary - put result in register edi. 1012 // Search dictionary - put result in register edi.
985 __ mov(edi, edx); 1013 __ mov(edi, edx);
986 GenerateDictionaryLoad(masm, miss, eax, edi, ebx, ecx, CHECK_DICTIONARY); 1014 GenerateDictionaryLoad(masm, miss, edx, ecx, eax, edi, ebx, CHECK_DICTIONARY);
987 1015
988 // Check that the result is not a smi. 1016 // Check that the result is not a smi.
989 __ test(edi, Immediate(kSmiTagMask)); 1017 __ test(edi, Immediate(kSmiTagMask));
990 __ j(zero, miss, not_taken); 1018 __ j(zero, miss, not_taken);
991 1019
992 // Check that the value is a JavaScript function, fetching its map into eax. 1020 // Check that the value is a JavaScript function, fetching its map into eax.
993 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 1021 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
994 __ j(not_equal, miss, not_taken); 1022 __ j(not_equal, miss, not_taken);
995 1023
996 // Patch the receiver on stack with the global proxy if necessary. 1024 // Patch the receiver on stack with the global proxy if necessary.
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1120 __ bind(&invoke); 1148 __ bind(&invoke);
1121 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1149 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
1122 } 1150 }
1123 1151
1124 1152
1125 // Defined in ic.cc. 1153 // Defined in ic.cc.
1126 Object* LoadIC_Miss(Arguments args); 1154 Object* LoadIC_Miss(Arguments args);
1127 1155
1128 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 1156 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
1129 // ----------- S t a t e ------------- 1157 // ----------- S t a t e -------------
1158 // -- eax : receiver
1130 // -- ecx : name 1159 // -- ecx : name
1131 // -- esp[0] : return address 1160 // -- esp[0] : return address
1132 // -- esp[4] : receiver
1133 // ----------------------------------- 1161 // -----------------------------------
1134 1162
1135 __ mov(eax, Operand(esp, kPointerSize));
1136
1137 // Probe the stub cache. 1163 // Probe the stub cache.
1138 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, 1164 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
1139 NOT_IN_LOOP, 1165 NOT_IN_LOOP,
1140 MONOMORPHIC); 1166 MONOMORPHIC);
1141 StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); 1167 StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx);
1142 1168
1143 // Cache miss: Jump to runtime. 1169 // Cache miss: Jump to runtime.
1144 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); 1170 GenerateMiss(masm);
1145 } 1171 }
1146 1172
1147 1173
1148 void LoadIC::GenerateNormal(MacroAssembler* masm) { 1174 void LoadIC::GenerateNormal(MacroAssembler* masm) {
1149 // ----------- S t a t e ------------- 1175 // ----------- S t a t e -------------
1176 // -- eax : receiver
1150 // -- ecx : name 1177 // -- ecx : name
1151 // -- esp[0] : return address 1178 // -- esp[0] : return address
1152 // -- esp[4] : receiver
1153 // ----------------------------------- 1179 // -----------------------------------
1154 Label miss, probe, global; 1180 Label miss, probe, global;
1155 1181
1156 __ mov(eax, Operand(esp, kPointerSize));
1157
1158 // Check that the receiver isn't a smi. 1182 // Check that the receiver isn't a smi.
1159 __ test(eax, Immediate(kSmiTagMask)); 1183 __ test(eax, Immediate(kSmiTagMask));
1160 __ j(zero, &miss, not_taken); 1184 __ j(zero, &miss, not_taken);
1161 1185
1162 // Check that the receiver is a valid JS object. 1186 // Check that the receiver is a valid JS object.
1163 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 1187 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
1164 __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1188 __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceTypeOffset));
1165 __ cmp(edx, FIRST_JS_OBJECT_TYPE); 1189 __ cmp(edx, FIRST_JS_OBJECT_TYPE);
1166 __ j(less, &miss, not_taken); 1190 __ j(less, &miss, not_taken);
1167 1191
1168 // If this assert fails, we have to check upper bound too. 1192 // If this assert fails, we have to check upper bound too.
1169 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1193 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
1170 1194
1171 // Check for access to global object (unlikely). 1195 // Check for access to global object (unlikely).
1172 __ cmp(edx, JS_GLOBAL_PROXY_TYPE); 1196 __ cmp(edx, JS_GLOBAL_PROXY_TYPE);
1173 __ j(equal, &global, not_taken); 1197 __ j(equal, &global, not_taken);
1174 1198
1175 // Check for non-global object that requires access check. 1199 // Check for non-global object that requires access check.
1176 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset)); 1200 __ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
1177 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 1201 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
1178 __ j(not_zero, &miss, not_taken); 1202 __ j(not_zero, &miss, not_taken);
1179 1203
1180 // Search the dictionary placing the result in eax. 1204 // Search the dictionary placing the result in eax.
1181 __ bind(&probe); 1205 __ bind(&probe);
1182 GenerateDictionaryLoad(masm, &miss, edx, eax, ebx, ecx, CHECK_DICTIONARY); 1206 GenerateDictionaryLoad(masm,
1207 &miss,
1208 eax,
1209 ecx,
1210 edx,
1211 edi,
1212 ebx,
1213 CHECK_DICTIONARY);
1214 __ mov(eax, edi);
1183 __ ret(0); 1215 __ ret(0);
1184 1216
1185 // Global object access: Check access rights. 1217 // Global object access: Check access rights.
1186 __ bind(&global); 1218 __ bind(&global);
1187 __ CheckAccessGlobalProxy(eax, edx, &miss); 1219 __ CheckAccessGlobalProxy(eax, edx, &miss);
1188 __ jmp(&probe); 1220 __ jmp(&probe);
1189 1221
1190 // Cache miss: Restore receiver from stack and jump to runtime. 1222 // Cache miss: Restore receiver from stack and jump to runtime.
1191 __ bind(&miss); 1223 __ bind(&miss);
1192 __ mov(eax, Operand(esp, 1 * kPointerSize)); 1224 GenerateMiss(masm);
1193 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
1194 } 1225 }
1195 1226
1196 1227
1197 void LoadIC::GenerateMiss(MacroAssembler* masm) { 1228 void LoadIC::GenerateMiss(MacroAssembler* masm) {
1198 // ----------- S t a t e ------------- 1229 // ----------- S t a t e -------------
1230 // -- eax : receiver
1199 // -- ecx : name 1231 // -- ecx : name
1200 // -- esp[0] : return address 1232 // -- esp[0] : return address
1201 // -- esp[4] : receiver
1202 // ----------------------------------- 1233 // -----------------------------------
1203 1234
1204 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
1205 }
1206
1207
1208 void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
1209 // ----------- S t a t e -------------
1210 // -- ecx : name
1211 // -- esp[0] : return address
1212 // -- esp[4] : receiver
1213 // -----------------------------------
1214
1215 __ mov(eax, Operand(esp, kPointerSize));
1216 __ pop(ebx); 1235 __ pop(ebx);
1217 __ push(eax); // receiver 1236 __ push(eax); // receiver
1218 __ push(ecx); // name 1237 __ push(ecx); // name
1219 __ push(ebx); // return address 1238 __ push(ebx); // return address
1220 1239
1221 // Perform tail call to the entry. 1240 // Perform tail call to the entry.
1222 __ TailCallRuntime(f, 2, 1); 1241 __ TailCallRuntime(ExternalReference(IC_Utility(kLoadIC_Miss)), 2, 1);
1223 } 1242 }
1224 1243
1225 1244
1226 // One byte opcode for test eax,0xXXXXXXXX. 1245 // One byte opcode for test eax,0xXXXXXXXX.
1227 static const byte kTestEaxByte = 0xA9; 1246 static const byte kTestEaxByte = 0xA9;
1228 1247
1229 1248
1230 void LoadIC::ClearInlinedVersion(Address address) { 1249 void LoadIC::ClearInlinedVersion(Address address) {
1231 // Reset the map check of the inlined inobject property load (if 1250 // Reset the map check of the inlined inobject property load (if
1232 // present) to guarantee failure by holding an invalid map (the null 1251 // present) to guarantee failure by holding an invalid map (the null
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 return PatchInlinedMapCheck(address, map); 1335 return PatchInlinedMapCheck(address, map);
1317 } 1336 }
1318 1337
1319 1338
1320 // Defined in ic.cc. 1339 // Defined in ic.cc.
1321 Object* KeyedLoadIC_Miss(Arguments args); 1340 Object* KeyedLoadIC_Miss(Arguments args);
1322 1341
1323 1342
1324 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1343 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
1325 // ----------- S t a t e ------------- 1344 // ----------- S t a t e -------------
1345 // -- eax : key
1346 // -- edx : receiver
1326 // -- esp[0] : return address 1347 // -- esp[0] : return address
1327 // -- esp[4] : name
1328 // -- esp[8] : receiver
1329 // ----------------------------------- 1348 // -----------------------------------
1330 1349
1331 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
1332 }
1333
1334
1335 void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
1336 // ----------- S t a t e -------------
1337 // -- esp[0] : return address
1338 // -- esp[4] : name
1339 // -- esp[8] : receiver
1340 // -----------------------------------
1341
1342 __ mov(eax, Operand(esp, kPointerSize));
1343 __ mov(ecx, Operand(esp, 2 * kPointerSize));
1344 __ pop(ebx); 1350 __ pop(ebx);
1345 __ push(ecx); // receiver 1351 __ push(edx); // receiver
1346 __ push(eax); // name 1352 __ push(eax); // name
1347 __ push(ebx); // return address 1353 __ push(ebx); // return address
1348 1354
1349 // Perform tail call to the entry. 1355 // Perform tail call to the entry.
1350 __ TailCallRuntime(f, 2, 1); 1356 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedLoadIC_Miss)), 2, 1);
1351 } 1357 }
1352 1358
1353 1359
1360 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
1361 // ----------- S t a t e -------------
1362 // -- eax : key
1363 // -- edx : receiver
1364 // -- esp[0] : return address
1365 // -----------------------------------
1366
1367 __ pop(ebx);
1368 __ push(edx); // receiver
1369 __ push(eax); // name
1370 __ push(ebx); // return address
1371
1372 // Perform tail call to the entry.
1373 __ TailCallRuntime(ExternalReference(Runtime::kKeyedGetProperty), 2, 1);
1374 }
1375
1376
1354 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 1377 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
1355 // ----------- S t a t e ------------- 1378 // ----------- S t a t e -------------
1356 // -- eax : value 1379 // -- eax : value
1357 // -- ecx : name 1380 // -- ecx : name
1358 // -- edx : receiver 1381 // -- edx : receiver
1359 // -- esp[0] : return address 1382 // -- esp[0] : return address
1360 // ----------------------------------- 1383 // -----------------------------------
1361 1384
1362 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1385 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
1363 NOT_IN_LOOP, 1386 NOT_IN_LOOP,
1364 MONOMORPHIC); 1387 MONOMORPHIC);
1365 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1388 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
1366 1389
1367 // Cache miss: Jump to runtime. 1390 // Cache miss: Jump to runtime.
1368 GenerateMiss(masm); 1391 GenerateMiss(masm);
1369 } 1392 }
1370 1393
1371 1394
1372 void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
1373 // ----------- S t a t e -------------
1374 // -- eax : value
1375 // -- ecx : transition map
1376 // -- edx : receiver
1377 // -- esp[0] : return address
1378 // -----------------------------------
1379
1380 __ pop(ebx);
1381 __ push(edx); // receiver
1382 __ push(ecx); // transition map
1383 __ push(eax); // value
1384 __ push(ebx); // return address
1385
1386 // Perform tail call to the entry.
1387 __ TailCallRuntime(
1388 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
1389 }
1390
1391
1392 void StoreIC::GenerateMiss(MacroAssembler* masm) { 1395 void StoreIC::GenerateMiss(MacroAssembler* masm) {
1393 // ----------- S t a t e ------------- 1396 // ----------- S t a t e -------------
1394 // -- eax : value 1397 // -- eax : value
1395 // -- ecx : name 1398 // -- ecx : name
1396 // -- edx : receiver 1399 // -- edx : receiver
1397 // -- esp[0] : return address 1400 // -- esp[0] : return address
1398 // ----------------------------------- 1401 // -----------------------------------
1399 1402
1400 __ pop(ebx); 1403 __ pop(ebx);
1401 __ push(edx); 1404 __ push(edx);
1402 __ push(ecx); 1405 __ push(ecx);
1403 __ push(eax); 1406 __ push(eax);
1404 __ push(ebx); 1407 __ push(ebx);
1405 1408
1406 // Perform tail call to the entry. 1409 // Perform tail call to the entry.
1407 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1); 1410 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1);
1408 } 1411 }
1409 1412
1410 1413
1414 void StoreIC::GenerateArrayLength(MacroAssembler* masm) {
1415 // ----------- S t a t e -------------
1416 // -- eax : value
1417 // -- ecx : name
1418 // -- edx : receiver
1419 // -- esp[0] : return address
1420 // -----------------------------------
1421 //
1422 // This accepts as a receiver anything JSObject::SetElementsLength accepts
1423 // (currently anything except for external and pixel arrays which means
1424 // anything with elements of FixedArray type.), but currently is restricted
1425 // to JSArray.
1426 // Value must be a number, but only smis are accepted as the most common case.
1427
1428 Label miss;
1429
1430 Register receiver = edx;
1431 Register value = eax;
1432 Register scratch = ebx;
1433
1434 // Check that the receiver isn't a smi.
1435 __ test(receiver, Immediate(kSmiTagMask));
1436 __ j(zero, &miss, not_taken);
1437
1438 // Check that the object is a JS array.
1439 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
1440 __ j(not_equal, &miss, not_taken);
1441
1442 // Check that elements are FixedArray.
1443 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
1444 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
1445 __ j(not_equal, &miss, not_taken);
1446
1447 // Check that value is a smi.
1448 __ test(value, Immediate(kSmiTagMask));
1449 __ j(not_zero, &miss, not_taken);
1450
1451 // Prepare tail call to StoreIC_ArrayLength.
1452 __ pop(scratch);
1453 __ push(receiver);
1454 __ push(value);
1455 __ push(scratch); // return address
1456
1457 __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_ArrayLength)), 2, 1);
1458
1459 __ bind(&miss);
1460
1461 GenerateMiss(masm);
1462 }
1463
1464
1411 // Defined in ic.cc. 1465 // Defined in ic.cc.
1412 Object* KeyedStoreIC_Miss(Arguments args); 1466 Object* KeyedStoreIC_Miss(Arguments args);
1413 1467
1414 void KeyedStoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) { 1468 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
1415 // ----------- S t a t e ------------- 1469 // ----------- S t a t e -------------
1416 // -- eax : value 1470 // -- eax : value
1417 // -- esp[0] : return address 1471 // -- esp[0] : return address
1418 // -- esp[4] : key 1472 // -- esp[4] : key
1419 // -- esp[8] : receiver 1473 // -- esp[8] : receiver
1420 // ----------------------------------- 1474 // -----------------------------------
1421 1475
1422 __ pop(ecx); 1476 __ pop(ecx);
1423 __ push(Operand(esp, 1 * kPointerSize)); 1477 __ push(Operand(esp, 1 * kPointerSize));
1424 __ push(Operand(esp, 1 * kPointerSize)); 1478 __ push(Operand(esp, 1 * kPointerSize));
1425 __ push(eax); 1479 __ push(eax);
1426 __ push(ecx); 1480 __ push(ecx);
1427 1481
1428 // Do tail-call to runtime routine. 1482 // Do tail-call to runtime routine.
1429 __ TailCallRuntime(f, 3, 1); 1483 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1);
1430 } 1484 }
1431 1485
1432 1486
1433 void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) { 1487 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
1434 // ----------- S t a t e ------------- 1488 // ----------- S t a t e -------------
1435 // -- eax : value 1489 // -- eax : value
1436 // -- ecx : transition map
1437 // -- esp[0] : return address 1490 // -- esp[0] : return address
1438 // -- esp[4] : key 1491 // -- esp[4] : key
1439 // -- esp[8] : receiver 1492 // -- esp[8] : receiver
1440 // ----------------------------------- 1493 // -----------------------------------
1441 1494
1442 __ pop(ebx); 1495 __ pop(ecx);
1443 __ push(Operand(esp, 1 * kPointerSize)); 1496 __ push(Operand(esp, 1 * kPointerSize));
1497 __ push(Operand(esp, 1 * kPointerSize));
1498 __ push(eax);
1444 __ push(ecx); 1499 __ push(ecx);
1445 __ push(eax);
1446 __ push(ebx);
1447 1500
1448 // Do tail-call to runtime routine. 1501 // Do tail-call to runtime routine.
1449 __ TailCallRuntime( 1502 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedStoreIC_Miss)), 3, 1);
1450 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
1451 } 1503 }
1452 1504
1453 #undef __ 1505 #undef __
1454 1506
1455 1507
1456 } } // namespace v8::internal 1508 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698