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

Side by Side Diff: src/x64/ic-x64.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/x64/assembler-x64.cc ('k') | test/cctest/test-api.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 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 __ j(above_equal, &slow); 355 __ j(above_equal, &slow);
356 __ movl(rax, rbx); 356 __ movl(rax, rbx);
357 __ and_(rax, Immediate((1 << String::kShortLengthShift) - 1)); 357 __ and_(rax, Immediate((1 << String::kShortLengthShift) - 1));
358 __ shrl(rax, Immediate(String::kLongLengthShift)); 358 __ shrl(rax, Immediate(String::kLongLengthShift));
359 __ jmp(&index_int); 359 __ jmp(&index_int);
360 } 360 }
361 361
362 362
363 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, 363 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
364 ExternalArrayType array_type) { 364 ExternalArrayType array_type) {
365 GenerateGeneric(masm); 365 // ----------- S t a t e -------------
366 // -- rsp[0] : return address
367 // -- rsp[8] : name
368 // -- rsp[16] : receiver
369 // -----------------------------------
370 Label slow, failed_allocation;
371
372 // Load name and receiver.
373 __ movq(rax, Operand(rsp, kPointerSize));
374 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
375
376 // Check that the object isn't a smi.
377 __ JumpIfSmi(rcx, &slow);
378
379 // Check that the key is a smi.
380 __ JumpIfNotSmi(rax, &slow);
381
382 // Check that the object is a JS object.
383 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx);
384 __ j(not_equal, &slow);
385 // Check that the receiver does not require access checks. We need
386 // to check this explicitly since this generic stub does not perform
387 // map checks. The map is already in rdx.
388 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
389 Immediate(1 << Map::kIsAccessCheckNeeded));
390 __ j(not_zero, &slow);
391
392 // Check that the elements array is the appropriate type of
393 // ExternalArray.
394 // rax: index (as a smi)
395 // rcx: JSObject
396 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
397 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
398 Heap::RootIndexForExternalArrayType(array_type));
399 __ j(not_equal, &slow);
400
401 // Check that the index is in range.
402 __ SmiToInteger32(rax, rax);
403 __ cmpl(rax, FieldOperand(rcx, ExternalArray::kLengthOffset));
404 // Unsigned comparison catches both negative and too-large values.
405 __ j(above_equal, &slow);
406
407 // rax: untagged index
408 // rcx: elements array
409 __ movq(rcx, FieldOperand(rcx, ExternalArray::kExternalPointerOffset));
410 // rcx: base pointer of external storage
411 switch (array_type) {
412 case kExternalByteArray:
413 __ movsxbq(rax, Operand(rcx, rax, times_1, 0));
414 break;
415 case kExternalUnsignedByteArray:
416 __ movb(rax, Operand(rcx, rax, times_1, 0));
417 break;
418 case kExternalShortArray:
419 __ movsxwq(rax, Operand(rcx, rax, times_2, 0));
420 break;
421 case kExternalUnsignedShortArray:
422 __ movzxwq(rax, Operand(rcx, rax, times_2, 0));
423 break;
424 case kExternalIntArray:
425 __ movsxlq(rax, Operand(rcx, rax, times_4, 0));
426 break;
427 case kExternalUnsignedIntArray:
428 __ movl(rax, Operand(rcx, rax, times_4, 0));
429 break;
430 case kExternalFloatArray:
431 __ fld_s(Operand(rcx, rax, times_4, 0));
432 break;
433 default:
434 UNREACHABLE();
435 break;
436 }
437
438 // For integer array types:
439 // rax: value
440 // For floating-point array type:
441 // FP(0): value
442
443 if (array_type == kExternalIntArray ||
444 array_type == kExternalUnsignedIntArray) {
445
446 // For the Int and UnsignedInt array types, we need to see whether
447 // the value can be represented in a Smi. If not, we need to convert
448 // it to a HeapNumber.
449 Label box_int;
450 if (array_type == kExternalIntArray) {
451 __ JumpIfNotValidSmiValue(rax, &box_int);
452 } else {
453 ASSERT_EQ(array_type, kExternalUnsignedIntArray);
454 __ JumpIfUIntNotValidSmiValue(rax, &box_int);
455 }
456
457 __ Integer32ToSmi(rax, rax);
458 __ ret(0);
459
460 __ bind(&box_int);
461
462 // Allocate a HeapNumber for the int and perform int-to-double
463 // conversion.
464 __ push(rax);
465 if (array_type == kExternalIntArray) {
466 __ fild_s(Operand(rsp, 0));
467 } else {
468 ASSERT(array_type == kExternalUnsignedIntArray);
469 // Need to zero-extend the value.
470 __ fild_d(Operand(rsp, 0));
471 }
472 __ pop(rax);
473 // FP(0): value
474 __ AllocateHeapNumber(rax, rbx, &failed_allocation);
475 // Set the value.
476 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
477 __ ret(0);
478 } else if (array_type == kExternalFloatArray) {
479 // For the floating-point array type, we need to always allocate a
480 // HeapNumber.
481 __ AllocateHeapNumber(rax, rbx, &failed_allocation);
482 // Set the value.
483 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
484 __ ret(0);
485 } else {
486 __ Integer32ToSmi(rax, rax);
487 __ ret(0);
488 }
489
490 // If we fail allocation of the HeapNumber, we still have a value on
491 // top of the FPU stack. Remove it.
492 __ bind(&failed_allocation);
493 __ ffree();
494 __ fincstp();
495 // Fall through to slow case.
496
497 // Slow case: Load name and receiver from stack and jump to runtime.
498 __ bind(&slow);
499 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
500 Generate(masm, ExternalReference(Runtime::kKeyedGetProperty));
366 } 501 }
367 502
368 503
369 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 504 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
370 // ----------- S t a t e ------------- 505 // ----------- S t a t e -------------
371 // -- rsp[0] : return address 506 // -- rsp[0] : return address
372 // -- rsp[8] : name 507 // -- rsp[8] : name
373 // -- rsp[16] : receiver 508 // -- rsp[16] : receiver
374 // ----------------------------------- 509 // -----------------------------------
375 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss))); 510 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 FixedArray::kHeaderSize - kHeapObjectTag), 688 FixedArray::kHeaderSize - kHeapObjectTag),
554 rax); 689 rax);
555 __ movq(rdx, rax); 690 __ movq(rdx, rax);
556 __ RecordWriteNonSmi(rcx, 0, rdx, rbx); 691 __ RecordWriteNonSmi(rcx, 0, rdx, rbx);
557 __ ret(0); 692 __ ret(0);
558 } 693 }
559 694
560 695
561 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, 696 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
562 ExternalArrayType array_type) { 697 ExternalArrayType array_type) {
563 GenerateGeneric(masm); 698 // ----------- S t a t e -------------
699 // -- rax : value
700 // -- rsp[0] : return address
701 // -- rsp[8] : key
702 // -- rsp[16] : receiver
703 // -----------------------------------
704 Label slow, check_heap_number;
705
706 // Get the receiver from the stack.
707 __ movq(rdx, Operand(rsp, 2 * kPointerSize));
708 // Check that the object isn't a smi.
709 __ JumpIfSmi(rdx, &slow);
710 // Get the map from the receiver.
711 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
712 // Check that the receiver does not require access checks. We need
713 // to do this because this generic stub does not perform map checks.
714 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
715 Immediate(1 << Map::kIsAccessCheckNeeded));
716 __ j(not_zero, &slow);
717 // Get the key from the stack.
718 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // 1 ~ return address
719 // Check that the key is a smi.
720 __ JumpIfNotSmi(rbx, &slow);
721
722 // Check that the object is a JS object.
723 __ CmpInstanceType(rcx, JS_OBJECT_TYPE);
724 __ j(not_equal, &slow);
725
726 // Check that the elements array is the appropriate type of
727 // ExternalArray.
728 // rax: value
729 // rdx: JSObject
730 // rbx: index (as a smi)
731 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
732 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
733 Heap::RootIndexForExternalArrayType(array_type));
734 __ j(not_equal, &slow);
735
736 // Check that the index is in range.
737 __ SmiToInteger32(rbx, rbx); // Untag the index.
738 __ cmpl(rbx, FieldOperand(rcx, ExternalArray::kLengthOffset));
739 // Unsigned comparison catches both negative and too-large values.
740 __ j(above_equal, &slow);
741
742 // Handle both smis and HeapNumbers in the fast path. Go to the
743 // runtime for all other kinds of values.
744 // rax: value
745 // rcx: elements array
746 // rbx: untagged index
747 __ JumpIfNotSmi(rax, &check_heap_number);
748 __ movq(rdx, rax); // Save the value.
749 __ SmiToInteger32(rax, rax);
750 __ movq(rcx, FieldOperand(rcx, ExternalArray::kExternalPointerOffset));
751 // rcx: base pointer of external storage
752 switch (array_type) {
753 case kExternalByteArray:
754 case kExternalUnsignedByteArray:
755 __ movb(Operand(rcx, rbx, times_1, 0), rax);
756 break;
757 case kExternalShortArray:
758 case kExternalUnsignedShortArray:
759 __ movw(Operand(rcx, rbx, times_2, 0), rax);
760 break;
761 case kExternalIntArray:
762 case kExternalUnsignedIntArray:
763 __ movl(Operand(rcx, rbx, times_4, 0), rax);
764 break;
765 case kExternalFloatArray:
766 // Need to perform int-to-float conversion.
767 __ push(rax);
768 __ fild_s(Operand(rsp, 0));
769 __ pop(rax);
770 __ fstp_s(Operand(rcx, rbx, times_4, 0));
771 break;
772 default:
773 UNREACHABLE();
774 break;
775 }
776 __ movq(rax, rdx); // Return the original value.
777 __ ret(0);
778
779 __ bind(&check_heap_number);
780 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, rdx);
781 __ j(not_equal, &slow);
782
783 // The WebGL specification leaves the behavior of storing NaN and
784 // +/-Infinity into integer arrays basically undefined. For more
785 // reproducible behavior, convert these to zero.
786 __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
787 __ movq(rdx, rax); // Save the value.
788 __ movq(rcx, FieldOperand(rcx, ExternalArray::kExternalPointerOffset));
789 // rbx: untagged index
790 // rcx: base pointer of external storage
791 // top of FPU stack: value
792 if (array_type == kExternalFloatArray) {
793 __ fstp_s(Operand(rcx, rbx, times_4, 0));
794 } else {
795 // Need to perform float-to-int conversion.
796 // Test the top of the FP stack for NaN.
797 Label is_nan;
798 __ fucomi(0);
799 __ j(parity_even, &is_nan);
800
801 __ push(rax); // Make room on stack
802 __ fistp_d(Operand(rsp, 0));
803 __ pop(rax);
804 // rax: untagged integer value
805 switch (array_type) {
806 case kExternalByteArray:
807 case kExternalUnsignedByteArray:
808 __ movb(Operand(rcx, rbx, times_1, 0), rax);
809 break;
810 case kExternalShortArray:
811 case kExternalUnsignedShortArray:
812 __ movw(Operand(rcx, rbx, times_2, 0), rax);
813 break;
814 case kExternalIntArray:
815 case kExternalUnsignedIntArray: {
816 // We also need to explicitly check for +/-Infinity. These are
817 // converted to MIN_INT, but we need to be careful not to
818 // confuse with legal uses of MIN_INT.
819 Label not_infinity;
820 // This test would apparently detect both NaN and Infinity,
821 // but we've already checked for NaN using the FPU hardware
822 // above.
823 __ movzxwq(rdi, FieldOperand(rdx, HeapNumber::kValueOffset + 6));
824 __ and_(rdi, Immediate(0x7FF0));
825 __ cmpw(rdi, Immediate(0x7FF0));
826 __ j(not_equal, &not_infinity);
827 __ movq(rax, Immediate(0));
828 __ bind(&not_infinity);
829 __ movl(Operand(rcx, rbx, times_4, 0), rax);
830 break;
831 }
832 default:
833 UNREACHABLE();
834 break;
835 }
836 __ movq(rax, rdx); // Return the original value.
837 __ ret(0);
838
839 __ bind(&is_nan);
840 __ ffree();
841 __ fincstp();
842 __ movq(rax, Immediate(0));
843 switch (array_type) {
844 case kExternalByteArray:
845 case kExternalUnsignedByteArray:
846 __ movb(Operand(rcx, rbx, times_1, 0), rax);
847 break;
848 case kExternalShortArray:
849 case kExternalUnsignedShortArray:
850 __ movw(Operand(rcx, rbx, times_2, 0), rax);
851 break;
852 case kExternalIntArray:
853 case kExternalUnsignedIntArray:
854 __ movl(Operand(rcx, rbx, times_4, 0), rax);
855 break;
856 default:
857 UNREACHABLE();
858 break;
859 }
860 __ movq(rax, rdx); // Return the original value.
861 __ ret(0);
862 }
863
864 // Slow case: call runtime.
865 __ bind(&slow);
866 Generate(masm, ExternalReference(Runtime::kSetProperty));
564 } 867 }
565 868
566 869
567 void CallIC::Generate(MacroAssembler* masm, 870 void CallIC::Generate(MacroAssembler* masm,
568 int argc, 871 int argc,
569 ExternalReference const& f) { 872 ExternalReference const& f) {
570 // Get the receiver of the function from the stack; 1 ~ return address. 873 // Get the receiver of the function from the stack; 1 ~ return address.
571 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 874 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
572 // Get the name of the function to call from the stack. 875 // Get the name of the function to call from the stack.
573 // 2 ~ receiver, return address. 876 // 2 ~ receiver, return address.
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 1326
1024 // Cache miss: Jump to runtime. 1327 // Cache miss: Jump to runtime.
1025 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); 1328 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
1026 } 1329 }
1027 1330
1028 1331
1029 #undef __ 1332 #undef __
1030 1333
1031 1334
1032 } } // namespace v8::internal 1335 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698