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