| OLD | NEW | 
|---|
| 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 604 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 615   __ TailCallExternalReference(ref, 2, 1); | 615   __ TailCallExternalReference(ref, 2, 1); | 
| 616 | 616 | 
| 617   __ bind(&slow); | 617   __ bind(&slow); | 
| 618   GenerateMiss(masm); | 618   GenerateMiss(masm); | 
| 619 } | 619 } | 
| 620 | 620 | 
| 621 | 621 | 
| 622 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 622 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 
| 623   // ----------- S t a t e ------------- | 623   // ----------- S t a t e ------------- | 
| 624   //  -- eax    : value | 624   //  -- eax    : value | 
|  | 625   //  -- ecx    : key | 
|  | 626   //  -- edx    : receiver | 
| 625   //  -- esp[0] : return address | 627   //  -- esp[0] : return address | 
| 626   //  -- esp[4] : key |  | 
| 627   //  -- esp[8] : receiver |  | 
| 628   // ----------------------------------- | 628   // ----------------------------------- | 
| 629   Label slow, fast, array, extra, check_pixel_array; | 629   Label slow, fast, array, extra, check_pixel_array; | 
| 630 | 630 | 
| 631   // Get the receiver from the stack. |  | 
| 632   __ mov(edx, Operand(esp, 2 * kPointerSize));  // 2 ~ return address, key |  | 
| 633   // Check that the object isn't a smi. | 631   // Check that the object isn't a smi. | 
| 634   __ test(edx, Immediate(kSmiTagMask)); | 632   __ test(edx, Immediate(kSmiTagMask)); | 
| 635   __ j(zero, &slow, not_taken); | 633   __ j(zero, &slow, not_taken); | 
| 636   // Get the map from the receiver. | 634   // Get the map from the receiver. | 
| 637   __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 635   __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 
| 638   // Check that the receiver does not require access checks.  We need | 636   // Check that the receiver does not require access checks.  We need | 
| 639   // to do this because this generic stub does not perform map checks. | 637   // to do this because this generic stub does not perform map checks. | 
| 640   __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); | 638   __ movzx_b(ebx, FieldOperand(edi, Map::kBitFieldOffset)); | 
| 641   __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 639   __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 
| 642   __ j(not_zero, &slow, not_taken); | 640   __ j(not_zero, &slow, not_taken); | 
| 643   // Get the key from the stack. |  | 
| 644   __ mov(ebx, Operand(esp, 1 * kPointerSize));  // 1 ~ return address |  | 
| 645   // Check that the key is a smi. | 641   // Check that the key is a smi. | 
| 646   __ test(ebx, Immediate(kSmiTagMask)); | 642   __ test(ecx, Immediate(kSmiTagMask)); | 
| 647   __ j(not_zero, &slow, not_taken); | 643   __ j(not_zero, &slow, not_taken); | 
| 648   // Get the instance type from the map of the receiver. | 644   __ CmpInstanceType(edi, JS_ARRAY_TYPE); | 
| 649   __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |  | 
| 650   // Check if the object is a JS array or not. |  | 
| 651   __ cmp(ecx, JS_ARRAY_TYPE); |  | 
| 652   __ j(equal, &array); | 645   __ j(equal, &array); | 
| 653   // Check that the object is some kind of JS object. | 646   // Check that the object is some kind of JS object. | 
| 654   __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 647   __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); | 
| 655   __ j(less, &slow, not_taken); | 648   __ j(below, &slow, not_taken); | 
| 656 | 649 | 
| 657   // Object case: Check key against length in the elements array. | 650   // Object case: Check key against length in the elements array. | 
| 658   // eax: value | 651   // eax: value | 
| 659   // edx: JSObject | 652   // edx: JSObject | 
| 660   // ebx: index (as a smi) | 653   // ecx: key (a smi) | 
| 661   __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 654   __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 
| 662   // Check that the object is in fast mode (not dictionary). | 655   // Check that the object is in fast mode (not dictionary). | 
| 663   __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 656   __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); | 
| 664          Immediate(Factory::fixed_array_map())); | 657   __ mov(ebx, Operand(ecx)); | 
| 665   __ j(not_equal, &check_pixel_array, not_taken); | 658   __ SmiUntag(ebx); | 
| 666   // Untag the key (for checking against untagged length in the fixed array). | 659   __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); | 
| 667   __ mov(edx, Operand(ebx)); |  | 
| 668   __ sar(edx, kSmiTagSize);  // untag the index and use it for the comparison |  | 
| 669   __ cmp(edx, FieldOperand(ecx, Array::kLengthOffset)); |  | 
| 670   // eax: value |  | 
| 671   // ecx: FixedArray |  | 
| 672   // ebx: index (as a smi) |  | 
| 673   __ j(below, &fast, taken); | 660   __ j(below, &fast, taken); | 
| 674 | 661 | 
| 675   // Slow case: call runtime. | 662   // Slow case: call runtime. | 
| 676   __ bind(&slow); | 663   __ bind(&slow); | 
| 677   GenerateRuntimeSetProperty(masm); | 664   GenerateRuntimeSetProperty(masm); | 
| 678 | 665 | 
| 679   // Check whether the elements is a pixel array. | 666   // Check whether the elements is a pixel array. | 
|  | 667   __ bind(&check_pixel_array); | 
| 680   // eax: value | 668   // eax: value | 
| 681   // ecx: elements array | 669   // ecx: key | 
| 682   // ebx: index (as a smi) | 670   // edx: receiver | 
| 683   __ bind(&check_pixel_array); | 671   // edi: elements array | 
| 684   __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 672   __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); | 
| 685          Immediate(Factory::pixel_array_map())); |  | 
| 686   __ j(not_equal, &slow); |  | 
| 687   // Check that the value is a smi. If a conversion is needed call into the | 673   // Check that the value is a smi. If a conversion is needed call into the | 
| 688   // runtime to convert and clamp. | 674   // runtime to convert and clamp. | 
| 689   __ test(eax, Immediate(kSmiTagMask)); | 675   __ test(eax, Immediate(kSmiTagMask)); | 
| 690   __ j(not_zero, &slow); | 676   __ j(not_zero, &slow); | 
| 691   __ sar(ebx, kSmiTagSize);  // Untag the index. | 677   __ mov(ebx, ecx); | 
| 692   __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); | 678   __ SmiUntag(ebx); | 
|  | 679   __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); | 
| 693   __ j(above_equal, &slow); | 680   __ j(above_equal, &slow); | 
| 694   __ mov(edx, eax);  // Save the value. | 681   __ mov(ecx, eax);  // Save the value. Key is not longer needed. | 
| 695   __ sar(eax, kSmiTagSize);  // Untag the value. | 682   __ SmiUntag(ecx); | 
| 696   {  // Clamp the value to [0..255]. | 683   {  // Clamp the value to [0..255]. | 
| 697     Label done; | 684     Label done; | 
| 698     __ test(eax, Immediate(0xFFFFFF00)); | 685     __ test(ecx, Immediate(0xFFFFFF00)); | 
| 699     __ j(zero, &done); | 686     __ j(zero, &done); | 
| 700     __ setcc(negative, eax);  // 1 if negative, 0 if positive. | 687     __ setcc(negative, ecx);  // 1 if negative, 0 if positive. | 
| 701     __ dec_b(eax);  // 0 if negative, 255 if positive. | 688     __ dec_b(ecx);  // 0 if negative, 255 if positive. | 
| 702     __ bind(&done); | 689     __ bind(&done); | 
| 703   } | 690   } | 
| 704   __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); | 691   __ mov(edi, FieldOperand(edi, PixelArray::kExternalPointerOffset)); | 
| 705   __ mov_b(Operand(ecx, ebx, times_1, 0), eax); | 692   __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 
| 706   __ mov(eax, edx);  // Return the original value. | 693   __ ret(0);  // Return value in eax. | 
| 707   __ ret(0); |  | 
| 708 | 694 | 
| 709   // Extra capacity case: Check if there is extra capacity to | 695   // Extra capacity case: Check if there is extra capacity to | 
| 710   // perform the store and update the length. Used for adding one | 696   // perform the store and update the length. Used for adding one | 
| 711   // element to the array by writing to array[array.length]. | 697   // element to the array by writing to array[array.length]. | 
| 712   __ bind(&extra); | 698   __ bind(&extra); | 
| 713   // eax: value | 699   // eax: value | 
| 714   // edx: JSArray | 700   // edx: receiver, a JSArray | 
| 715   // ecx: FixedArray | 701   // ecx: key, a smi. | 
| 716   // ebx: index (as a smi) | 702   // edi: receiver->elements, a FixedArray | 
| 717   // flags: compare (ebx, edx.length()) | 703   // flags: compare (ecx, edx.length()) | 
| 718   __ j(not_equal, &slow, not_taken);  // do not leave holes in the array | 704   __ j(not_equal, &slow, not_taken);  // do not leave holes in the array | 
| 719   __ sar(ebx, kSmiTagSize);  // untag | 705   __ mov(ebx, ecx); | 
| 720   __ cmp(ebx, FieldOperand(ecx, Array::kLengthOffset)); | 706   __ SmiUntag(ebx);  // untag | 
|  | 707   __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); | 
| 721   __ j(above_equal, &slow, not_taken); | 708   __ j(above_equal, &slow, not_taken); | 
| 722   // Restore tag and increment. | 709   // Add 1 to receiver->length, and go to fast array write. | 
| 723   __ lea(ebx, Operand(ebx, times_2, 1 << kSmiTagSize)); | 710   __ add(FieldOperand(edx, JSArray::kLengthOffset), | 
| 724   __ mov(FieldOperand(edx, JSArray::kLengthOffset), ebx); | 711          Immediate(1 << kSmiTagSize)); | 
| 725   __ sub(Operand(ebx), Immediate(1 << kSmiTagSize));  // decrement ebx again |  | 
| 726   __ jmp(&fast); | 712   __ jmp(&fast); | 
| 727 | 713 | 
| 728   // Array case: Get the length and the elements array from the JS | 714   // Array case: Get the length and the elements array from the JS | 
| 729   // array. Check that the array is in fast mode; if it is the | 715   // array. Check that the array is in fast mode; if it is the | 
| 730   // length is always a smi. | 716   // length is always a smi. | 
| 731   __ bind(&array); | 717   __ bind(&array); | 
| 732   // eax: value | 718   // eax: value | 
| 733   // edx: JSArray | 719   // edx: receiver, a JSArray | 
| 734   // ebx: index (as a smi) | 720   // ecx: key, a smi. | 
| 735   __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 721   __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 
| 736   __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 722   __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); | 
| 737          Immediate(Factory::fixed_array_map())); |  | 
| 738   __ j(not_equal, &check_pixel_array); |  | 
| 739 | 723 | 
| 740   // Check the key against the length in the array, compute the | 724   // Check the key against the length in the array, compute the | 
| 741   // address to store into and fall through to fast case. | 725   // address to store into and fall through to fast case. | 
| 742   __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); | 726   __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // Compare smis. | 
| 743   __ j(above_equal, &extra, not_taken); | 727   __ j(above_equal, &extra, not_taken); | 
| 744 | 728 | 
| 745   // Fast case: Do the store. | 729   // Fast case: Do the store. | 
| 746   __ bind(&fast); | 730   __ bind(&fast); | 
| 747   // eax: value | 731   // eax: value | 
| 748   // ecx: FixedArray | 732   // ecx: key (a smi) | 
| 749   // ebx: index (as a smi) | 733   // edx: receiver | 
| 750   __ mov(Operand(ecx, ebx, times_2, FixedArray::kHeaderSize - kHeapObjectTag), | 734   // edi: FixedArray receiver->elements | 
| 751          eax); | 735   __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); | 
| 752   // Update write barrier for the elements array address. | 736   // Update write barrier for the elements array address. | 
| 753   __ mov(edx, Operand(eax)); | 737   __ mov(edx, Operand(eax)); | 
| 754   __ RecordWrite(ecx, 0, edx, ebx); | 738   __ RecordWrite(edi, 0, edx, ecx); | 
| 755   __ ret(0); | 739   __ ret(0); | 
| 756 } | 740 } | 
| 757 | 741 | 
| 758 | 742 | 
| 759 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, | 743 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, | 
| 760                                          ExternalArrayType array_type) { | 744                                          ExternalArrayType array_type) { | 
| 761   // ----------- S t a t e ------------- | 745   // ----------- S t a t e ------------- | 
| 762   //  -- eax    : value | 746   //  -- eax    : value | 
|  | 747   //  -- ecx    : key | 
|  | 748   //  -- edx    : receiver | 
| 763   //  -- esp[0] : return address | 749   //  -- esp[0] : return address | 
| 764   //  -- esp[4] : key |  | 
| 765   //  -- esp[8] : receiver |  | 
| 766   // ----------------------------------- | 750   // ----------------------------------- | 
| 767   Label slow, check_heap_number; | 751   Label slow, check_heap_number; | 
| 768 | 752 | 
| 769   // Get the receiver from the stack. |  | 
| 770   __ mov(edx, Operand(esp, 2 * kPointerSize)); |  | 
| 771   // Check that the object isn't a smi. | 753   // Check that the object isn't a smi. | 
| 772   __ test(edx, Immediate(kSmiTagMask)); | 754   __ test(edx, Immediate(kSmiTagMask)); | 
| 773   __ j(zero, &slow); | 755   __ j(zero, &slow); | 
| 774   // Get the map from the receiver. | 756   // Get the map from the receiver. | 
| 775   __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 757   __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 
| 776   // Check that the receiver does not require access checks.  We need | 758   // Check that the receiver does not require access checks.  We need | 
| 777   // to do this because this generic stub does not perform map checks. | 759   // to do this because this generic stub does not perform map checks. | 
| 778   __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); | 760   __ movzx_b(ebx, FieldOperand(edi, Map::kBitFieldOffset)); | 
| 779   __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 761   __ test(ebx, Immediate(1 << Map::kIsAccessCheckNeeded)); | 
| 780   __ j(not_zero, &slow); | 762   __ j(not_zero, &slow); | 
| 781   // Get the key from the stack. |  | 
| 782   __ mov(ebx, Operand(esp, 1 * kPointerSize));  // 1 ~ return address |  | 
| 783   // Check that the key is a smi. | 763   // Check that the key is a smi. | 
| 784   __ test(ebx, Immediate(kSmiTagMask)); | 764   __ test(ecx, Immediate(kSmiTagMask)); | 
| 785   __ j(not_zero, &slow); | 765   __ j(not_zero, &slow); | 
| 786   // Get the instance type from the map of the receiver. | 766   // Get the instance type from the map of the receiver. | 
| 787   __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 767   __ CmpInstanceType(edi, JS_OBJECT_TYPE); | 
| 788   // Check that the object is a JS object. |  | 
| 789   __ cmp(ecx, JS_OBJECT_TYPE); |  | 
| 790   __ j(not_equal, &slow); | 768   __ j(not_equal, &slow); | 
| 791 | 769 | 
| 792   // Check that the elements array is the appropriate type of | 770   // Check that the elements array is the appropriate type of | 
| 793   // ExternalArray. | 771   // ExternalArray. | 
| 794   // eax: value | 772   // eax: value | 
| 795   // edx: JSObject | 773   // edx: receiver, a JSObject | 
| 796   // ebx: index (as a smi) | 774   // ecx: key, a smi | 
| 797   __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 775   __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 
| 798   Handle<Map> map(Heap::MapForExternalArrayType(array_type)); | 776   __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)), | 
| 799   __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 777               &slow, true); | 
| 800          Immediate(map)); |  | 
| 801   __ j(not_equal, &slow); |  | 
| 802 | 778 | 
| 803   // Check that the index is in range. | 779   // Check that the index is in range. | 
| 804   __ sar(ebx, kSmiTagSize);  // Untag the index. | 780   __ mov(ebx, ecx); | 
| 805   __ cmp(ebx, FieldOperand(ecx, ExternalArray::kLengthOffset)); | 781   __ SmiUntag(ebx); | 
|  | 782   __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); | 
| 806   // Unsigned comparison catches both negative and too-large values. | 783   // Unsigned comparison catches both negative and too-large values. | 
| 807   __ j(above_equal, &slow); | 784   __ j(above_equal, &slow); | 
| 808 | 785 | 
| 809   // Handle both smis and HeapNumbers in the fast path. Go to the | 786   // Handle both smis and HeapNumbers in the fast path. Go to the | 
| 810   // runtime for all other kinds of values. | 787   // runtime for all other kinds of values. | 
| 811   // eax: value | 788   // eax: value | 
| 812   // ecx: elements array | 789   // edx: receiver | 
|  | 790   // ecx: key | 
|  | 791   // edi: elements array | 
| 813   // ebx: untagged index | 792   // ebx: untagged index | 
| 814   __ test(eax, Immediate(kSmiTagMask)); | 793   __ test(eax, Immediate(kSmiTagMask)); | 
| 815   __ j(not_equal, &check_heap_number); | 794   __ j(not_equal, &check_heap_number); | 
| 816   // smi case | 795   // smi case | 
| 817   __ mov(edx, eax);  // Save the value. | 796   __ mov(ecx, eax);  // Preserve the value in eax.  Key is no longer needed. | 
| 818   __ sar(eax, kSmiTagSize);  // Untag the value. | 797   __ SmiUntag(ecx); | 
| 819   __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset)); | 798   __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 
| 820   // ecx: base pointer of external storage | 799   // ecx: base pointer of external storage | 
| 821   switch (array_type) { | 800   switch (array_type) { | 
| 822     case kExternalByteArray: | 801     case kExternalByteArray: | 
| 823     case kExternalUnsignedByteArray: | 802     case kExternalUnsignedByteArray: | 
| 824       __ mov_b(Operand(ecx, ebx, times_1, 0), eax); | 803       __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 
| 825       break; | 804       break; | 
| 826     case kExternalShortArray: | 805     case kExternalShortArray: | 
| 827     case kExternalUnsignedShortArray: | 806     case kExternalUnsignedShortArray: | 
| 828       __ mov_w(Operand(ecx, ebx, times_2, 0), eax); | 807       __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 
| 829       break; | 808       break; | 
| 830     case kExternalIntArray: | 809     case kExternalIntArray: | 
| 831     case kExternalUnsignedIntArray: | 810     case kExternalUnsignedIntArray: | 
| 832       __ mov(Operand(ecx, ebx, times_4, 0), eax); | 811       __ mov(Operand(edi, ebx, times_4, 0), ecx); | 
| 833       break; | 812       break; | 
| 834     case kExternalFloatArray: | 813     case kExternalFloatArray: | 
| 835       // Need to perform int-to-float conversion. | 814       // Need to perform int-to-float conversion. | 
| 836       __ push(eax); | 815       __ push(ecx); | 
| 837       __ fild_s(Operand(esp, 0)); | 816       __ fild_s(Operand(esp, 0)); | 
| 838       __ pop(eax); | 817       __ pop(ecx); | 
| 839       __ fstp_s(Operand(ecx, ebx, times_4, 0)); | 818       __ fstp_s(Operand(edi, ebx, times_4, 0)); | 
| 840       break; | 819       break; | 
| 841     default: | 820     default: | 
| 842       UNREACHABLE(); | 821       UNREACHABLE(); | 
| 843       break; | 822       break; | 
| 844   } | 823   } | 
| 845   __ mov(eax, edx);  // Return the original value. | 824   __ ret(0);  // Return the original value. | 
| 846   __ ret(0); |  | 
| 847 | 825 | 
| 848   __ bind(&check_heap_number); | 826   __ bind(&check_heap_number); | 
|  | 827   // eax: value | 
|  | 828   // edx: receiver | 
|  | 829   // ecx: key | 
|  | 830   // edi: elements array | 
|  | 831   // ebx: untagged index | 
| 849   __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 832   __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 
| 850          Immediate(Factory::heap_number_map())); | 833          Immediate(Factory::heap_number_map())); | 
| 851   __ j(not_equal, &slow); | 834   __ j(not_equal, &slow); | 
| 852 | 835 | 
| 853   // The WebGL specification leaves the behavior of storing NaN and | 836   // The WebGL specification leaves the behavior of storing NaN and | 
| 854   // +/-Infinity into integer arrays basically undefined. For more | 837   // +/-Infinity into integer arrays basically undefined. For more | 
| 855   // reproducible behavior, convert these to zero. | 838   // reproducible behavior, convert these to zero. | 
| 856   __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 839   __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 
| 857   __ mov(edx, eax);  // Save the value. | 840   __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 
| 858   __ mov(ecx, FieldOperand(ecx, ExternalArray::kExternalPointerOffset)); |  | 
| 859   // ebx: untagged index | 841   // ebx: untagged index | 
| 860   // ecx: base pointer of external storage | 842   // edi: base pointer of external storage | 
| 861   // top of FPU stack: value | 843   // top of FPU stack: value | 
| 862   if (array_type == kExternalFloatArray) { | 844   if (array_type == kExternalFloatArray) { | 
| 863     __ fstp_s(Operand(ecx, ebx, times_4, 0)); | 845     __ fstp_s(Operand(edi, ebx, times_4, 0)); | 
| 864     __ mov(eax, edx);  // Return the original value. |  | 
| 865     __ ret(0); | 846     __ ret(0); | 
| 866   } else { | 847   } else { | 
| 867     // Need to perform float-to-int conversion. | 848     // Need to perform float-to-int conversion. | 
| 868     // Test the top of the FP stack for NaN. | 849     // Test the top of the FP stack for NaN. | 
| 869     Label is_nan; | 850     Label is_nan; | 
| 870     __ fucomi(0); | 851     __ fucomi(0); | 
| 871     __ j(parity_even, &is_nan); | 852     __ j(parity_even, &is_nan); | 
| 872 | 853 | 
| 873     if (array_type != kExternalUnsignedIntArray) { | 854     if (array_type != kExternalUnsignedIntArray) { | 
| 874       __ push(eax);  // Make room on stack | 855       __ push(ecx);  // Make room on stack | 
| 875       __ fistp_s(Operand(esp, 0)); | 856       __ fistp_s(Operand(esp, 0)); | 
| 876       __ pop(eax); | 857       __ pop(ecx); | 
| 877     } else { | 858     } else { | 
| 878       // fistp stores values as signed integers. | 859       // fistp stores values as signed integers. | 
| 879       // To represent the entire range, we need to store as a 64-bit | 860       // To represent the entire range, we need to store as a 64-bit | 
| 880       // int and discard the high 32 bits. | 861       // int and discard the high 32 bits. | 
| 881       __ push(eax);  // Make room on stack | 862       __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 
| 882       __ push(eax);  // Make room on stack |  | 
| 883       __ fistp_d(Operand(esp, 0)); | 863       __ fistp_d(Operand(esp, 0)); | 
| 884       __ pop(eax); | 864       __ pop(ecx); | 
| 885       __ mov(Operand(esp, 0), eax); | 865       __ add(Operand(esp), Immediate(kPointerSize)); | 
| 886       __ pop(eax); |  | 
| 887     } | 866     } | 
| 888     // eax: untagged integer value | 867     // ecx: untagged integer value | 
| 889     switch (array_type) { | 868     switch (array_type) { | 
| 890       case kExternalByteArray: | 869       case kExternalByteArray: | 
| 891       case kExternalUnsignedByteArray: | 870       case kExternalUnsignedByteArray: | 
| 892         __ mov_b(Operand(ecx, ebx, times_1, 0), eax); | 871         __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 
| 893         break; | 872         break; | 
| 894       case kExternalShortArray: | 873       case kExternalShortArray: | 
| 895       case kExternalUnsignedShortArray: | 874       case kExternalUnsignedShortArray: | 
| 896         __ mov_w(Operand(ecx, ebx, times_2, 0), eax); | 875         __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 
| 897         break; | 876         break; | 
| 898       case kExternalIntArray: | 877       case kExternalIntArray: | 
| 899       case kExternalUnsignedIntArray: { | 878       case kExternalUnsignedIntArray: { | 
| 900         // We also need to explicitly check for +/-Infinity. These are | 879         // We also need to explicitly check for +/-Infinity. These are | 
| 901         // converted to MIN_INT, but we need to be careful not to | 880         // converted to MIN_INT, but we need to be careful not to | 
| 902         // confuse with legal uses of MIN_INT. | 881         // confuse with legal uses of MIN_INT. | 
| 903         Label not_infinity; | 882         Label not_infinity; | 
| 904         // This test would apparently detect both NaN and Infinity, | 883         // This test would apparently detect both NaN and Infinity, | 
| 905         // but we've already checked for NaN using the FPU hardware | 884         // but we've already checked for NaN using the FPU hardware | 
| 906         // above. | 885         // above. | 
| 907         __ mov_w(edi, FieldOperand(edx, HeapNumber::kValueOffset + 6)); | 886         __ mov_w(edx, FieldOperand(eax, HeapNumber::kValueOffset + 6)); | 
| 908         __ and_(edi, 0x7FF0); | 887         __ and_(edx, 0x7FF0); | 
| 909         __ cmp(edi, 0x7FF0); | 888         __ cmp(edx, 0x7FF0); | 
| 910         __ j(not_equal, ¬_infinity); | 889         __ j(not_equal, ¬_infinity); | 
| 911         __ mov(eax, 0); | 890         __ mov(ecx, 0); | 
| 912         __ bind(¬_infinity); | 891         __ bind(¬_infinity); | 
| 913         __ mov(Operand(ecx, ebx, times_4, 0), eax); | 892         __ mov(Operand(edi, ebx, times_4, 0), ecx); | 
| 914         break; | 893         break; | 
| 915       } | 894       } | 
| 916       default: | 895       default: | 
| 917         UNREACHABLE(); | 896         UNREACHABLE(); | 
| 918         break; | 897         break; | 
| 919     } | 898     } | 
| 920     __ mov(eax, edx);  // Return the original value. | 899     __ ret(0);  // Return original value. | 
| 921     __ ret(0); |  | 
| 922 | 900 | 
| 923     __ bind(&is_nan); | 901     __ bind(&is_nan); | 
| 924     __ ffree(); | 902     __ ffree(); | 
| 925     __ fincstp(); | 903     __ fincstp(); | 
| 926     switch (array_type) { | 904     switch (array_type) { | 
| 927       case kExternalByteArray: | 905       case kExternalByteArray: | 
| 928       case kExternalUnsignedByteArray: | 906       case kExternalUnsignedByteArray: | 
| 929         __ mov_b(Operand(ecx, ebx, times_1, 0), 0); | 907         __ mov_b(Operand(edi, ebx, times_1, 0), 0); | 
| 930         break; | 908         break; | 
| 931       case kExternalShortArray: | 909       case kExternalShortArray: | 
| 932       case kExternalUnsignedShortArray: | 910       case kExternalUnsignedShortArray: | 
| 933         __ mov(eax, 0); | 911         __ xor_(ecx, Operand(ecx)); | 
| 934         __ mov_w(Operand(ecx, ebx, times_2, 0), eax); | 912         __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 
| 935         break; | 913         break; | 
| 936       case kExternalIntArray: | 914       case kExternalIntArray: | 
| 937       case kExternalUnsignedIntArray: | 915       case kExternalUnsignedIntArray: | 
| 938         __ mov(Operand(ecx, ebx, times_4, 0), Immediate(0)); | 916         __ mov(Operand(edi, ebx, times_4, 0), Immediate(0)); | 
| 939         break; | 917         break; | 
| 940       default: | 918       default: | 
| 941         UNREACHABLE(); | 919         UNREACHABLE(); | 
| 942         break; | 920         break; | 
| 943     } | 921     } | 
| 944     __ mov(eax, edx);  // Return the original value. | 922     __ ret(0);  // Return the original value. | 
| 945     __ ret(0); |  | 
| 946   } | 923   } | 
| 947 | 924 | 
| 948   // Slow case: call runtime. | 925   // Slow case: call runtime. | 
| 949   __ bind(&slow); | 926   __ bind(&slow); | 
| 950   GenerateRuntimeSetProperty(masm); | 927   GenerateRuntimeSetProperty(masm); | 
| 951 } | 928 } | 
| 952 | 929 | 
| 953 | 930 | 
| 954 // Defined in ic.cc. | 931 // Defined in ic.cc. | 
| 955 Object* CallIC_Miss(Arguments args); | 932 Object* CallIC_Miss(Arguments args); | 
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1490   GenerateMiss(masm); | 1467   GenerateMiss(masm); | 
| 1491 } | 1468 } | 
| 1492 | 1469 | 
| 1493 | 1470 | 
| 1494 // Defined in ic.cc. | 1471 // Defined in ic.cc. | 
| 1495 Object* KeyedStoreIC_Miss(Arguments args); | 1472 Object* KeyedStoreIC_Miss(Arguments args); | 
| 1496 | 1473 | 
| 1497 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | 1474 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | 
| 1498   // ----------- S t a t e ------------- | 1475   // ----------- S t a t e ------------- | 
| 1499   //  -- eax    : value | 1476   //  -- eax    : value | 
|  | 1477   //  -- ecx    : key | 
|  | 1478   //  -- edx    : receiver | 
| 1500   //  -- esp[0] : return address | 1479   //  -- esp[0] : return address | 
| 1501   //  -- esp[4] : key |  | 
| 1502   //  -- esp[8] : receiver |  | 
| 1503   // ----------------------------------- | 1480   // ----------------------------------- | 
| 1504 | 1481 | 
| 1505   __ pop(ecx); | 1482   __ pop(ebx); | 
| 1506   __ push(Operand(esp, 1 * kPointerSize)); | 1483   __ push(edx); | 
| 1507   __ push(Operand(esp, 1 * kPointerSize)); | 1484   __ push(ecx); | 
| 1508   __ push(eax); | 1485   __ push(eax); | 
| 1509   __ push(ecx); | 1486   __ push(ebx); | 
| 1510 | 1487 | 
| 1511   // Do tail-call to runtime routine. | 1488   // Do tail-call to runtime routine. | 
| 1512   __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1489   __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 
| 1513 } | 1490 } | 
| 1514 | 1491 | 
| 1515 | 1492 | 
| 1516 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 1493 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 
| 1517   // ----------- S t a t e ------------- | 1494   // ----------- S t a t e ------------- | 
| 1518   //  -- eax    : value | 1495   //  -- eax    : value | 
|  | 1496   //  -- ecx    : key | 
|  | 1497   //  -- edx    : receiver | 
| 1519   //  -- esp[0] : return address | 1498   //  -- esp[0] : return address | 
| 1520   //  -- esp[4] : key |  | 
| 1521   //  -- esp[8] : receiver |  | 
| 1522   // ----------------------------------- | 1499   // ----------------------------------- | 
| 1523 | 1500 | 
| 1524   __ pop(ecx); | 1501   __ pop(ebx); | 
| 1525   __ push(Operand(esp, 1 * kPointerSize)); | 1502   __ push(edx); | 
| 1526   __ push(Operand(esp, 1 * kPointerSize)); | 1503   __ push(ecx); | 
| 1527   __ push(eax); | 1504   __ push(eax); | 
| 1528   __ push(ecx); | 1505   __ push(ebx); | 
| 1529 | 1506 | 
| 1530   // Do tail-call to runtime routine. | 1507   // Do tail-call to runtime routine. | 
| 1531   ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1508   ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 
| 1532   __ TailCallExternalReference(ref, 3, 1); | 1509   __ TailCallExternalReference(ref, 3, 1); | 
| 1533 } | 1510 } | 
| 1534 | 1511 | 
| 1535 #undef __ | 1512 #undef __ | 
| 1536 | 1513 | 
| 1537 | 1514 | 
| 1538 } }  // namespace v8::internal | 1515 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|