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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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/lithium-codegen-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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 Register r0, 65 Register r0,
66 Register r1, 66 Register r1,
67 Label* miss) { 67 Label* miss) {
68 // Register usage: 68 // Register usage:
69 // receiver: holds the receiver on entry and is unchanged. 69 // receiver: holds the receiver on entry and is unchanged.
70 // r0: used to hold receiver instance type. 70 // r0: used to hold receiver instance type.
71 // Holds the property dictionary on fall through. 71 // Holds the property dictionary on fall through.
72 // r1: used to hold receivers map. 72 // r1: used to hold receivers map.
73 73
74 // Check that the receiver isn't a smi. 74 // Check that the receiver isn't a smi.
75 __ test(receiver, Immediate(kSmiTagMask)); 75 __ JumpIfSmi(receiver, miss);
76 __ j(zero, miss);
77 76
78 // Check that the receiver is a valid JS object. 77 // Check that the receiver is a valid JS object.
79 __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); 78 __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset));
80 __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); 79 __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset));
81 __ cmp(r0, FIRST_JS_OBJECT_TYPE); 80 __ cmp(r0, FIRST_SPEC_OBJECT_TYPE);
82 __ j(below, miss); 81 __ j(below, miss);
83 82
84 // If this assert fails, we have to check upper bound too. 83 // If this assert fails, we have to check upper bound too.
85 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 84 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
86 85
87 GenerateGlobalInstanceTypeCheck(masm, r0, miss); 86 GenerateGlobalInstanceTypeCheck(masm, r0, miss);
88 87
89 // Check for non-global object that requires access check. 88 // Check for non-global object that requires access check.
90 __ test_b(FieldOperand(r1, Map::kBitFieldOffset), 89 __ test_b(FieldOperand(r1, Map::kBitFieldOffset),
91 (1 << Map::kIsAccessCheckNeeded) | 90 (1 << Map::kIsAccessCheckNeeded) |
92 (1 << Map::kHasNamedInterceptor)); 91 (1 << Map::kHasNamedInterceptor));
93 __ j(not_zero, miss); 92 __ j(not_zero, miss);
94 93
95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); 94 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset));
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 const int kValueOffset = kElementsStartOffset + kPointerSize; 209 const int kValueOffset = kElementsStartOffset + kPointerSize;
211 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); 210 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag));
212 __ mov(Operand(r0, 0), value); 211 __ mov(Operand(r0, 0), value);
213 212
214 // Update write barrier. Make sure not to clobber the value. 213 // Update write barrier. Make sure not to clobber the value.
215 __ mov(r1, value); 214 __ mov(r1, value);
216 __ RecordWrite(elements, r0, r1, kDontSaveFPRegs); 215 __ RecordWrite(elements, r0, r1, kDontSaveFPRegs);
217 } 216 }
218 217
219 218
220 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
221 Label* miss,
222 Register elements,
223 Register key,
224 Register r0,
225 Register r1,
226 Register r2,
227 Register result) {
228 // Register use:
229 //
230 // elements - holds the slow-case elements of the receiver and is unchanged.
231 //
232 // key - holds the smi key on entry and is unchanged.
233 //
234 // Scratch registers:
235 //
236 // r0 - holds the untagged key on entry and holds the hash once computed.
237 //
238 // r1 - used to hold the capacity mask of the dictionary
239 //
240 // r2 - used for the index into the dictionary.
241 //
242 // result - holds the result on exit if the load succeeds and we fall through.
243
244 Label done;
245
246 // Compute the hash code from the untagged key. This must be kept in sync
247 // with ComputeIntegerHash in utils.h.
248 //
249 // hash = ~hash + (hash << 15);
250 __ mov(r1, r0);
251 __ not_(r0);
252 __ shl(r1, 15);
253 __ add(r0, Operand(r1));
254 // hash = hash ^ (hash >> 12);
255 __ mov(r1, r0);
256 __ shr(r1, 12);
257 __ xor_(r0, Operand(r1));
258 // hash = hash + (hash << 2);
259 __ lea(r0, Operand(r0, r0, times_4, 0));
260 // hash = hash ^ (hash >> 4);
261 __ mov(r1, r0);
262 __ shr(r1, 4);
263 __ xor_(r0, Operand(r1));
264 // hash = hash * 2057;
265 __ imul(r0, r0, 2057);
266 // hash = hash ^ (hash >> 16);
267 __ mov(r1, r0);
268 __ shr(r1, 16);
269 __ xor_(r0, Operand(r1));
270
271 // Compute capacity mask.
272 __ mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset));
273 __ shr(r1, kSmiTagSize); // convert smi to int
274 __ dec(r1);
275
276 // Generate an unrolled loop that performs a few probes before giving up.
277 const int kProbes = 4;
278 for (int i = 0; i < kProbes; i++) {
279 // Use r2 for index calculations and keep the hash intact in r0.
280 __ mov(r2, r0);
281 // Compute the masked index: (hash + i + i * i) & mask.
282 if (i > 0) {
283 __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i)));
284 }
285 __ and_(r2, Operand(r1));
286
287 // Scale the index by multiplying by the entry size.
288 ASSERT(NumberDictionary::kEntrySize == 3);
289 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3
290
291 // Check if the key matches.
292 __ cmp(key, FieldOperand(elements,
293 r2,
294 times_pointer_size,
295 NumberDictionary::kElementsStartOffset));
296 if (i != (kProbes - 1)) {
297 __ j(equal, &done);
298 } else {
299 __ j(not_equal, miss);
300 }
301 }
302
303 __ bind(&done);
304 // Check that the value is a normal propety.
305 const int kDetailsOffset =
306 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
307 ASSERT_EQ(NORMAL, 0);
308 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
309 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
310 __ j(not_zero, miss);
311
312 // Get the value at the masked, scaled index.
313 const int kValueOffset =
314 NumberDictionary::kElementsStartOffset + kPointerSize;
315 __ mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
316 }
317
318
319 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { 219 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
320 // ----------- S t a t e ------------- 220 // ----------- S t a t e -------------
321 // -- eax : receiver 221 // -- eax : receiver
322 // -- ecx : name 222 // -- ecx : name
323 // -- esp[0] : return address 223 // -- esp[0] : return address
324 // ----------------------------------- 224 // -----------------------------------
325 Label miss; 225 Label miss;
326 226
327 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); 227 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
328 __ bind(&miss); 228 __ bind(&miss);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 Register receiver, 266 Register receiver,
367 Register map, 267 Register map,
368 int interceptor_bit, 268 int interceptor_bit,
369 Label* slow) { 269 Label* slow) {
370 // Register use: 270 // Register use:
371 // receiver - holds the receiver and is unchanged. 271 // receiver - holds the receiver and is unchanged.
372 // Scratch registers: 272 // Scratch registers:
373 // map - used to hold the map of the receiver. 273 // map - used to hold the map of the receiver.
374 274
375 // Check that the object isn't a smi. 275 // Check that the object isn't a smi.
376 __ test(receiver, Immediate(kSmiTagMask)); 276 __ JumpIfSmi(receiver, slow);
377 __ j(zero, slow);
378 277
379 // Get the map of the receiver. 278 // Get the map of the receiver.
380 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); 279 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset));
381 280
382 // Check bit field. 281 // Check bit field.
383 __ test_b(FieldOperand(map, Map::kBitFieldOffset), 282 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
384 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); 283 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit));
385 __ j(not_zero, slow); 284 __ j(not_zero, slow);
386 // Check that the object is some kind of JS object EXCEPT JS Value type. 285 // Check that the object is some kind of JS object EXCEPT JS Value type.
387 // In the case that the object is a value-wrapper object, 286 // In the case that the object is a value-wrapper object,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); 357 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
459 __ j(zero, index_string); 358 __ j(zero, index_string);
460 359
461 // Is the string a symbol? 360 // Is the string a symbol?
462 ASSERT(kSymbolTag != 0); 361 ASSERT(kSymbolTag != 0);
463 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); 362 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
464 __ j(zero, not_symbol); 363 __ j(zero, not_symbol);
465 } 364 }
466 365
467 366
367 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm,
368 Register object,
369 Register key,
370 Register scratch1,
371 Register scratch2,
372 Label* unmapped_case,
373 Label* slow_case) {
374 Heap* heap = masm->isolate()->heap();
375 Factory* factory = masm->isolate()->factory();
376
377 // Check that the receiver is a JSObject. Because of the elements
378 // map check later, we do not need to check for interceptors or
379 // whether it requires access checks.
380 __ JumpIfSmi(object, slow_case);
381 // Check that the object is some kind of JSObject.
382 __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1);
383 __ j(below, slow_case);
384
385 // Check that the key is a positive smi.
386 __ test(key, Immediate(0x8000001));
387 __ j(not_zero, slow_case);
388
389 // Load the elements into scratch1 and check its map.
390 Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
391 __ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset));
392 __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
393
394 // Check if element is in the range of mapped arguments. If not, jump
395 // to the unmapped lookup with the parameter map in scratch1.
396 __ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset));
397 __ sub(Operand(scratch2), Immediate(Smi::FromInt(2)));
398 __ cmp(key, Operand(scratch2));
399 __ j(greater_equal, unmapped_case);
400
401 // Load element index and check whether it is the hole.
402 const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize;
403 __ mov(scratch2, FieldOperand(scratch1,
404 key,
405 times_half_pointer_size,
406 kHeaderSize));
407 __ cmp(scratch2, factory->the_hole_value());
408 __ j(equal, unmapped_case);
409
410 // Load value from context and return it. We can reuse scratch1 because
411 // we do not jump to the unmapped lookup (which requires the parameter
412 // map in scratch1).
413 const int kContextOffset = FixedArray::kHeaderSize;
414 __ mov(scratch1, FieldOperand(scratch1, kContextOffset));
415 return FieldOperand(scratch1,
416 scratch2,
417 times_half_pointer_size,
418 Context::kHeaderSize);
419 }
420
421
422 static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
423 Register key,
424 Register parameter_map,
425 Register scratch,
426 Label* slow_case) {
427 // Element is in arguments backing store, which is referenced by the
428 // second element of the parameter_map.
429 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
430 Register backing_store = parameter_map;
431 __ mov(backing_store, FieldOperand(parameter_map, kBackingStoreOffset));
432 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
433 __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK);
434 __ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset));
435 __ cmp(key, Operand(scratch));
436 __ j(greater_equal, slow_case);
437 return FieldOperand(backing_store,
438 key,
439 times_half_pointer_size,
440 FixedArray::kHeaderSize);
441 }
442
443
468 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 444 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
469 // ----------- S t a t e ------------- 445 // ----------- S t a t e -------------
470 // -- eax : key 446 // -- eax : key
471 // -- edx : receiver 447 // -- edx : receiver
472 // -- esp[0] : return address 448 // -- esp[0] : return address
473 // ----------------------------------- 449 // -----------------------------------
474 Label slow, check_string, index_smi, index_string, property_array_property; 450 Label slow, check_string, index_smi, index_string, property_array_property;
475 Label probe_dictionary, check_number_dictionary; 451 Label probe_dictionary, check_number_dictionary;
476 452
477 // Check that the key is a smi. 453 // Check that the key is a smi.
478 __ test(eax, Immediate(kSmiTagMask)); 454 __ JumpIfNotSmi(eax, &check_string);
479 __ j(not_zero, &check_string);
480 __ bind(&index_smi); 455 __ bind(&index_smi);
481 // Now the key is known to be a smi. This place is also jumped to from 456 // Now the key is known to be a smi. This place is also jumped to from
482 // where a numeric string is converted to a smi. 457 // where a numeric string is converted to a smi.
483 458
484 GenerateKeyedLoadReceiverCheck( 459 GenerateKeyedLoadReceiverCheck(
485 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); 460 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow);
486 461
487 // Check the "has fast elements" bit in the receiver's map which is 462 // Check the receiver's map to see if it has fast elements.
488 // now in ecx. 463 __ CheckFastElements(ecx, &check_number_dictionary);
489 __ test_b(FieldOperand(ecx, Map::kBitField2Offset),
490 1 << Map::kHasFastElements);
491 __ j(zero, &check_number_dictionary);
492 464
493 GenerateFastArrayLoad(masm, 465 GenerateFastArrayLoad(masm,
494 edx, 466 edx,
495 eax, 467 eax,
496 ecx, 468 ecx,
497 eax, 469 eax,
498 NULL, 470 NULL,
499 &slow); 471 &slow);
500 Isolate* isolate = masm->isolate(); 472 Isolate* isolate = masm->isolate();
501 Counters* counters = isolate->counters(); 473 Counters* counters = isolate->counters();
(...skipping 11 matching lines...) Expand all
513 // eax: key 485 // eax: key
514 // ecx: elements 486 // ecx: elements
515 __ CheckMap(ecx, 487 __ CheckMap(ecx,
516 isolate->factory()->hash_table_map(), 488 isolate->factory()->hash_table_map(),
517 &slow, 489 &slow,
518 DONT_DO_SMI_CHECK); 490 DONT_DO_SMI_CHECK);
519 Label slow_pop_receiver; 491 Label slow_pop_receiver;
520 // Push receiver on the stack to free up a register for the dictionary 492 // Push receiver on the stack to free up a register for the dictionary
521 // probing. 493 // probing.
522 __ push(edx); 494 __ push(edx);
523 GenerateNumberDictionaryLoad(masm, 495 __ LoadFromNumberDictionary(&slow_pop_receiver,
524 &slow_pop_receiver, 496 ecx,
525 ecx, 497 eax,
526 eax, 498 ebx,
527 ebx, 499 edx,
528 edx, 500 edi,
529 edi, 501 eax);
530 eax);
531 // Pop receiver before returning. 502 // Pop receiver before returning.
532 __ pop(edx); 503 __ pop(edx);
533 __ ret(0); 504 __ ret(0);
534 505
535 __ bind(&slow_pop_receiver); 506 __ bind(&slow_pop_receiver);
536 // Pop the receiver from the stack and jump to runtime. 507 // Pop the receiver from the stack and jump to runtime.
537 __ pop(edx); 508 __ pop(edx);
538 509
539 __ bind(&slow); 510 __ bind(&slow);
540 // Slow case: jump to runtime. 511 // Slow case: jump to runtime.
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 632
662 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 633 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
663 // ----------- S t a t e ------------- 634 // ----------- S t a t e -------------
664 // -- eax : key 635 // -- eax : key
665 // -- edx : receiver 636 // -- edx : receiver
666 // -- esp[0] : return address 637 // -- esp[0] : return address
667 // ----------------------------------- 638 // -----------------------------------
668 Label slow; 639 Label slow;
669 640
670 // Check that the receiver isn't a smi. 641 // Check that the receiver isn't a smi.
671 __ test(edx, Immediate(kSmiTagMask)); 642 __ JumpIfSmi(edx, &slow);
672 __ j(zero, &slow);
673 643
674 // Check that the key is an array index, that is Uint32. 644 // Check that the key is an array index, that is Uint32.
675 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask)); 645 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask));
676 __ j(not_zero, &slow); 646 __ j(not_zero, &slow);
677 647
678 // Get the map of the receiver. 648 // Get the map of the receiver.
679 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 649 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
680 650
681 // Check that it has indexed interceptor and access checks 651 // Check that it has indexed interceptor and access checks
682 // are not enabled for this object. 652 // are not enabled for this object.
(...skipping 12 matching lines...) Expand all
695 ExternalReference ref = 665 ExternalReference ref =
696 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), 666 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
697 masm->isolate()); 667 masm->isolate());
698 __ TailCallExternalReference(ref, 2, 1); 668 __ TailCallExternalReference(ref, 2, 1);
699 669
700 __ bind(&slow); 670 __ bind(&slow);
701 GenerateMiss(masm, false); 671 GenerateMiss(masm, false);
702 } 672 }
703 673
704 674
675 void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
676 // ----------- S t a t e -------------
677 // -- eax : key
678 // -- edx : receiver
679 // -- esp[0] : return address
680 // -----------------------------------
681 Label slow, notin;
682 Factory* factory = masm->isolate()->factory();
683 Operand mapped_location =
684 GenerateMappedArgumentsLookup(masm, edx, eax, ebx, ecx, &notin, &slow);
685 __ mov(eax, mapped_location);
686 __ Ret();
687 __ bind(&notin);
688 // The unmapped lookup expects that the parameter map is in ebx.
689 Operand unmapped_location =
690 GenerateUnmappedArgumentsLookup(masm, eax, ebx, ecx, &slow);
691 __ cmp(unmapped_location, factory->the_hole_value());
692 __ j(equal, &slow);
693 __ mov(eax, unmapped_location);
694 __ Ret();
695 __ bind(&slow);
696 GenerateMiss(masm, false);
697 }
698
699
700 void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
701 // ----------- S t a t e -------------
702 // -- eax : value
703 // -- ecx : key
704 // -- edx : receiver
705 // -- esp[0] : return address
706 // -----------------------------------
707 Label slow, notin;
708 Operand mapped_location =
709 GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, edi, &notin, &slow);
710 __ mov(mapped_location, eax);
711 __ lea(ecx, mapped_location);
712 __ mov(edx, eax);
713 __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs);
714 __ Ret();
715 __ bind(&notin);
716 // The unmapped lookup expects that the parameter map is in ebx.
717 Operand unmapped_location =
718 GenerateUnmappedArgumentsLookup(masm, ecx, ebx, edi, &slow);
719 __ mov(unmapped_location, eax);
720 __ lea(edi, unmapped_location);
721 __ mov(edx, eax);
722 __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs);
723 __ Ret();
724 __ bind(&slow);
725 GenerateMiss(masm, false);
726 }
727
728
705 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 729 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
706 StrictModeFlag strict_mode) { 730 StrictModeFlag strict_mode) {
707 // ----------- S t a t e ------------- 731 // ----------- S t a t e -------------
708 // -- eax : value 732 // -- eax : value
709 // -- ecx : key 733 // -- ecx : key
710 // -- edx : receiver 734 // -- edx : receiver
711 // -- esp[0] : return address 735 // -- esp[0] : return address
712 // ----------------------------------- 736 // -----------------------------------
713 Label slow, fast, array, extra; 737 Label slow, fast, array, extra;
714 738
715 // Check that the object isn't a smi. 739 // Check that the object isn't a smi.
716 __ test(edx, Immediate(kSmiTagMask)); 740 __ JumpIfSmi(edx, &slow);
717 __ j(zero, &slow);
718 // Get the map from the receiver. 741 // Get the map from the receiver.
719 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 742 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
720 // Check that the receiver does not require access checks. We need 743 // Check that the receiver does not require access checks. We need
721 // to do this because this generic stub does not perform map checks. 744 // to do this because this generic stub does not perform map checks.
722 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), 745 __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
723 1 << Map::kIsAccessCheckNeeded); 746 1 << Map::kIsAccessCheckNeeded);
724 __ j(not_zero, &slow); 747 __ j(not_zero, &slow);
725 // Check that the key is a smi. 748 // Check that the key is a smi.
726 __ test(ecx, Immediate(kSmiTagMask)); 749 __ JumpIfNotSmi(ecx, &slow);
727 __ j(not_zero, &slow);
728 __ CmpInstanceType(edi, JS_ARRAY_TYPE); 750 __ CmpInstanceType(edi, JS_ARRAY_TYPE);
729 __ j(equal, &array); 751 __ j(equal, &array);
730 // Check that the object is some kind of JS object. 752 // Check that the object is some kind of JSObject.
731 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); 753 __ CmpInstanceType(edi, FIRST_JS_RECEIVER_TYPE);
732 __ j(below, &slow); 754 __ j(below, &slow);
755 __ CmpInstanceType(edi, JS_PROXY_TYPE);
756 __ j(equal, &slow);
757 __ CmpInstanceType(edi, JS_FUNCTION_PROXY_TYPE);
758 __ j(equal, &slow);
733 759
734 // Object case: Check key against length in the elements array. 760 // Object case: Check key against length in the elements array.
735 // eax: value 761 // eax: value
736 // edx: JSObject 762 // edx: JSObject
737 // ecx: key (a smi) 763 // ecx: key (a smi)
738 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 764 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
739 // Check that the object is in fast mode and writable. 765 // Check that the object is in fast mode and writable.
740 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK); 766 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK);
741 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); 767 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
742 __ j(below, &fast); 768 __ j(below, &fast);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 argc); 840 argc);
815 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, 841 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx,
816 eax); 842 eax);
817 843
818 // If the stub cache probing failed, the receiver might be a value. 844 // If the stub cache probing failed, the receiver might be a value.
819 // For value objects, we use the map of the prototype objects for 845 // For value objects, we use the map of the prototype objects for
820 // the corresponding JSValue for the cache and that is what we need 846 // the corresponding JSValue for the cache and that is what we need
821 // to probe. 847 // to probe.
822 // 848 //
823 // Check for number. 849 // Check for number.
824 __ test(edx, Immediate(kSmiTagMask)); 850 __ JumpIfSmi(edx, &number);
825 __ j(zero, &number);
826 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); 851 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx);
827 __ j(not_equal, &non_number); 852 __ j(not_equal, &non_number);
828 __ bind(&number); 853 __ bind(&number);
829 StubCompiler::GenerateLoadGlobalFunctionPrototype( 854 StubCompiler::GenerateLoadGlobalFunctionPrototype(
830 masm, Context::NUMBER_FUNCTION_INDEX, edx); 855 masm, Context::NUMBER_FUNCTION_INDEX, edx);
831 __ jmp(&probe); 856 __ jmp(&probe);
832 857
833 // Check for string. 858 // Check for string.
834 __ bind(&non_number); 859 __ bind(&non_number);
835 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); 860 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE);
(...skipping 26 matching lines...) Expand all
862 // ----------- S t a t e ------------- 887 // ----------- S t a t e -------------
863 // -- ecx : name 888 // -- ecx : name
864 // -- edi : function 889 // -- edi : function
865 // -- esp[0] : return address 890 // -- esp[0] : return address
866 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 891 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
867 // -- ... 892 // -- ...
868 // -- esp[(argc + 1) * 4] : receiver 893 // -- esp[(argc + 1) * 4] : receiver
869 // ----------------------------------- 894 // -----------------------------------
870 895
871 // Check that the result is not a smi. 896 // Check that the result is not a smi.
872 __ test(edi, Immediate(kSmiTagMask)); 897 __ JumpIfSmi(edi, miss);
873 __ j(zero, miss);
874 898
875 // Check that the value is a JavaScript function, fetching its map into eax. 899 // Check that the value is a JavaScript function, fetching its map into eax.
876 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 900 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
877 __ j(not_equal, miss); 901 __ j(not_equal, miss);
878 902
879 // Invoke the function. 903 // Invoke the function.
880 ParameterCount actual(argc); 904 ParameterCount actual(argc);
881 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 905 __ InvokeFunction(edi, actual, JUMP_FUNCTION,
906 NullCallWrapper(), CALL_AS_METHOD);
882 } 907 }
883 908
884 // The generated code falls through if the call should be handled by runtime. 909 // The generated code falls through if the call should be handled by runtime.
885 static void GenerateCallNormal(MacroAssembler* masm, int argc) { 910 static void GenerateCallNormal(MacroAssembler* masm, int argc) {
886 // ----------- S t a t e ------------- 911 // ----------- S t a t e -------------
887 // -- ecx : name 912 // -- ecx : name
888 // -- esp[0] : return address 913 // -- esp[0] : return address
889 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 914 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
890 // -- ... 915 // -- ...
891 // -- esp[(argc + 1) * 4] : receiver 916 // -- esp[(argc + 1) * 4] : receiver
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 968
944 // Move result to edi and exit the internal frame. 969 // Move result to edi and exit the internal frame.
945 __ mov(edi, eax); 970 __ mov(edi, eax);
946 __ LeaveInternalFrame(); 971 __ LeaveInternalFrame();
947 972
948 // Check if the receiver is a global object of some sort. 973 // Check if the receiver is a global object of some sort.
949 // This can happen only for regular CallIC but not KeyedCallIC. 974 // This can happen only for regular CallIC but not KeyedCallIC.
950 if (id == IC::kCallIC_Miss) { 975 if (id == IC::kCallIC_Miss) {
951 Label invoke, global; 976 Label invoke, global;
952 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver 977 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver
953 __ test(edx, Immediate(kSmiTagMask)); 978 __ JumpIfSmi(edx, &invoke, Label::kNear);
954 __ j(zero, &invoke, Label::kNear);
955 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 979 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
956 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); 980 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
957 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); 981 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE);
958 __ j(equal, &global, Label::kNear); 982 __ j(equal, &global, Label::kNear);
959 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); 983 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE);
960 __ j(not_equal, &invoke, Label::kNear); 984 __ j(not_equal, &invoke, Label::kNear);
961 985
962 // Patch the receiver on the stack. 986 // Patch the receiver on the stack.
963 __ bind(&global); 987 __ bind(&global);
964 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 988 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 // ----------------------------------- 1061 // -----------------------------------
1038 1062
1039 // Get the receiver of the function from the stack; 1 ~ return address. 1063 // Get the receiver of the function from the stack; 1 ~ return address.
1040 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1064 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1041 1065
1042 Label do_call, slow_call, slow_load, slow_reload_receiver; 1066 Label do_call, slow_call, slow_load, slow_reload_receiver;
1043 Label check_number_dictionary, check_string, lookup_monomorphic_cache; 1067 Label check_number_dictionary, check_string, lookup_monomorphic_cache;
1044 Label index_smi, index_string; 1068 Label index_smi, index_string;
1045 1069
1046 // Check that the key is a smi. 1070 // Check that the key is a smi.
1047 __ test(ecx, Immediate(kSmiTagMask)); 1071 __ JumpIfNotSmi(ecx, &check_string);
1048 __ j(not_zero, &check_string);
1049 1072
1050 __ bind(&index_smi); 1073 __ bind(&index_smi);
1051 // Now the key is known to be a smi. This place is also jumped to from 1074 // Now the key is known to be a smi. This place is also jumped to from
1052 // where a numeric string is converted to a smi. 1075 // where a numeric string is converted to a smi.
1053 1076
1054 GenerateKeyedLoadReceiverCheck( 1077 GenerateKeyedLoadReceiverCheck(
1055 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); 1078 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call);
1056 1079
1057 GenerateFastArrayLoad( 1080 GenerateFastArrayLoad(
1058 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); 1081 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
(...skipping 12 matching lines...) Expand all
1071 // ecx: smi key 1094 // ecx: smi key
1072 // Check whether the elements is a number dictionary. 1095 // Check whether the elements is a number dictionary.
1073 __ CheckMap(eax, 1096 __ CheckMap(eax,
1074 isolate->factory()->hash_table_map(), 1097 isolate->factory()->hash_table_map(),
1075 &slow_load, 1098 &slow_load,
1076 DONT_DO_SMI_CHECK); 1099 DONT_DO_SMI_CHECK);
1077 __ mov(ebx, ecx); 1100 __ mov(ebx, ecx);
1078 __ SmiUntag(ebx); 1101 __ SmiUntag(ebx);
1079 // ebx: untagged index 1102 // ebx: untagged index
1080 // Receiver in edx will be clobbered, need to reload it on miss. 1103 // Receiver in edx will be clobbered, need to reload it on miss.
1081 GenerateNumberDictionaryLoad( 1104 __ LoadFromNumberDictionary(
1082 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); 1105 &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
1083 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1); 1106 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1);
1084 __ jmp(&do_call); 1107 __ jmp(&do_call);
1085 1108
1086 __ bind(&slow_reload_receiver); 1109 __ bind(&slow_reload_receiver);
1087 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1110 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1088 1111
1089 __ bind(&slow_load); 1112 __ bind(&slow_load);
1090 // This branch is taken when calling KeyedCallIC_Miss is neither required 1113 // This branch is taken when calling KeyedCallIC_Miss is neither required
1091 // nor beneficial. 1114 // nor beneficial.
1092 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1); 1115 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 __ IncrementCounter(counters->keyed_call_generic_slow(), 1); 1161 __ IncrementCounter(counters->keyed_call_generic_slow(), 1);
1139 GenerateMiss(masm, argc); 1162 GenerateMiss(masm, argc);
1140 1163
1141 __ bind(&index_string); 1164 __ bind(&index_string);
1142 __ IndexFromHash(ebx, ecx); 1165 __ IndexFromHash(ebx, ecx);
1143 // Now jump to the place where smi keys are handled. 1166 // Now jump to the place where smi keys are handled.
1144 __ jmp(&index_smi); 1167 __ jmp(&index_smi);
1145 } 1168 }
1146 1169
1147 1170
1171 void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
1172 int argc) {
1173 // ----------- S t a t e -------------
1174 // -- ecx : name
1175 // -- esp[0] : return address
1176 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1177 // -- ...
1178 // -- esp[(argc + 1) * 4] : receiver
1179 // -----------------------------------
1180 Label slow, notin;
1181 Factory* factory = masm->isolate()->factory();
1182 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1183 Operand mapped_location =
1184 GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, &notin, &slow);
1185 __ mov(edi, mapped_location);
1186 GenerateFunctionTailCall(masm, argc, &slow);
1187 __ bind(&notin);
1188 // The unmapped lookup expects that the parameter map is in ebx.
1189 Operand unmapped_location =
1190 GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow);
1191 __ cmp(unmapped_location, factory->the_hole_value());
1192 __ j(equal, &slow);
1193 __ mov(edi, unmapped_location);
1194 GenerateFunctionTailCall(masm, argc, &slow);
1195 __ bind(&slow);
1196 GenerateMiss(masm, argc);
1197 }
1198
1199
1148 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1200 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
1149 // ----------- S t a t e ------------- 1201 // ----------- S t a t e -------------
1150 // -- ecx : name 1202 // -- ecx : name
1151 // -- esp[0] : return address 1203 // -- esp[0] : return address
1152 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1204 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1153 // -- ... 1205 // -- ...
1154 // -- esp[(argc + 1) * 4] : receiver 1206 // -- esp[(argc + 1) * 4] : receiver
1155 // ----------------------------------- 1207 // -----------------------------------
1156 1208
1157 // Check if the name is a string. 1209 // Check if the name is a string.
1158 Label miss; 1210 Label miss;
1159 __ test(ecx, Immediate(kSmiTagMask)); 1211 __ JumpIfSmi(ecx, &miss);
1160 __ j(zero, &miss);
1161 Condition cond = masm->IsObjectStringType(ecx, eax, eax); 1212 Condition cond = masm->IsObjectStringType(ecx, eax, eax);
1162 __ j(NegateCondition(cond), &miss); 1213 __ j(NegateCondition(cond), &miss);
1163 GenerateCallNormal(masm, argc); 1214 GenerateCallNormal(masm, argc);
1164 __ bind(&miss); 1215 __ bind(&miss);
1165 GenerateMiss(masm, argc); 1216 GenerateMiss(masm, argc);
1166 } 1217 }
1167 1218
1168 1219
1169 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1220 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1170 // ----------- S t a t e ------------- 1221 // ----------- S t a t e -------------
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1335 // elements of FixedArray type.), but currently is restricted to JSArray. 1386 // elements of FixedArray type.), but currently is restricted to JSArray.
1336 // Value must be a number, but only smis are accepted as the most common case. 1387 // Value must be a number, but only smis are accepted as the most common case.
1337 1388
1338 Label miss; 1389 Label miss;
1339 1390
1340 Register receiver = edx; 1391 Register receiver = edx;
1341 Register value = eax; 1392 Register value = eax;
1342 Register scratch = ebx; 1393 Register scratch = ebx;
1343 1394
1344 // Check that the receiver isn't a smi. 1395 // Check that the receiver isn't a smi.
1345 __ test(receiver, Immediate(kSmiTagMask)); 1396 __ JumpIfSmi(receiver, &miss);
1346 __ j(zero, &miss);
1347 1397
1348 // Check that the object is a JS array. 1398 // Check that the object is a JS array.
1349 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 1399 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
1350 __ j(not_equal, &miss); 1400 __ j(not_equal, &miss);
1351 1401
1352 // Check that elements are FixedArray. 1402 // Check that elements are FixedArray.
1353 // We rely on StoreIC_ArrayLength below to deal with all types of 1403 // We rely on StoreIC_ArrayLength below to deal with all types of
1354 // fast elements (including COW). 1404 // fast elements (including COW).
1355 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); 1405 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
1356 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); 1406 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
1357 __ j(not_equal, &miss); 1407 __ j(not_equal, &miss);
1358 1408
1359 // Check that value is a smi. 1409 // Check that value is a smi.
1360 __ test(value, Immediate(kSmiTagMask)); 1410 __ JumpIfNotSmi(value, &miss);
1361 __ j(not_zero, &miss);
1362 1411
1363 // Prepare tail call to StoreIC_ArrayLength. 1412 // Prepare tail call to StoreIC_ArrayLength.
1364 __ pop(scratch); 1413 __ pop(scratch);
1365 __ push(receiver); 1414 __ push(receiver);
1366 __ push(value); 1415 __ push(value);
1367 __ push(scratch); // return address 1416 __ push(scratch); // return address
1368 1417
1369 ExternalReference ref = 1418 ExternalReference ref =
1370 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate()); 1419 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
1371 __ TailCallExternalReference(ref, 2, 1); 1420 __ TailCallExternalReference(ref, 2, 1);
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1589 Condition cc = *jmp_address == Assembler::kJncShortOpcode 1638 Condition cc = *jmp_address == Assembler::kJncShortOpcode
1590 ? not_zero 1639 ? not_zero
1591 : zero; 1640 : zero;
1592 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1641 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1593 } 1642 }
1594 1643
1595 1644
1596 } } // namespace v8::internal 1645 } } // namespace v8::internal
1597 1646
1598 #endif // V8_TARGET_ARCH_IA32 1647 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698