| Index: src/ia32/ic-ia32.cc
|
| ===================================================================
|
| --- src/ia32/ic-ia32.cc (revision 2544)
|
| +++ src/ia32/ic-ia32.cc (working copy)
|
| @@ -234,7 +234,7 @@
|
| // -- esp[4] : name
|
| // -- esp[8] : 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.
|
| __ mov(eax, Operand(esp, kPointerSize));
|
| @@ -269,11 +269,36 @@
|
| __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset));
|
| // Check that the object is in fast mode (not dictionary).
|
| __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
|
| - Immediate(Factory::hash_table_map()));
|
| - __ j(equal, &slow, not_taken);
|
| + Immediate(Factory::fixed_array_map()));
|
| + __ j(not_equal, &check_pixel_array);
|
| // Check that the key (index) is within bounds.
|
| __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
|
| - __ j(below, &fast, taken);
|
| + __ j(above_equal, &slow);
|
| + // Fast case: Do the load.
|
| + __ mov(eax,
|
| + Operand(ecx, eax, times_4, FixedArray::kHeaderSize - kHeapObjectTag));
|
| + __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
|
| + // 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.
|
| + // eax: untagged index
|
| + // ecx: elements array
|
| + __ bind(&check_pixel_array);
|
| + __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
|
| + Immediate(Factory::pixel_array_map()));
|
| + __ j(not_equal, &slow);
|
| + __ cmp(eax, FieldOperand(ecx, PixelArray::kLengthOffset));
|
| + __ j(above_equal, &slow);
|
| + __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset));
|
| + __ movzx_b(eax, Operand(ecx, eax, times_1, 0));
|
| + __ shl(eax, kSmiTagSize);
|
| + __ ret(0);
|
| +
|
| +
|
| // Slow case: Load name and receiver from stack and jump to runtime.
|
| __ bind(&slow);
|
| __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
|
| @@ -315,16 +340,6 @@
|
| __ and_(eax, (1 << String::kShortLengthShift) - 1);
|
| __ shr(eax, String::kLongLengthShift);
|
| __ jmp(&index_int);
|
| - // Fast case: Do the load.
|
| - __ bind(&fast);
|
| - __ mov(eax,
|
| - Operand(ecx, eax, times_4, FixedArray::kHeaderSize - kHeapObjectTag));
|
| - __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
|
| - // In case the loaded value is the_hole we have to consult GetProperty
|
| - // to ensure the prototype chain is searched.
|
| - __ j(equal, &slow, not_taken);
|
| - __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
|
| - __ ret(0);
|
| }
|
|
|
|
|
| @@ -335,7 +350,7 @@
|
| // -- esp[4] : key
|
| // -- esp[8] : receiver
|
| // -----------------------------------
|
| - Label slow, fast, array, extra;
|
| + Label slow, fast, array, extra, check_pixel_array;
|
|
|
| // Get the receiver from the stack.
|
| __ mov(edx, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, key
|
| @@ -370,8 +385,8 @@
|
| __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
|
| // Check that the object is in fast mode (not dictionary).
|
| __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
|
| - Immediate(Factory::hash_table_map()));
|
| - __ j(equal, &slow, not_taken);
|
| + Immediate(Factory::fixed_array_map()));
|
| + __ j(not_equal, &check_pixel_array, not_taken);
|
| // Untag the key (for checking against untagged length in the fixed array).
|
| __ mov(edx, Operand(ebx));
|
| __ sar(edx, kSmiTagSize); // untag the index and use it for the comparison
|
| @@ -381,7 +396,6 @@
|
| // ebx: index (as a smi)
|
| __ j(below, &fast, taken);
|
|
|
| -
|
| // Slow case: Push extra copies of the arguments (3).
|
| __ bind(&slow);
|
| __ pop(ecx);
|
| @@ -392,6 +406,37 @@
|
| // Do tail-call to runtime routine.
|
| __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
|
|
|
| + // Check whether the elements is a pixel array.
|
| + // eax: value
|
| + // ecx: elements array
|
| + // ebx: index (as a smi)
|
| + __ bind(&check_pixel_array);
|
| + __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
|
| + Immediate(Factory::pixel_array_map()));
|
| + __ j(not_equal, &slow);
|
| + // Check that the value is a smi. If a conversion is needed call into the
|
| + // runtime to convert and clamp.
|
| + __ test(eax, Immediate(kSmiTagMask));
|
| + __ j(not_zero, &slow);
|
| + __ sar(ebx, kSmiTagSize); // Untag the index.
|
| + __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset));
|
| + __ j(above_equal, &slow);
|
| + __ sar(eax, kSmiTagSize); // Untag the value.
|
| + { // Clamp the value to [0..255].
|
| + Label done, check_255;
|
| + __ cmp(eax, 0);
|
| + __ j(greater_equal, &check_255);
|
| + __ mov(eax, Immediate(0));
|
| + __ jmp(&done);
|
| + __ bind(&check_255);
|
| + __ cmp(eax, 255);
|
| + __ j(less_equal, &done);
|
| + __ mov(eax, Immediate(255));
|
| + __ bind(&done);
|
| + }
|
| + __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset));
|
| + __ mov_b(Operand(ecx, ebx, times_1, 0), eax);
|
| + __ ret(0);
|
|
|
| // Extra capacity case: Check if there is extra capacity to
|
| // perform the store and update the length. Used for adding one
|
| @@ -422,15 +467,14 @@
|
| // ebx: index (as a smi)
|
| __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
|
| __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
|
| - Immediate(Factory::hash_table_map()));
|
| - __ j(equal, &slow, not_taken);
|
| + Immediate(Factory::fixed_array_map()));
|
| + __ j(not_equal, &check_pixel_array);
|
|
|
| // Check the key against the length in the array, compute the
|
| // address to store into and fall through to fast case.
|
| __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset));
|
| __ j(above_equal, &extra, not_taken);
|
|
|
| -
|
| // Fast case: Do the store.
|
| __ bind(&fast);
|
| // eax: value
|
|
|