| 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 | 
|  |