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

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

Issue 601080: Change KeyedLoadIC interface on ia32 to take receiver and name in registers. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
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/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 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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 Label miss; 212 Label miss;
213 213
214 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); 214 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
215 __ bind(&miss); 215 __ bind(&miss);
216 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 216 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
217 } 217 }
218 218
219 219
220 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 220 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
221 // ----------- S t a t e ------------- 221 // ----------- S t a t e -------------
222 // -- eax : key
223 // -- edx : receiver
222 // -- esp[0] : return address 224 // -- esp[0] : return address
223 // -- esp[4] : name
224 // -- esp[8] : receiver
225 // ----------------------------------- 225 // -----------------------------------
226 Label slow, check_string, index_int, index_string; 226 Label slow, check_string, index_int, index_string;
227 Label check_pixel_array, probe_dictionary; 227 Label check_pixel_array, probe_dictionary;
228 228
229 // Load name and receiver.
230 __ mov(eax, Operand(esp, kPointerSize));
231 __ mov(ecx, Operand(esp, 2 * kPointerSize));
232
233 // Check that the object isn't a smi. 229 // Check that the object isn't a smi.
234 __ test(ecx, Immediate(kSmiTagMask)); 230 __ test(edx, Immediate(kSmiTagMask));
235 __ j(zero, &slow, not_taken); 231 __ j(zero, &slow, not_taken);
236 232
237 // Get the map of the receiver. 233 // Get the map of the receiver.
238 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 234 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
239 235
240 // Check bit field. 236 // Check bit field.
241 __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset)); 237 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset));
242 __ test(ebx, Immediate(kSlowCaseBitFieldMask)); 238 __ test(ebx, Immediate(kSlowCaseBitFieldMask));
243 __ j(not_zero, &slow, not_taken); 239 __ j(not_zero, &slow, not_taken);
244 // Check that the object is some kind of JS object EXCEPT JS Value type. 240 // Check that the object is some kind of JS object EXCEPT JS Value type.
245 // In the case that the object is a value-wrapper object, 241 // In the case that the object is a value-wrapper object,
246 // we enter the runtime system to make sure that indexing 242 // we enter the runtime system to make sure that indexing
247 // into string objects work as intended. 243 // into string objects work as intended.
248 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 244 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
249 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); 245 __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
250 __ cmp(edx, JS_OBJECT_TYPE); 246 __ j(below, &slow, not_taken);
251 __ j(less, &slow, not_taken);
252 // Check that the key is a smi. 247 // Check that the key is a smi.
253 __ test(eax, Immediate(kSmiTagMask)); 248 __ test(eax, Immediate(kSmiTagMask));
254 __ j(not_zero, &check_string, not_taken); 249 __ j(not_zero, &check_string, not_taken);
255 __ sar(eax, kSmiTagSize); 250 __ mov(ebx, eax);
251 __ SmiUntag(ebx);
256 // Get the elements array of the object. 252 // Get the elements array of the object.
257 __ bind(&index_int); 253 __ bind(&index_int);
258 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); 254 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
259 // Check that the object is in fast mode (not dictionary). 255 // Check that the object is in fast mode (not dictionary).
260 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 256 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true);
261 Immediate(Factory::fixed_array_map()));
262 __ j(not_equal, &check_pixel_array);
263 // Check that the key (index) is within bounds. 257 // Check that the key (index) is within bounds.
264 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); 258 __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
265 __ j(above_equal, &slow); 259 __ j(above_equal, &slow);
266 // Fast case: Do the load. 260 // Fast case: Do the load.
267 __ mov(eax, 261 __ mov(ecx, FieldOperand(ecx, ebx, times_4, FixedArray::kHeaderSize));
268 Operand(ecx, eax, times_4, FixedArray::kHeaderSize - kHeapObjectTag)); 262 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value()));
269 __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
270 // In case the loaded value is the_hole we have to consult GetProperty 263 // In case the loaded value is the_hole we have to consult GetProperty
271 // to ensure the prototype chain is searched. 264 // to ensure the prototype chain is searched.
272 __ j(equal, &slow); 265 __ j(equal, &slow);
266 __ mov(eax, ecx);
273 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 267 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
274 __ ret(0); 268 __ ret(0);
275 269
270 __ bind(&check_pixel_array);
276 // Check whether the elements is a pixel array. 271 // Check whether the elements is a pixel array.
277 // eax: untagged index 272 // edx: receiver
278 // ecx: elements array 273 // ebx: untagged index
279 __ bind(&check_pixel_array); 274 // eax: key
280 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 275 // ecx: elements
281 Immediate(Factory::pixel_array_map())); 276 __ CheckMap(ecx, Factory::pixel_array_map(), &slow, true);
282 __ j(not_equal, &slow); 277 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset));
283 __ cmp(eax, FieldOperand(ecx, PixelArray::kLengthOffset));
284 __ j(above_equal, &slow); 278 __ j(above_equal, &slow);
285 __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); 279 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset));
286 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); 280 __ movzx_b(eax, Operand(eax, ebx, times_1, 0));
287 __ shl(eax, kSmiTagSize); 281 __ SmiTag(eax);
288 __ ret(0); 282 __ ret(0);
289 283
290 // Slow case: Load name and receiver from stack and jump to runtime.
291 __ bind(&slow); 284 __ bind(&slow);
285 // Slow case: jump to runtime.
286 // edx: receiver
287 // eax: key
292 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 288 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
293 GenerateRuntimeGetProperty(masm); 289 GenerateRuntimeGetProperty(masm);
294 290
295 __ bind(&check_string); 291 __ bind(&check_string);
296 // The key is not a smi. 292 // The key is not a smi.
297 // Is it a string? 293 // Is it a string?
298 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); 294 // edx: receiver
295 // eax: key
296 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx);
299 __ j(above_equal, &slow); 297 __ j(above_equal, &slow);
300 // Is the string an array index, with cached numeric value? 298 // Is the string an array index, with cached numeric value?
301 __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset)); 299 __ mov(ebx, FieldOperand(eax, String::kHashFieldOffset));
302 __ test(ebx, Immediate(String::kIsArrayIndexMask)); 300 __ test(ebx, Immediate(String::kIsArrayIndexMask));
303 __ j(not_zero, &index_string, not_taken); 301 __ j(not_zero, &index_string, not_taken);
304 302
305 // Is the string a symbol? 303 // Is the string a symbol?
306 __ movzx_b(ebx, FieldOperand(edx, Map::kInstanceTypeOffset)); 304 __ movzx_b(ebx, FieldOperand(ecx, Map::kInstanceTypeOffset));
307 ASSERT(kSymbolTag != 0); 305 ASSERT(kSymbolTag != 0);
308 __ test(ebx, Immediate(kIsSymbolMask)); 306 __ test(ebx, Immediate(kIsSymbolMask));
309 __ j(zero, &slow, not_taken); 307 __ j(zero, &slow, not_taken);
310 308
311 // If the receiver is a fast-case object, check the keyed lookup 309 // If the receiver is a fast-case object, check the keyed lookup
312 // cache. Otherwise probe the dictionary leaving result in ecx. 310 // cache. Otherwise probe the dictionary.
313 __ mov(ebx, FieldOperand(ecx, JSObject::kPropertiesOffset)); 311 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
314 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 312 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
315 Immediate(Factory::hash_table_map())); 313 Immediate(Factory::hash_table_map()));
316 __ j(equal, &probe_dictionary); 314 __ j(equal, &probe_dictionary);
317 315
318 // Load the map of the receiver, compute the keyed lookup cache hash 316 // Load the map of the receiver, compute the keyed lookup cache hash
319 // based on 32 bits of the map pointer and the string hash. 317 // based on 32 bits of the map pointer and the string hash.
320 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); 318 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
321 __ mov(edx, ebx); 319 __ mov(ecx, ebx);
322 __ shr(edx, KeyedLookupCache::kMapHashShift); 320 __ shr(ecx, KeyedLookupCache::kMapHashShift);
323 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); 321 __ mov(edi, FieldOperand(eax, String::kHashFieldOffset));
324 __ shr(eax, String::kHashShift); 322 __ shr(edi, String::kHashShift);
325 __ xor_(edx, Operand(eax)); 323 __ xor_(ecx, Operand(edi));
326 __ and_(edx, KeyedLookupCache::kCapacityMask); 324 __ and_(ecx, KeyedLookupCache::kCapacityMask);
327 325
328 // Load the key (consisting of map and symbol) from the cache and 326 // Load the key (consisting of map and symbol) from the cache and
329 // check for match. 327 // check for match.
330 ExternalReference cache_keys 328 ExternalReference cache_keys
331 = ExternalReference::keyed_lookup_cache_keys(); 329 = ExternalReference::keyed_lookup_cache_keys();
332 __ mov(edi, edx); 330 __ mov(edi, ecx);
333 __ shl(edi, kPointerSizeLog2 + 1); 331 __ shl(edi, kPointerSizeLog2 + 1);
334 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); 332 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
335 __ j(not_equal, &slow); 333 __ j(not_equal, &slow);
336 __ add(Operand(edi), Immediate(kPointerSize)); 334 __ add(Operand(edi), Immediate(kPointerSize));
337 __ mov(edi, Operand::StaticArray(edi, times_1, cache_keys)); 335 __ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
338 __ cmp(edi, Operand(esp, kPointerSize));
339 __ j(not_equal, &slow); 336 __ j(not_equal, &slow);
340 337
341 // Get field offset and check that it is an in-object property. 338 // Get field offset and check that it is an in-object property.
339 // edx : receiver
340 // ebx : receiver's map
341 // eax : key
342 // ecx : lookup cache index
342 ExternalReference cache_field_offsets 343 ExternalReference cache_field_offsets
343 = ExternalReference::keyed_lookup_cache_field_offsets(); 344 = ExternalReference::keyed_lookup_cache_field_offsets();
344 __ mov(eax, 345 __ mov(edi,
345 Operand::StaticArray(edx, times_pointer_size, cache_field_offsets)); 346 Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
346 __ movzx_b(edx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); 347 __ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
347 __ cmp(eax, Operand(edx)); 348 __ cmp(edi, Operand(ecx));
348 __ j(above_equal, &slow); 349 __ j(above_equal, &slow);
349 350
350 // Load in-object property. 351 // Load in-object property.
351 __ sub(eax, Operand(edx)); 352 __ sub(edi, Operand(ecx));
352 __ movzx_b(edx, FieldOperand(ebx, Map::kInstanceSizeOffset)); 353 __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
353 __ add(eax, Operand(edx)); 354 __ add(ecx, Operand(edi));
354 __ mov(eax, FieldOperand(ecx, eax, times_pointer_size, 0)); 355 __ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));
355 __ ret(0); 356 __ ret(0);
356 357
357 // Do a quick inline probe of the receiver's dictionary, if it 358 // Do a quick inline probe of the receiver's dictionary, if it
358 // exists. 359 // exists.
359 __ bind(&probe_dictionary); 360 __ bind(&probe_dictionary);
360 GenerateDictionaryLoad(masm, 361 GenerateDictionaryLoad(masm,
361 &slow, 362 &slow,
362 ecx, 363 edx,
363 eax, 364 eax,
364 ebx, 365 ebx,
365 edx, 366 ecx,
366 edi, 367 edi,
367 DICTIONARY_CHECK_DONE); 368 DICTIONARY_CHECK_DONE);
368 GenerateCheckNonObjectOrLoaded(masm, &slow, edx, ebx); 369 GenerateCheckNonObjectOrLoaded(masm, &slow, ecx, ebx);
369 __ mov(eax, Operand(edx)); 370 __ mov(eax, ecx);
370 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 371 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
371 __ ret(0); 372 __ ret(0);
372 373
373 // If the hash field contains an array index pick it out. The assert checks 374 // If the hash field contains an array index pick it out. The assert checks
374 // that the constants for the maximum number of digits for an array index 375 // that the constants for the maximum number of digits for an array index
375 // cached in the hash field and the number of bits reserved for it does not 376 // cached in the hash field and the number of bits reserved for it does not
376 // conflict. 377 // conflict.
377 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 378 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
378 (1 << String::kArrayIndexValueBits)); 379 (1 << String::kArrayIndexValueBits));
379 __ bind(&index_string); 380 __ bind(&index_string);
380 __ mov(eax, Operand(ebx)); 381 __ and_(ebx, String::kArrayIndexHashMask);
381 __ and_(eax, String::kArrayIndexHashMask); 382 __ shr(ebx, String::kHashShift);
382 __ shr(eax, String::kHashShift);
383 __ jmp(&index_int); 383 __ jmp(&index_int);
384 } 384 }
385 385
386 386
387 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 387 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
388 // ----------- S t a t e ------------- 388 // ----------- S t a t e -------------
389 // -- eax : key
390 // -- edx : receiver
389 // -- esp[0] : return address 391 // -- esp[0] : return address
390 // -- esp[4] : key
391 // -- esp[8] : receiver
392 // ----------------------------------- 392 // -----------------------------------
393 Label miss, index_ok; 393 Label miss, index_ok;
394 394
395 // Pop return address. 395 // Pop return address.
396 // Performing the load early is better in the common case. 396 // Performing the load early is better in the common case.
397 __ pop(eax); 397 __ pop(ebx);
398 398
399 __ mov(ebx, Operand(esp, 1 * kPointerSize)); 399 __ test(edx, Immediate(kSmiTagMask));
400 __ test(ebx, Immediate(kSmiTagMask));
401 __ j(zero, &miss); 400 __ j(zero, &miss);
402 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); 401 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
403 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 402 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
404 __ test(ecx, Immediate(kIsNotStringMask)); 403 __ test(ecx, Immediate(kIsNotStringMask));
405 __ j(not_zero, &miss); 404 __ j(not_zero, &miss);
406 405
407 // Check if key is a smi or a heap number. 406 // Check if key is a smi or a heap number.
408 __ mov(edx, Operand(esp, 0)); 407 __ test(eax, Immediate(kSmiTagMask));
409 __ test(edx, Immediate(kSmiTagMask));
410 __ j(zero, &index_ok); 408 __ j(zero, &index_ok);
411 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); 409 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
412 __ cmp(ecx, Factory::heap_number_map()); 410 __ cmp(ecx, Factory::heap_number_map());
413 __ j(not_equal, &miss); 411 __ j(not_equal, &miss);
414 412
415 __ bind(&index_ok); 413 __ bind(&index_ok);
416 // Duplicate receiver and key since they are expected on the stack after 414 // Push receiver and key on the stack, and make a tail call.
417 // the KeyedLoadIC call. 415 __ push(edx); // receiver
418 __ push(ebx); // receiver 416 __ push(eax); // key
419 __ push(edx); // key 417 __ push(ebx); // return address
420 __ push(eax); // return address
421 __ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION); 418 __ InvokeBuiltin(Builtins::STRING_CHAR_AT, JUMP_FUNCTION);
422 419
423 __ bind(&miss); 420 __ bind(&miss);
424 __ push(eax); 421 __ push(ebx);
425 GenerateMiss(masm); 422 GenerateMiss(masm);
426 } 423 }
427 424
428 425
429 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, 426 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
430 ExternalArrayType array_type) { 427 ExternalArrayType array_type) {
431 // ----------- S t a t e ------------- 428 // ----------- S t a t e -------------
429 // -- eax : key
430 // -- edx : receiver
432 // -- esp[0] : return address 431 // -- esp[0] : return address
433 // -- esp[4] : key
434 // -- esp[8] : receiver
435 // ----------------------------------- 432 // -----------------------------------
436 Label slow, failed_allocation; 433 Label slow, failed_allocation;
437 434
438 // Load name and receiver.
439 __ mov(eax, Operand(esp, kPointerSize));
440 __ mov(ecx, Operand(esp, 2 * kPointerSize));
441
442 // Check that the object isn't a smi. 435 // Check that the object isn't a smi.
443 __ test(ecx, Immediate(kSmiTagMask)); 436 __ test(edx, Immediate(kSmiTagMask));
444 __ j(zero, &slow, not_taken); 437 __ j(zero, &slow, not_taken);
445 438
446 // Check that the key is a smi. 439 // Check that the key is a smi.
447 __ test(eax, Immediate(kSmiTagMask)); 440 __ test(eax, Immediate(kSmiTagMask));
448 __ j(not_zero, &slow, not_taken); 441 __ j(not_zero, &slow, not_taken);
449 442
450 // Get the map of the receiver. 443 // Get the map of the receiver.
451 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 444 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
452 // Check that the receiver does not require access checks. We need 445 // Check that the receiver does not require access checks. We need
453 // to check this explicitly since this generic stub does not perform 446 // to check this explicitly since this generic stub does not perform
454 // map checks. 447 // map checks.
455 __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset)); 448 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset));
456 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); 449 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
457 __ j(not_zero, &slow, not_taken); 450 __ j(not_zero, &slow, not_taken);
458 451
459 // Get the instance type from the map of the receiver. 452 __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
460 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
461 // Check that the object is a JS object.
462 __ cmp(edx, JS_OBJECT_TYPE);
463 __ j(not_equal, &slow, not_taken); 453 __ j(not_equal, &slow, not_taken);
464 454
465 // Check that the elements array is the appropriate type of 455 // Check that the elements array is the appropriate type of
466 // ExternalArray. 456 // ExternalArray.
467 // eax: index (as a smi) 457 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
468 // ecx: JSObject
469 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
470 Handle<Map> map(Heap::MapForExternalArrayType(array_type)); 458 Handle<Map> map(Heap::MapForExternalArrayType(array_type));
471 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), 459 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
472 Immediate(map)); 460 Immediate(map));
473 __ j(not_equal, &slow, not_taken); 461 __ j(not_equal, &slow, not_taken);
474 462
463 // eax: key, known to be a smi.
464 // edx: receiver, known to be a JSObject.
465 // ebx: elements object, known to be an external array.
475 // Check that the index is in range. 466 // Check that the index is in range.
476 __ sar(eax, kSmiTagSize); // Untag the index. 467 __ mov(ecx, eax);
477 __ cmp(eax, FieldOperand(ecx, ExternalArray::kLengthOffset)); 468 __ SmiUntag(ecx); // Untag the index.
469 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
478 // Unsigned comparison catches both negative and too-large values. 470 // Unsigned comparison catches both negative and too-large values.
479 __ j(above_equal, &slow); 471 __ j(above_equal, &slow);
480 472
481 // eax: untagged index 473 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
482 // ecx: elements array 474 // ebx: base pointer of external storage
483 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset));
484 // ecx: base pointer of external storage
485 switch (array_type) { 475 switch (array_type) {
486 case kExternalByteArray: 476 case kExternalByteArray:
487 __ movsx_b(eax, Operand(ecx, eax, times_1, 0)); 477 __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0));
488 break; 478 break;
489 case kExternalUnsignedByteArray: 479 case kExternalUnsignedByteArray:
490 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); 480 __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0));
491 break; 481 break;
492 case kExternalShortArray: 482 case kExternalShortArray:
493 __ movsx_w(eax, Operand(ecx, eax, times_2, 0)); 483 __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0));
494 break; 484 break;
495 case kExternalUnsignedShortArray: 485 case kExternalUnsignedShortArray:
496 __ movzx_w(eax, Operand(ecx, eax, times_2, 0)); 486 __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0));
497 break; 487 break;
498 case kExternalIntArray: 488 case kExternalIntArray:
499 case kExternalUnsignedIntArray: 489 case kExternalUnsignedIntArray:
500 __ mov(eax, Operand(ecx, eax, times_4, 0)); 490 __ mov(ecx, Operand(ebx, ecx, times_4, 0));
501 break; 491 break;
502 case kExternalFloatArray: 492 case kExternalFloatArray:
503 __ fld_s(Operand(ecx, eax, times_4, 0)); 493 __ fld_s(Operand(ebx, ecx, times_4, 0));
504 break; 494 break;
505 default: 495 default:
506 UNREACHABLE(); 496 UNREACHABLE();
507 break; 497 break;
508 } 498 }
509 499
510 // For integer array types: 500 // For integer array types:
511 // eax: value 501 // ecx: value
512 // For floating-point array type: 502 // For floating-point array type:
513 // FP(0): value 503 // FP(0): value
514 504
515 if (array_type == kExternalIntArray || 505 if (array_type == kExternalIntArray ||
516 array_type == kExternalUnsignedIntArray) { 506 array_type == kExternalUnsignedIntArray) {
517 // For the Int and UnsignedInt array types, we need to see whether 507 // For the Int and UnsignedInt array types, we need to see whether
518 // the value can be represented in a Smi. If not, we need to convert 508 // the value can be represented in a Smi. If not, we need to convert
519 // it to a HeapNumber. 509 // it to a HeapNumber.
520 Label box_int; 510 Label box_int;
521 if (array_type == kExternalIntArray) { 511 if (array_type == kExternalIntArray) {
522 // See Smi::IsValid for why this works. 512 __ cmp(ecx, 0xC0000000);
523 __ mov(ebx, eax); 513 __ j(sign, &box_int);
524 __ add(Operand(ebx), Immediate(0x40000000));
525 __ cmp(ebx, 0x80000000);
526 __ j(above_equal, &box_int);
527 } else { 514 } else {
528 ASSERT_EQ(array_type, kExternalUnsignedIntArray); 515 ASSERT_EQ(array_type, kExternalUnsignedIntArray);
529 // The test is different for unsigned int values. Since we need 516 // The test is different for unsigned int values. Since we need
530 // the Smi-encoded result to be treated as unsigned, we can't 517 // the value to be in the range of a positive smi, we can't
531 // handle either of the top two bits being set in the value. 518 // handle either of the top two bits being set in the value.
532 __ test(eax, Immediate(0xC0000000)); 519 __ test(ecx, Immediate(0xC0000000));
533 __ j(not_zero, &box_int); 520 __ j(not_zero, &box_int);
534 } 521 }
535 522
536 __ shl(eax, kSmiTagSize); 523 __ mov(eax, ecx);
524 __ SmiTag(eax);
537 __ ret(0); 525 __ ret(0);
538 526
539 __ bind(&box_int); 527 __ bind(&box_int);
540 528
541 // Allocate a HeapNumber for the int and perform int-to-double 529 // Allocate a HeapNumber for the int and perform int-to-double
542 // conversion. 530 // conversion.
543 if (array_type == kExternalIntArray) { 531 if (array_type == kExternalIntArray) {
544 __ push(eax); 532 __ push(ecx);
545 __ fild_s(Operand(esp, 0)); 533 __ fild_s(Operand(esp, 0));
546 __ pop(eax); 534 __ pop(ecx);
547 } else { 535 } else {
548 ASSERT(array_type == kExternalUnsignedIntArray); 536 ASSERT(array_type == kExternalUnsignedIntArray);
549 // Need to zero-extend the value. 537 // Need to zero-extend the value.
550 // There's no fild variant for unsigned values, so zero-extend 538 // There's no fild variant for unsigned values, so zero-extend
551 // to a 64-bit int manually. 539 // to a 64-bit int manually.
552 __ push(Immediate(0)); 540 __ push(Immediate(0));
553 __ push(eax); 541 __ push(ecx);
554 __ fild_d(Operand(esp, 0)); 542 __ fild_d(Operand(esp, 0));
555 __ pop(eax); 543 __ pop(ecx);
556 __ pop(eax); 544 __ pop(ecx);
557 } 545 }
558 // FP(0): value 546 // FP(0): value
559 __ AllocateHeapNumber(eax, ebx, ecx, &failed_allocation); 547 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
560 // Set the value. 548 // Set the value.
549 __ mov(eax, ecx);
561 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 550 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
562 __ ret(0); 551 __ ret(0);
563 } else if (array_type == kExternalFloatArray) { 552 } else if (array_type == kExternalFloatArray) {
564 // For the floating-point array type, we need to always allocate a 553 // For the floating-point array type, we need to always allocate a
565 // HeapNumber. 554 // HeapNumber.
566 __ AllocateHeapNumber(eax, ebx, ecx, &failed_allocation); 555 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
567 // Set the value. 556 // Set the value.
557 __ mov(eax, ecx);
568 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 558 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
569 __ ret(0); 559 __ ret(0);
570 } else { 560 } else {
571 __ shl(eax, kSmiTagSize); 561 __ mov(eax, ecx);
562 __ SmiTag(eax);
572 __ ret(0); 563 __ ret(0);
573 } 564 }
574 565
575 // If we fail allocation of the HeapNumber, we still have a value on 566 // If we fail allocation of the HeapNumber, we still have a value on
576 // top of the FPU stack. Remove it. 567 // top of the FPU stack. Remove it.
577 __ bind(&failed_allocation); 568 __ bind(&failed_allocation);
578 __ ffree(); 569 __ ffree();
579 __ fincstp(); 570 __ fincstp();
580 // Fall through to slow case. 571 // Fall through to slow case.
581 572
582 // Slow case: Load name and receiver from stack and jump to runtime. 573 // Slow case: Load key and receiver from stack and jump to runtime.
583 __ bind(&slow); 574 __ bind(&slow);
584 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); 575 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
585 GenerateRuntimeGetProperty(masm); 576 GenerateRuntimeGetProperty(masm);
586 } 577 }
587 578
588 579
589 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 580 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
590 // ----------- S t a t e ------------- 581 // ----------- S t a t e -------------
591 // -- eax : value 582 // -- eax : key
583 // -- edx : receiver
592 // -- esp[0] : return address 584 // -- esp[0] : return address
593 // -- esp[4] : key
594 // -- esp[8] : receiver
595 // ----------------------------------- 585 // -----------------------------------
596 Label slow; 586 Label slow;
597 587
598 // Load key and receiver.
599 __ mov(eax, Operand(esp, kPointerSize));
600 __ mov(ecx, Operand(esp, 2 * kPointerSize));
601
602 // Check that the receiver isn't a smi. 588 // Check that the receiver isn't a smi.
603 __ test(ecx, Immediate(kSmiTagMask)); 589 __ test(edx, Immediate(kSmiTagMask));
604 __ j(zero, &slow, not_taken); 590 __ j(zero, &slow, not_taken);
605 591
606 // Check that the key is a smi. 592 // Check that the key is a smi.
607 __ test(eax, Immediate(kSmiTagMask)); 593 __ test(eax, Immediate(kSmiTagMask));
608 __ j(not_zero, &slow, not_taken); 594 __ j(not_zero, &slow, not_taken);
609 595
610 // Get the map of the receiver. 596 // Get the map of the receiver.
611 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset)); 597 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
612 598
613 // Check that it has indexed interceptor and access checks 599 // Check that it has indexed interceptor and access checks
614 // are not enabled for this object. 600 // are not enabled for this object.
615 __ movzx_b(edx, FieldOperand(edx, Map::kBitFieldOffset)); 601 __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
616 __ and_(Operand(edx), Immediate(kSlowCaseBitFieldMask)); 602 __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask));
617 __ cmp(Operand(edx), Immediate(1 << Map::kHasIndexedInterceptor)); 603 __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor));
618 __ j(not_zero, &slow, not_taken); 604 __ j(not_zero, &slow, not_taken);
619 605
620 // Everything is fine, call runtime. 606 // Everything is fine, call runtime.
621 __ pop(edx); 607 __ pop(ecx);
622 __ push(ecx); // receiver 608 __ push(edx); // receiver
623 __ push(eax); // key 609 __ push(eax); // key
624 __ push(edx); // return address 610 __ push(ecx); // return address
625 611
626 // Perform tail call to the entry. 612 // Perform tail call to the entry.
627 __ TailCallRuntime(ExternalReference( 613 __ TailCallRuntime(ExternalReference(
628 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); 614 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1);
629 615
630 __ bind(&slow); 616 __ bind(&slow);
631 GenerateMiss(masm); 617 GenerateMiss(masm);
632 } 618 }
633 619
634 620
(...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after
1373 return PatchInlinedMapCheck(address, map); 1359 return PatchInlinedMapCheck(address, map);
1374 } 1360 }
1375 1361
1376 1362
1377 // Defined in ic.cc. 1363 // Defined in ic.cc.
1378 Object* KeyedLoadIC_Miss(Arguments args); 1364 Object* KeyedLoadIC_Miss(Arguments args);
1379 1365
1380 1366
1381 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 1367 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
1382 // ----------- S t a t e ------------- 1368 // ----------- S t a t e -------------
1369 // -- eax : key
1370 // -- edx : receiver
1383 // -- esp[0] : return address 1371 // -- esp[0] : return address
1384 // -- esp[4] : name
1385 // -- esp[8] : receiver
1386 // ----------------------------------- 1372 // -----------------------------------
1387 1373
1388 __ pop(ebx); 1374 __ pop(ebx);
1389 __ push(Operand(esp, kPointerSize)); // receiver 1375 __ push(edx); // receiver
1390 __ push(Operand(esp, kPointerSize)); // name 1376 __ push(eax); // name
1391 __ push(ebx); // return address 1377 __ push(ebx); // return address
1392 1378
1393 // Perform tail call to the entry. 1379 // Perform tail call to the entry.
1394 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedLoadIC_Miss)), 2, 1); 1380 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedLoadIC_Miss)), 2, 1);
1395 } 1381 }
1396 1382
1397 1383
1398 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 1384 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
1399 // ----------- S t a t e ------------- 1385 // ----------- S t a t e -------------
1386 // -- eax : key
1387 // -- edx : receiver
1400 // -- esp[0] : return address 1388 // -- esp[0] : return address
1401 // -- esp[4] : name
1402 // -- esp[8] : receiver
1403 // ----------------------------------- 1389 // -----------------------------------
1404 1390
1405 __ pop(ebx); 1391 __ pop(ebx);
1406 __ push(Operand(esp, 1 * kPointerSize)); // receiver 1392 __ push(edx); // receiver
1407 __ push(Operand(esp, 1 * kPointerSize)); // name 1393 __ push(eax); // name
1408 __ push(ebx); // return address 1394 __ push(ebx); // return address
1409 1395
1410 // Perform tail call to the entry. 1396 // Perform tail call to the entry.
1411 __ TailCallRuntime(ExternalReference(Runtime::kKeyedGetProperty), 2, 1); 1397 __ TailCallRuntime(ExternalReference(Runtime::kKeyedGetProperty), 2, 1);
1412 } 1398 }
1413 1399
1414 1400
1415 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 1401 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
1416 // ----------- S t a t e ------------- 1402 // ----------- S t a t e -------------
1417 // -- eax : value 1403 // -- eax : value
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1486 __ push(ecx); 1472 __ push(ecx);
1487 1473
1488 // Do tail-call to runtime routine. 1474 // Do tail-call to runtime routine.
1489 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedStoreIC_Miss)), 3, 1); 1475 __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedStoreIC_Miss)), 3, 1);
1490 } 1476 }
1491 1477
1492 #undef __ 1478 #undef __
1493 1479
1494 1480
1495 } } // namespace v8::internal 1481 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698