Index: src/ia32/lithium-ia32.cc |
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc |
index a4b1b865451ec91c3b75332f64ab35f4523e4545..3ce57381bd9163aaaa298711fcf6964aff3cf392 100644 |
--- a/src/ia32/lithium-ia32.cc |
+++ b/src/ia32/lithium-ia32.cc |
@@ -91,6 +91,22 @@ void LInstruction::VerifyCall() { |
#endif |
+bool LInstruction::HasDoubleRegisterResult() { |
+ return HasResult() && result()->IsDoubleRegister(); |
+} |
+ |
+ |
+bool LInstruction::HasDoubleRegisterInput() { |
+ for (int i = 0; i < InputCount(); i++) { |
+ LOperand* op = InputAt(i); |
+ if (op->IsDoubleRegister()) { |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
void LInstruction::PrintTo(StringStream* stream) { |
stream->Add("%s ", this->Mnemonic()); |
@@ -542,6 +558,11 @@ LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) { |
} |
+LOperand* LChunkBuilder::UseX87TopOfStack(HValue* value) { |
+ return Use(value, ToUnallocated(x87tos)); |
+} |
+ |
+ |
LOperand* LChunkBuilder::UseRegister(HValue* value) { |
return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); |
} |
@@ -1861,20 +1882,33 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
? TempRegister() |
: NULL; |
LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); |
- return AssignEnvironment(DefineAsRegister(res)); |
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
+ return AssignEnvironment(DefineAsRegister(res)); |
+ } else { |
+ return AssignEnvironment(DefineX87TOS(res)); |
+ } |
} else { |
ASSERT(to.IsInteger32()); |
- LOperand* value = UseRegister(instr->value()); |
if (instr->value()->type().IsSmi()) { |
+ LOperand* value = UseRegister(instr->value()); |
return DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); |
} else { |
bool truncating = instr->CanTruncateToInt32(); |
- LOperand* xmm_temp = |
- (truncating && CpuFeatures::IsSupported(SSE3)) |
- ? NULL |
- : FixedTemp(xmm1); |
- LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp); |
- return AssignEnvironment(DefineSameAsFirst(res)); |
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
+ LOperand* value = UseRegister(instr->value()); |
+ LOperand* xmm_temp = |
+ (truncating && CpuFeatures::IsSupported(SSE3)) |
+ ? NULL |
+ : FixedTemp(xmm1); |
+ LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp); |
+ return AssignEnvironment(DefineSameAsFirst(res)); |
+ } else { |
+ LOperand* value = UseFixed(instr->value(), ecx); |
+ LTaggedToINoSSE2* res = |
+ new(zone()) LTaggedToINoSSE2(value, TempRegister(), |
+ TempRegister(), TempRegister()); |
+ return AssignEnvironment(DefineFixed(res, ecx)); |
+ } |
} |
} |
} else if (from.IsDouble()) { |
@@ -1992,12 +2026,20 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
return DefineFixed(new(zone()) LClampIToUint8(reg), eax); |
} else { |
ASSERT(input_rep.IsTagged()); |
- LOperand* reg = UseFixed(value, eax); |
- // Register allocator doesn't (yet) support allocation of double |
- // temps. Reserve xmm1 explicitly. |
- LOperand* temp = FixedTemp(xmm1); |
- LClampTToUint8* result = new(zone()) LClampTToUint8(reg, temp); |
- return AssignEnvironment(DefineFixed(result, eax)); |
+ if (CpuFeatures::IsSupported(SSE2)) { |
+ LOperand* reg = UseFixed(value, eax); |
+ // Register allocator doesn't (yet) support allocation of double |
+ // temps. Reserve xmm1 explicitly. |
+ LOperand* temp = FixedTemp(xmm1); |
+ LClampTToUint8* result = new(zone()) LClampTToUint8(reg, temp); |
+ return AssignEnvironment(DefineFixed(result, eax)); |
+ } else { |
+ LOperand* value = UseRegister(instr->value()); |
+ LClampTToUint8NoSSE2* res = |
+ new(zone()) LClampTToUint8NoSSE2(value, TempRegister(), |
+ TempRegister(), TempRegister()); |
+ return AssignEnvironment(DefineFixed(res, ecx)); |
+ } |
} |
} |
@@ -2018,10 +2060,13 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
return DefineAsRegister(new(zone()) LConstantI); |
} else if (r.IsDouble()) { |
double value = instr->DoubleValue(); |
- LOperand* temp = (BitCast<uint64_t, double>(value) != 0) |
- ? TempRegister() |
- : NULL; |
- return DefineAsRegister(new(zone()) LConstantD(temp)); |
+ bool value_is_zero = BitCast<uint64_t, double>(value) == 0; |
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
+ LOperand* temp = value_is_zero ? NULL : TempRegister(); |
+ return DefineAsRegister(new(zone()) LConstantD(temp)); |
+ } else { |
+ return DefineX87TOS(new(zone()) LConstantD(NULL)); |
+ } |
} else if (r.IsTagged()) { |
return DefineAsRegister(new(zone()) LConstantT); |
} else { |
@@ -2190,6 +2235,27 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
} |
+LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) { |
+ ElementsKind elements_kind = instr->elements_kind(); |
+ |
+ // Determine if we need a byte register in this case for the value. |
+ bool val_is_fixed_register = |
+ elements_kind == EXTERNAL_BYTE_ELEMENTS || |
+ elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS || |
+ elements_kind == EXTERNAL_PIXEL_ELEMENTS; |
+ if (val_is_fixed_register) { |
+ return UseFixed(instr->value(), eax); |
+ } |
+ |
+ if (!CpuFeatures::IsSafeForSnapshot(SSE2) && |
+ IsDoubleOrFloatElementsKind(elements_kind)) { |
+ return UseRegisterAtStart(instr->value()); |
+ } |
+ |
+ return UseRegister(instr->value()); |
+} |
+ |
+ |
LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
if (!instr->is_external()) { |
ASSERT(instr->elements()->representation().IsTagged()); |
@@ -2198,7 +2264,12 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
if (instr->value()->representation().IsDouble()) { |
LOperand* object = UseRegisterAtStart(instr->elements()); |
- LOperand* val = UseTempRegister(instr->value()); |
+ LOperand* val = NULL; |
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
+ val = UseRegisterAtStart(instr->value()); |
+ } else if (!instr->IsConstantHoleStore()) { |
+ val = UseX87TopOfStack(instr->value()); |
+ } |
LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
return new(zone()) LStoreKeyed(object, key, val); |
@@ -2228,15 +2299,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
ASSERT(instr->elements()->representation().IsExternal()); |
LOperand* external_pointer = UseRegister(instr->elements()); |
- // Determine if we need a byte register in this case for the value. |
- bool val_is_fixed_register = |
- elements_kind == EXTERNAL_BYTE_ELEMENTS || |
- elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS || |
- elements_kind == EXTERNAL_PIXEL_ELEMENTS; |
- |
- LOperand* val = val_is_fixed_register |
- ? UseFixed(instr->value(), eax) |
- : UseRegister(instr->value()); |
+ LOperand* val = GetStoreKeyedValueOperand(instr); |
bool clobbers_key = ExternalArrayOpRequiresTemp( |
instr->key()->representation(), elements_kind); |
LOperand* key = clobbers_key |