Index: src/x64/ic-x64.cc |
=================================================================== |
--- src/x64/ic-x64.cc (revision 2992) |
+++ src/x64/ic-x64.cc (working copy) |
@@ -257,7 +257,7 @@ |
// -- rsp[8] : name |
// -- rsp[16] : receiver |
// ----------------------------------- |
- Label slow, fast, check_string, index_int, index_string; |
+ Label slow, check_string, index_int, index_string, check_pixel_array; |
// Load name and receiver. |
__ movq(rax, Operand(rsp, kPointerSize)); |
@@ -287,11 +287,36 @@ |
__ bind(&index_int); |
__ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); |
// Check that the object is in fast mode (not dictionary). |
- __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), Factory::fixed_array_map()); |
- __ j(not_equal, &slow); |
+ __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
+ Heap::kFixedArrayMapRootIndex); |
+ __ j(not_equal, &check_pixel_array); |
// Check that the key (index) is within bounds. |
__ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); |
- __ j(below, &fast); // Unsigned comparison rejects negative indices. |
+ __ j(above_equal, &slow); // Unsigned comparison rejects negative indices. |
+ // Fast case: Do the load. |
+ __ movq(rax, Operand(rcx, rax, times_pointer_size, |
+ FixedArray::kHeaderSize - kHeapObjectTag)); |
+ __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
+ // In case the loaded value is the_hole we have to consult GetProperty |
+ // to ensure the prototype chain is searched. |
+ __ j(equal, &slow); |
+ __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
+ __ ret(0); |
+ |
+ // Check whether the elements is a pixel array. |
+ // rax: untagged index |
+ // rcx: elements array |
+ __ bind(&check_pixel_array); |
+ __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
+ Heap::kPixelArrayMapRootIndex); |
+ __ j(not_equal, &slow); |
+ __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset)); |
+ __ j(above_equal, &slow); |
+ __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); |
+ __ movb(rax, Operand(rcx, rax, times_1, 0)); |
+ __ Integer32ToSmi(rax, rax); |
+ __ ret(0); |
+ |
// Slow case: Load name and receiver from stack and jump to runtime. |
__ bind(&slow); |
__ IncrementCounter(&Counters::keyed_load_generic_slow, 1); |
@@ -332,16 +357,6 @@ |
__ and_(rax, Immediate((1 << String::kShortLengthShift) - 1)); |
__ shrl(rax, Immediate(String::kLongLengthShift)); |
__ jmp(&index_int); |
- // Fast case: Do the load. |
- __ bind(&fast); |
- __ movq(rax, Operand(rcx, rax, times_pointer_size, |
- FixedArray::kHeaderSize - kHeapObjectTag)); |
- __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
- // In case the loaded value is the_hole we have to consult GetProperty |
- // to ensure the prototype chain is searched. |
- __ j(equal, &slow); |
- __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
- __ ret(0); |
} |
@@ -402,7 +417,7 @@ |
// -- rsp[8] : key |
// -- rsp[16] : receiver |
// ----------------------------------- |
- Label slow, fast, array, extra; |
+ Label slow, fast, array, extra, check_pixel_array; |
// Get the receiver from the stack. |
__ movq(rdx, Operand(rsp, 2 * kPointerSize)); // 2 ~ return address, key |
@@ -435,8 +450,9 @@ |
// rbx: index (as a smi), zero-extended. |
__ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
// Check that the object is in fast mode (not dictionary). |
- __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), Factory::fixed_array_map()); |
- __ j(not_equal, &slow); |
+ __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
+ Heap::kFixedArrayMapRootIndex); |
+ __ j(not_equal, &check_pixel_array); |
// Untag the key (for checking against untagged length in the fixed array). |
__ SmiToInteger32(rdx, rbx); |
__ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); |
@@ -445,7 +461,6 @@ |
// rbx: index (as a smi) |
__ j(below, &fast); |
- |
// Slow case: Push extra copies of the arguments (3). |
__ bind(&slow); |
__ pop(rcx); |
@@ -456,6 +471,37 @@ |
// Do tail-call to runtime routine. |
__ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1); |
+ // Check whether the elements is a pixel array. |
+ // rax: value |
+ // rcx: elements array |
+ // rbx: index (as a smi), zero-extended. |
+ __ bind(&check_pixel_array); |
+ __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
+ Heap::kPixelArrayMapRootIndex); |
+ __ j(not_equal, &slow); |
+ // Check that the value is a smi. If a conversion is needed call into the |
+ // runtime to convert and clamp. |
+ __ JumpIfNotSmi(rax, &slow); |
+ __ SmiToInteger32(rbx, rbx); |
+ __ cmpl(rbx, FieldOperand(rcx, PixelArray::kLengthOffset)); |
+ __ j(above_equal, &slow); |
+ __ movq(rdx, rax); // Save the value. |
+ __ SmiToInteger32(rax, rax); |
+ { // Clamp the value to [0..255]. |
+ Label done, is_negative; |
+ __ testl(rax, Immediate(0xFFFFFF00)); |
+ __ j(zero, &done); |
+ __ j(negative, &is_negative); |
Lasse Reichstein
2009/09/30 16:50:40
A thought: It might be faster to do the out-of-ran
Søren Thygesen Gjesse
2009/09/30 20:27:06
Nice jump-free clamping. I will try to see if it h
|
+ __ movl(rax, Immediate(255)); |
+ __ jmp(&done); |
+ __ bind(&is_negative); |
+ __ xorl(rax, rax); // Clear rax. |
+ __ bind(&done); |
+ } |
+ __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); |
+ __ movb(Operand(rcx, rbx, times_1, 0), rax); |
+ __ movq(rax, rdx); // Return the original value. |
+ __ ret(0); |
// Extra capacity case: Check if there is extra capacity to |
// perform the store and update the length. Used for adding one |
@@ -476,7 +522,6 @@ |
__ SmiSubConstant(rbx, rbx, 1, NULL); |
__ jmp(&fast); |
- |
// Array case: Get the length and the elements array from the JS |
// array. Check that the array is in fast mode; if it is the |
// length is always a smi. |
@@ -493,7 +538,6 @@ |
__ cmpl(rbx, FieldOperand(rdx, JSArray::kLengthOffset)); |
__ j(above_equal, &extra); |
- |
// Fast case: Do the store. |
__ bind(&fast); |
// rax: value |