Index: src/ia32/lithium-codegen-ia32.cc |
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc |
index 84eb799604dbdf0095e4643556de9f633ef272a7..3461be083e1162212cb98bcf668df52259043d47 100644 |
--- a/src/ia32/lithium-codegen-ia32.cc |
+++ b/src/ia32/lithium-codegen-ia32.cc |
@@ -2246,11 +2246,16 @@ void LCodeGen::DoLoadElements(LLoadElements* instr) { |
Immediate(factory()->fixed_array_map())); |
__ j(equal, &done); |
__ cmp(FieldOperand(result, HeapObject::kMapOffset), |
- Immediate(factory()->external_pixel_array_map())); |
- __ j(equal, &done); |
- __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
Immediate(factory()->fixed_cow_array_map())); |
- __ Check(equal, "Check for fast elements or pixel array failed."); |
+ __ j(equal, &done); |
+ Register temp((result.is(eax)) ? ebx : eax); |
+ __ push(temp); |
+ __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); |
+ __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
+ __ sub(Operand(temp), Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); |
+ __ cmp(Operand(temp), Immediate(kExternalArrayTypeCount)); |
+ __ pop(temp); |
+ __ Check(below, "Check for fast elements or pixel array failed."); |
__ bind(&done); |
} |
} |
@@ -2298,14 +2303,47 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
} |
-void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) { |
+void LCodeGen::DoLoadKeyedSpecializedArrayElement( |
+ LLoadKeyedSpecializedArrayElement* instr) { |
Register external_pointer = ToRegister(instr->external_pointer()); |
Register key = ToRegister(instr->key()); |
- Register result = ToRegister(instr->result()); |
- ASSERT(result.is(external_pointer)); |
- |
- // Load the result. |
- __ movzx_b(result, Operand(external_pointer, key, times_1, 0)); |
+ ExternalArrayType array_type = instr->array_type(); |
+ if (array_type == kExternalFloatArray) { |
+ XMMRegister result(ToDoubleRegister(instr->result())); |
+ __ movss(result, Operand(external_pointer, key, times_4, 0)); |
+ __ cvtss2sd(result, result); |
+ } else { |
+ Register result(ToRegister(instr->result())); |
+ switch (array_type) { |
+ case kExternalByteArray: |
+ __ movsx_b(result, Operand(external_pointer, key, times_1, 0)); |
+ break; |
+ case kExternalUnsignedByteArray: |
+ case kExternalPixelArray: |
+ __ movzx_b(result, Operand(external_pointer, key, times_1, 0)); |
+ break; |
+ case kExternalShortArray: |
+ __ movsx_w(result, Operand(external_pointer, key, times_2, 0)); |
+ break; |
+ case kExternalUnsignedShortArray: |
+ __ movzx_w(result, Operand(external_pointer, key, times_2, 0)); |
+ break; |
+ case kExternalIntArray: |
+ __ mov(result, Operand(external_pointer, key, times_4, 0)); |
+ break; |
+ case kExternalUnsignedIntArray: |
+ __ mov(result, Operand(external_pointer, key, times_4, 0)); |
+ __ test(Operand(result), Immediate(0x80000000)); |
+ // TODO(danno): we could be more clever here, perhaps having a special |
+ // version of the stub that detects if the overflow case actually |
+ // happens, and generate code that returns a double rather than int. |
+ DeoptimizeIf(not_zero, instr->environment()); |
+ break; |
+ case kExternalFloatArray: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ } |
} |
@@ -2930,22 +2968,52 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
} |
-void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) { |
+void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
+ LStoreKeyedSpecializedArrayElement* instr) { |
Register external_pointer = ToRegister(instr->external_pointer()); |
Register key = ToRegister(instr->key()); |
- Register value = ToRegister(instr->value()); |
- ASSERT(ToRegister(instr->TempAt(0)).is(eax)); |
- |
- __ mov(eax, value); |
- { // Clamp the value to [0..255]. |
- NearLabel done; |
- __ test(eax, Immediate(0xFFFFFF00)); |
- __ j(zero, &done); |
- __ setcc(negative, eax); // 1 if negative, 0 if positive. |
- __ dec_b(eax); // 0 if negative, 255 if positive. |
- __ bind(&done); |
+ ExternalArrayType array_type = instr->array_type(); |
+ if (array_type == kExternalFloatArray) { |
+ __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); |
+ __ movss(Operand(external_pointer, key, times_4, 0), xmm0); |
+ } else { |
+ Register value = ToRegister(instr->value()); |
+ switch (array_type) { |
+ case kExternalPixelArray: { |
+ // Clamp the value to [0..255]. |
+ Register temp = ToRegister(instr->TempAt(0)); |
+ // The dec_b below requires that the clamped value is in a byte |
+ // register. eax is an arbitrary choice to satisfy this requirement, we |
+ // hinted the register allocator to give us eax when building the |
+ // instruction. |
+ ASSERT(temp.is(eax)); |
+ __ mov(temp, ToRegister(instr->value())); |
+ NearLabel done; |
+ __ test(temp, Immediate(0xFFFFFF00)); |
+ __ j(zero, &done); |
+ __ setcc(negative, temp); // 1 if negative, 0 if positive. |
+ __ dec_b(temp); // 0 if negative, 255 if positive. |
+ __ bind(&done); |
+ __ mov_b(Operand(external_pointer, key, times_1, 0), temp); |
+ break; |
+ } |
+ case kExternalByteArray: |
+ case kExternalUnsignedByteArray: |
+ __ mov_b(Operand(external_pointer, key, times_1, 0), value); |
+ break; |
+ case kExternalShortArray: |
+ case kExternalUnsignedShortArray: |
+ __ mov_w(Operand(external_pointer, key, times_2, 0), value); |
+ break; |
+ case kExternalIntArray: |
+ case kExternalUnsignedIntArray: |
+ __ mov(Operand(external_pointer, key, times_4, 0), value); |
+ break; |
+ case kExternalFloatArray: |
+ UNREACHABLE(); |
+ break; |
+ } |
} |
- __ mov_b(Operand(external_pointer, key, times_1, 0), eax); |
} |