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

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

Issue 294022: Add optimized ICs for new CanvasArray types. This is a follow-on CL to... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 2 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/assembler-ia32.cc ('k') | src/objects.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 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 __ j(above_equal, &slow); 337 __ j(above_equal, &slow);
338 __ mov(eax, Operand(ebx)); 338 __ mov(eax, Operand(ebx));
339 __ and_(eax, (1 << String::kShortLengthShift) - 1); 339 __ and_(eax, (1 << String::kShortLengthShift) - 1);
340 __ shr(eax, String::kLongLengthShift); 340 __ shr(eax, String::kLongLengthShift);
341 __ jmp(&index_int); 341 __ jmp(&index_int);
342 } 342 }
343 343
344 344
345 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, 345 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
346 ExternalArrayType array_type) { 346 ExternalArrayType array_type) {
347 GenerateGeneric(masm); 347 // ----------- S t a t e -------------
348 // -- esp[0] : return address
349 // -- esp[4] : key
350 // -- esp[8] : receiver
351 // -----------------------------------
352 Label slow, failed_allocation;
353
354 // Load name and receiver.
355 __ mov(eax, Operand(esp, kPointerSize));
356 __ mov(ecx, Operand(esp, 2 * kPointerSize));
357
358 // Check that the object isn't a smi.
359 __ test(ecx, Immediate(kSmiTagMask));
360 __ j(zero, &slow, not_taken);
361
362 // Check that the key is a smi.
363 __ test(eax, Immediate(kSmiTagMask));
364 __ j(not_zero, &slow, not_taken);
365
366 // Get the map of the receiver.
367 __ mov(edx, FieldOperand(ecx, HeapObject::kMapOffset));
368 // Check that the receiver does not require access checks. We need
369 // to check this explicitly since this generic stub does not perform
370 // map checks.
371 __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset));
372 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
373 __ j(not_zero, &slow, not_taken);
374
375 // Get the instance type from the map of the receiver.
376 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
377 // Check that the object is a JS object.
378 __ cmp(edx, JS_OBJECT_TYPE);
379 __ j(not_equal, &slow, not_taken);
380
381 // Check that the elements array is the appropriate type of
382 // ExternalArray.
383 // eax: index (as a smi)
384 // ecx: JSObject
385 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
386 Handle<Map> map(Heap::MapForExternalArrayType(array_type));
387 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
388 Immediate(map));
389 __ j(not_equal, &slow, not_taken);
390
391 // Check that the index is in range.
392 __ sar(eax, kSmiTagSize); // Untag the index.
393 __ cmp(eax, FieldOperand(ecx, ExternalArray::kLengthOffset));
394 // Unsigned comparison catches both negative and too-large values.
395 __ j(above_equal, &slow);
396
397 // eax: untagged index
398 // ecx: elements array
399 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset));
400 // ecx: base pointer of external storage
401 switch (array_type) {
402 case kExternalByteArray:
403 __ movsx_b(eax, Operand(ecx, eax, times_1, 0));
404 break;
405 case kExternalUnsignedByteArray:
406 __ mov_b(eax, Operand(ecx, eax, times_1, 0));
407 break;
408 case kExternalShortArray:
409 __ movsx_w(eax, Operand(ecx, eax, times_2, 0));
410 break;
411 case kExternalUnsignedShortArray:
412 __ mov_w(eax, Operand(ecx, eax, times_2, 0));
413 break;
414 case kExternalIntArray:
415 case kExternalUnsignedIntArray:
416 __ mov(eax, Operand(ecx, eax, times_4, 0));
417 break;
418 case kExternalFloatArray:
419 __ fld_s(Operand(ecx, eax, times_4, 0));
420 break;
421 default:
422 UNREACHABLE();
423 break;
424 }
425
426 // For integer array types:
427 // eax: value
428 // For floating-point array type:
429 // FP(0): value
430
431 if (array_type == kExternalIntArray ||
432 array_type == kExternalUnsignedIntArray) {
433
434 // For the Int and UnsignedInt array types, we need to see whether
435 // the value can be represented in a Smi. If not, we need to convert
436 // it to a HeapNumber.
437 Label box_int;
438 if (array_type == kExternalIntArray) {
439 // See Smi::IsValid for why this works.
440 __ mov(ebx, eax);
441 __ add(Operand(ebx), Immediate(0x40000000));
442 __ cmp(ebx, 0x80000000);
443 __ j(above_equal, &box_int);
444 } else {
445 ASSERT_EQ(array_type, kExternalUnsignedIntArray);
446 // The test is different for unsigned int values. Since we need
447 // the Smi-encoded result to be treated as unsigned, we can't
448 // handle either of the top two bits being set in the value.
449 __ test(eax, Immediate(0xC0000000));
450 __ j(not_zero, &box_int);
451 }
452
453 __ shl(eax, kSmiTagSize);
454 __ ret(0);
455
456 __ bind(&box_int);
457
458 // Allocate a HeapNumber for the int and perform int-to-double
459 // conversion.
460 if (array_type == kExternalIntArray) {
461 __ push(eax);
462 __ fild_s(Operand(esp, 0));
463 __ pop(eax);
464 } else {
465 ASSERT(array_type == kExternalUnsignedIntArray);
466 // Need to zero-extend the value.
467 // There's no fild variant for unsigned values, so zero-extend
468 // to a 64-bit int manually.
469 __ push(Immediate(0));
470 __ push(eax);
471 __ fild_d(Operand(esp, 0));
472 __ pop(eax);
473 __ pop(eax);
474 }
475 // FP(0): value
476 __ AllocateHeapNumber(eax, ebx, ecx, &failed_allocation);
477 // Set the value.
478 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
479 __ ret(0);
480 } else if (array_type == kExternalFloatArray) {
481 // For the floating-point array type, we need to always allocate a
482 // HeapNumber.
483 __ AllocateHeapNumber(eax, ebx, ecx, &failed_allocation);
484 // Set the value.
485 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
486 __ ret(0);
487 } else {
488 __ shl(eax, kSmiTagSize);
489 __ ret(0);
490 }
491
492 // If we fail allocation of the HeapNumber, we still have a value on
493 // top of the FPU stack. Remove it.
494 __ bind(&failed_allocation);
495 __ ffree();
496 __ fincstp();
497 // Fall through to slow case.
498
499 // Slow case: Load name and receiver from stack and jump to runtime.
500 __ bind(&slow);
501 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
502 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty));
348 } 503 }
349 504
350 505
351 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { 506 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
352 // ----------- S t a t e ------------- 507 // ----------- S t a t e -------------
353 // -- eax : value 508 // -- eax : value
354 // -- esp[0] : return address 509 // -- esp[0] : return address
355 // -- esp[4] : key 510 // -- esp[4] : key
356 // -- esp[8] : receiver 511 // -- esp[8] : receiver
357 // ----------------------------------- 512 // -----------------------------------
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 eax); 635 eax);
481 // Update write barrier for the elements array address. 636 // Update write barrier for the elements array address.
482 __ mov(edx, Operand(eax)); 637 __ mov(edx, Operand(eax));
483 __ RecordWrite(ecx, 0, edx, ebx); 638 __ RecordWrite(ecx, 0, edx, ebx);
484 __ ret(0); 639 __ ret(0);
485 } 640 }
486 641
487 642
488 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, 643 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
489 ExternalArrayType array_type) { 644 ExternalArrayType array_type) {
490 GenerateGeneric(masm); 645 // ----------- S t a t e -------------
646 // -- eax : value
647 // -- esp[0] : return address
648 // -- esp[4] : key
649 // -- esp[8] : receiver
650 // -----------------------------------
651 Label slow, check_heap_number;
652
653 // Get the receiver from the stack.
654 __ mov(edx, Operand(esp, 2 * kPointerSize));
655 // Check that the object isn't a smi.
656 __ test(edx, Immediate(kSmiTagMask));
657 __ j(zero, &slow);
658 // Get the map from the receiver.
659 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
660 // Check that the receiver does not require access checks. We need
661 // to do this because this generic stub does not perform map checks.
662 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset));
663 __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded));
664 __ j(not_zero, &slow);
665 // Get the key from the stack.
666 __ mov(ebx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address
667 // Check that the key is a smi.
668 __ test(ebx, Immediate(kSmiTagMask));
669 __ j(not_zero, &slow);
670 // Get the instance type from the map of the receiver.
671 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
672 // Check that the object is a JS object.
673 __ cmp(ecx, JS_OBJECT_TYPE);
674 __ j(not_equal, &slow);
675
676 // Check that the elements array is the appropriate type of
677 // ExternalArray.
678 // eax: value
679 // edx: JSObject
680 // ebx: index (as a smi)
681 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
682 Handle<Map> map(Heap::MapForExternalArrayType(array_type));
683 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
684 Immediate(map));
685 __ j(not_equal, &slow);
686
687 // Check that the index is in range.
688 __ sar(ebx, kSmiTagSize); // Untag the index.
689 __ cmp(ebx, FieldOperand(ecx, ExternalArray::kLengthOffset));
690 // Unsigned comparison catches both negative and too-large values.
691 __ j(above_equal, &slow);
692
693 // Handle both smis and HeapNumbers in the fast path. Go to the
694 // runtime for all other kinds of values.
695 // eax: value
696 // ecx: elements array
697 // ebx: untagged index
698 __ test(eax, Immediate(kSmiTagMask));
699 __ j(not_equal, &check_heap_number);
700 // smi case
701 __ mov(edx, eax); // Save the value.
702 __ sar(eax, kSmiTagSize); // Untag the value.
703 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset));
704 // ecx: base pointer of external storage
705 switch (array_type) {
706 case kExternalByteArray:
707 case kExternalUnsignedByteArray:
708 __ mov_b(Operand(ecx, ebx, times_1, 0), eax);
709 break;
710 case kExternalShortArray:
711 case kExternalUnsignedShortArray:
712 __ mov_w(Operand(ecx, ebx, times_2, 0), eax);
713 break;
714 case kExternalIntArray:
715 case kExternalUnsignedIntArray:
716 __ mov(Operand(ecx, ebx, times_4, 0), eax);
717 break;
718 case kExternalFloatArray:
719 // Need to perform int-to-float conversion.
720 __ push(eax);
721 __ fild_s(Operand(esp, 0));
722 __ pop(eax);
723 __ fstp_s(Operand(ecx, ebx, times_4, 0));
724 break;
725 default:
726 UNREACHABLE();
727 break;
728 }
729 __ mov(eax, edx); // Return the original value.
730 __ ret(0);
731
732 __ bind(&check_heap_number);
733 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
734 Immediate(Factory::heap_number_map()));
735 __ j(not_equal, &slow);
736
737 // The WebGL specification leaves the behavior of storing NaN and
738 // +/-Infinity into integer arrays basically undefined. For more
739 // reproducible behavior, convert these to zero.
740 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
741 __ mov(edx, eax); // Save the value.
742 __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset));
743 // ebx: untagged index
744 // ecx: base pointer of external storage
745 // top of FPU stack: value
746 if (array_type == kExternalFloatArray) {
747 __ fstp_s(Operand(ecx, ebx, times_4, 0));
748 __ mov(eax, edx); // Return the original value.
749 __ ret(0);
750 } else {
751 // Need to perform float-to-int conversion.
752 // Test the top of the FP stack for NaN.
753 Label is_nan;
754 __ fucomi(0);
755 __ j(parity_even, &is_nan);
756
757 if (array_type != kExternalUnsignedIntArray) {
758 __ push(eax); // Make room on stack
759 __ fistp_s(Operand(esp, 0));
760 __ pop(eax);
761 } else {
762 // fistp stores values as signed integers.
763 // To represent the entire range, we need to store as a 64-bit
764 // int and discard the high 32 bits.
765 __ push(eax); // Make room on stack
766 __ push(eax); // Make room on stack
767 __ fistp_d(Operand(esp, 0));
768 __ pop(eax);
769 __ mov(Operand(esp, 0), eax);
770 __ pop(eax);
771 }
772 // eax: untagged integer value
773 switch (array_type) {
774 case kExternalByteArray:
775 case kExternalUnsignedByteArray:
776 __ mov_b(Operand(ecx, ebx, times_1, 0), eax);
777 break;
778 case kExternalShortArray:
779 case kExternalUnsignedShortArray:
780 __ mov_w(Operand(ecx, ebx, times_2, 0), eax);
781 break;
782 case kExternalIntArray:
783 case kExternalUnsignedIntArray: {
784 // We also need to explicitly check for +/-Infinity. These are
785 // converted to MIN_INT, but we need to be careful not to
786 // confuse with legal uses of MIN_INT.
787 Label not_infinity;
788 // This test would apparently detect both NaN and Infinity,
789 // but we've already checked for NaN using the FPU hardware
790 // above.
791 __ mov_w(edi, FieldOperand(edx, HeapNumber::kValueOffset + 6));
792 __ and_(edi, 0x7FF0);
793 __ cmp(edi, 0x7FF0);
794 __ j(not_equal, &not_infinity);
795 __ mov(eax, 0);
796 __ bind(&not_infinity);
797 __ mov(Operand(ecx, ebx, times_4, 0), eax);
798 break;
799 }
800 default:
801 UNREACHABLE();
802 break;
803 }
804 __ mov(eax, edx); // Return the original value.
805 __ ret(0);
806
807 __ bind(&is_nan);
808 __ ffree();
809 __ fincstp();
810 switch (array_type) {
811 case kExternalByteArray:
812 case kExternalUnsignedByteArray:
813 __ mov_b(Operand(ecx, ebx, times_1, 0), 0);
814 break;
815 case kExternalShortArray:
816 case kExternalUnsignedShortArray:
817 __ mov(eax, 0);
818 __ mov_w(Operand(ecx, ebx, times_2, 0), eax);
819 break;
820 case kExternalIntArray:
821 case kExternalUnsignedIntArray:
822 __ mov(Operand(ecx, ebx, times_4, 0), Immediate(0));
823 break;
824 default:
825 UNREACHABLE();
826 break;
827 }
828 __ mov(eax, edx); // Return the original value.
829 __ ret(0);
830 }
831
832 // Slow case: call runtime.
833 __ bind(&slow);
834 Generate(masm, ExternalReference(Runtime::kSetProperty));
491 } 835 }
492 836
493 837
494 // Defined in ic.cc. 838 // Defined in ic.cc.
495 Object* CallIC_Miss(Arguments args); 839 Object* CallIC_Miss(Arguments args);
496 840
497 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 841 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
498 // ----------- S t a t e ------------- 842 // ----------- S t a t e -------------
499 // ----------------------------------- 843 // -----------------------------------
500 Label number, non_number, non_string, boolean, probe, miss; 844 Label number, non_number, non_string, boolean, probe, miss;
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 1378
1035 // Do tail-call to runtime routine. 1379 // Do tail-call to runtime routine.
1036 __ TailCallRuntime( 1380 __ TailCallRuntime(
1037 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1); 1381 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
1038 } 1382 }
1039 1383
1040 #undef __ 1384 #undef __
1041 1385
1042 1386
1043 } } // namespace v8::internal 1387 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/assembler-ia32.cc ('k') | src/objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698