Commit f054b56e authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Add pixel array handling in keyed IC's for x64 version.

Review URL: http://codereview.chromium.org/251041

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3000 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0db55a94
...@@ -424,15 +424,14 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -424,15 +424,14 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
__ mov(edx, eax); // Save the value. __ mov(edx, eax); // Save the value.
__ sar(eax, kSmiTagSize); // Untag the value. __ sar(eax, kSmiTagSize); // Untag the value.
{ // Clamp the value to [0..255]. { // Clamp the value to [0..255].
Label done, check_255; Label done, is_negative;
__ cmp(eax, 0); __ test(eax, Immediate(0xFFFFFF00));
__ j(greater_equal, &check_255); __ j(zero, &done);
__ mov(eax, Immediate(0)); __ j(negative, &is_negative);
__ jmp(&done);
__ bind(&check_255);
__ cmp(eax, 255);
__ j(less_equal, &done);
__ mov(eax, Immediate(255)); __ mov(eax, Immediate(255));
__ jmp(&done);
__ bind(&is_negative);
__ xor_(eax, Operand(eax)); // Clear eax.
__ bind(&done); __ bind(&done);
} }
__ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); __ mov(ecx, FieldOperand(ecx, PixelArray::kExternalPointerOffset));
......
...@@ -257,7 +257,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -257,7 +257,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// -- rsp[8] : name // -- rsp[8] : name
// -- rsp[16] : receiver // -- 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. // Load name and receiver.
__ movq(rax, Operand(rsp, kPointerSize)); __ movq(rax, Operand(rsp, kPointerSize));
...@@ -287,11 +287,36 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -287,11 +287,36 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ bind(&index_int); __ bind(&index_int);
__ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset));
// Check that the object is in fast mode (not dictionary). // Check that the object is in fast mode (not dictionary).
__ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), Factory::fixed_array_map()); __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
__ j(not_equal, &slow); Heap::kFixedArrayMapRootIndex);
__ j(not_equal, &check_pixel_array);
// Check that the key (index) is within bounds. // Check that the key (index) is within bounds.
__ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); __ 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. // Slow case: Load name and receiver from stack and jump to runtime.
__ bind(&slow); __ bind(&slow);
__ IncrementCounter(&Counters::keyed_load_generic_slow, 1); __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
...@@ -332,16 +357,6 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -332,16 +357,6 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ and_(rax, Immediate((1 << String::kShortLengthShift) - 1)); __ and_(rax, Immediate((1 << String::kShortLengthShift) - 1));
__ shrl(rax, Immediate(String::kLongLengthShift)); __ shrl(rax, Immediate(String::kLongLengthShift));
__ jmp(&index_int); __ 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 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -402,7 +417,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
// -- rsp[8] : key // -- rsp[8] : key
// -- rsp[16] : receiver // -- rsp[16] : receiver
// ----------------------------------- // -----------------------------------
Label slow, fast, array, extra; Label slow, fast, array, extra, check_pixel_array;
// Get the receiver from the stack. // Get the receiver from the stack.
__ movq(rdx, Operand(rsp, 2 * kPointerSize)); // 2 ~ return address, key __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // 2 ~ return address, key
...@@ -435,8 +450,9 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -435,8 +450,9 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
// rbx: index (as a smi), zero-extended. // rbx: index (as a smi), zero-extended.
__ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
// Check that the object is in fast mode (not dictionary). // Check that the object is in fast mode (not dictionary).
__ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), Factory::fixed_array_map()); __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
__ j(not_equal, &slow); Heap::kFixedArrayMapRootIndex);
__ j(not_equal, &check_pixel_array);
// Untag the key (for checking against untagged length in the fixed array). // Untag the key (for checking against untagged length in the fixed array).
__ SmiToInteger32(rdx, rbx); __ SmiToInteger32(rdx, rbx);
__ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); __ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset));
...@@ -445,7 +461,6 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -445,7 +461,6 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
// rbx: index (as a smi) // rbx: index (as a smi)
__ j(below, &fast); __ j(below, &fast);
// Slow case: Push extra copies of the arguments (3). // Slow case: Push extra copies of the arguments (3).
__ bind(&slow); __ bind(&slow);
__ pop(rcx); __ pop(rcx);
...@@ -456,6 +471,37 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -456,6 +471,37 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1); __ 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);
__ 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 // Extra capacity case: Check if there is extra capacity to
// perform the store and update the length. Used for adding one // perform the store and update the length. Used for adding one
...@@ -476,7 +522,6 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -476,7 +522,6 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
__ SmiSubConstant(rbx, rbx, 1, NULL); __ SmiSubConstant(rbx, rbx, 1, NULL);
__ jmp(&fast); __ jmp(&fast);
// Array case: Get the length and the elements array from the JS // 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 // array. Check that the array is in fast mode; if it is the
// length is always a smi. // length is always a smi.
...@@ -493,7 +538,6 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -493,7 +538,6 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
__ cmpl(rbx, FieldOperand(rdx, JSArray::kLengthOffset)); __ cmpl(rbx, FieldOperand(rdx, JSArray::kLengthOffset));
__ j(above_equal, &extra); __ j(above_equal, &extra);
// Fast case: Do the store. // Fast case: Do the store.
__ bind(&fast); __ bind(&fast);
// rax: value // rax: value
......
...@@ -63,6 +63,13 @@ void MacroAssembler::CompareRoot(Register with, ...@@ -63,6 +63,13 @@ void MacroAssembler::CompareRoot(Register with,
} }
void MacroAssembler::CompareRoot(Operand with,
Heap::RootListIndex index) {
LoadRoot(kScratchRegister, index);
cmpq(with, kScratchRegister);
}
static void RecordWriteHelper(MacroAssembler* masm, static void RecordWriteHelper(MacroAssembler* masm,
Register object, Register object,
Register addr, Register addr,
......
...@@ -56,6 +56,7 @@ class MacroAssembler: public Assembler { ...@@ -56,6 +56,7 @@ class MacroAssembler: public Assembler {
void LoadRoot(Register destination, Heap::RootListIndex index); void LoadRoot(Register destination, Heap::RootListIndex index);
void CompareRoot(Register with, Heap::RootListIndex index); void CompareRoot(Register with, Heap::RootListIndex index);
void CompareRoot(Operand with, Heap::RootListIndex index);
void PushRoot(Heap::RootListIndex index); void PushRoot(Heap::RootListIndex index);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment