Index: src/ia32/lithium-ia32.cc |
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc |
index de3bf9eca827ca1f467dbac831f694967587b6dd..696c6be6e8159cd8ba3427dab2f8eb6e0717400c 100644 |
--- a/src/ia32/lithium-ia32.cc |
+++ b/src/ia32/lithium-ia32.cc |
@@ -1005,30 +1005,22 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
LInstruction* goto_instr = CheckElideControlInstruction(instr); |
if (goto_instr != NULL) return goto_instr; |
- ToBooleanStub::Types expected = instr->expected_input_types(); |
- |
- // Tagged values that are not known smis or booleans require a |
- // deoptimization environment. If the instruction is generic no |
- // environment is needed since all cases are handled. |
HValue* value = instr->value(); |
- Representation rep = value->representation(); |
+ Representation r = value->representation(); |
HType type = value->type(); |
- if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { |
- return new(zone()) LBranch(UseRegister(value), NULL); |
- } |
- |
- bool needs_temp = expected.NeedsMap() || expected.IsEmpty(); |
- LOperand* temp = needs_temp ? TempRegister() : NULL; |
+ ToBooleanStub::Types expected = instr->expected_input_types(); |
+ if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
- // The Generic stub does not have a deopt, so we need no environment. |
- if (expected.IsGeneric()) { |
- return new(zone()) LBranch(UseRegister(value), temp); |
+ bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() || |
+ type.IsJSArray() || type.IsHeapNumber() || type.IsString(); |
+ LOperand* temp = !easy_case && expected.NeedsMap() ? TempRegister() : NULL; |
+ LInstruction* branch = new(zone()) LBranch(UseRegister(value), temp); |
+ if (!easy_case && |
+ ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) || |
+ !expected.IsGeneric())) { |
+ branch = AssignEnvironment(branch); |
} |
- |
- // We need a temporary register when we have to access the map *or* we have |
- // no type info yet, in which case we handle all cases (including the ones |
- // involving maps). |
- return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp)); |
+ return branch; |
} |
@@ -1221,8 +1213,12 @@ LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { |
LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { |
LOperand* context = UseAny(instr->context()); // Deferred use. |
LOperand* input = UseRegisterAtStart(instr->value()); |
- LMathAbs* result = new(zone()) LMathAbs(context, input); |
- return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
+ LInstruction* result = |
+ DefineSameAsFirst(new(zone()) LMathAbs(context, input)); |
+ Representation r = instr->value()->representation(); |
+ if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); |
+ if (!r.IsDouble()) result = AssignEnvironment(result); |
+ return result; |
} |
@@ -1901,8 +1897,12 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
LOperand* value = UseRegister(instr->value()); |
// Temp register only necessary for minus zero check. |
LOperand* temp = TempRegister(); |
- LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); |
- return AssignEnvironment(DefineAsRegister(res)); |
+ LInstruction* result = DefineAsRegister( |
+ new(zone()) LNumberUntagD(value, temp)); |
+ if (!instr->value()->representation().IsSmi()) { |
+ result = AssignEnvironment(result); |
+ } |
+ return result; |
} else if (to.IsSmi()) { |
HValue* val = instr->value(); |
LOperand* value = UseRegister(val); |
@@ -1921,8 +1921,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
LOperand* xmm_temp = |
(CpuFeatures::IsSafeForSnapshot(SSE2) && !truncating) |
? FixedTemp(xmm1) : NULL; |
- LTaggedToI* res = new(zone()) LTaggedToI(UseRegister(val), xmm_temp); |
- return AssignEnvironment(DefineSameAsFirst(res)); |
+ LInstruction* result = DefineSameAsFirst( |
+ new(zone()) LTaggedToI(UseRegister(val), xmm_temp)); |
+ if (!instr->value()->representation().IsSmi()) { |
+ // Note: Only deopts in deferred code. |
+ result = AssignEnvironment(result); |
+ } |
+ return result; |
} |
} |
} else if (from.IsDouble()) { |
@@ -1946,8 +1951,10 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
LOperand* value = needs_temp ? |
UseTempRegister(instr->value()) : UseRegister(instr->value()); |
LOperand* temp = needs_temp ? TempRegister() : NULL; |
- return AssignEnvironment( |
- DefineAsRegister(new(zone()) LDoubleToI(value, temp))); |
+ LInstruction* result = |
+ DefineAsRegister(new(zone()) LDoubleToI(value, temp)); |
+ if (!truncating) result = AssignEnvironment(result); |
+ return result; |
} |
} else if (from.IsInteger32()) { |
info()->MarkAsDeferredCalling(); |
@@ -1961,11 +1968,11 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
LOperand* temp2 = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1) |
: NULL; |
LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); |
- return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
+ return AssignPointerMap(DefineSameAsFirst(result)); |
} else { |
LOperand* temp = TempRegister(); |
LNumberTagI* result = new(zone()) LNumberTagI(value, temp); |
- return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
+ return AssignPointerMap(DefineSameAsFirst(result)); |
} |
} else if (to.IsSmi()) { |
HValue* val = instr->value(); |
@@ -2031,6 +2038,7 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { |
} |
LCheckMaps* result = new(zone()) LCheckMaps(value); |
if (!instr->CanOmitMapChecks()) { |
+ // Note: Only deopts in deferred code. |
AssignEnvironment(result); |
if (instr->has_migration_target()) return AssignPointerMap(result); |
} |
@@ -2139,7 +2147,10 @@ LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
LOperand* context = UseRegisterAtStart(instr->value()); |
LInstruction* result = |
DefineAsRegister(new(zone()) LLoadContextSlot(context)); |
- return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; |
+ if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
+ result = AssignEnvironment(result); |
+ } |
+ return result; |
} |
@@ -2155,7 +2166,10 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { |
temp = NULL; |
} |
LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp); |
- return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; |
+ if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
+ result = AssignEnvironment(result); |
+ } |
+ return result; |
} |
@@ -2197,11 +2211,11 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
LOperand* key = clobbers_key |
? UseTempRegister(instr->key()) |
: UseRegisterOrConstantAtStart(instr->key()); |
- LLoadKeyed* result = NULL; |
+ LInstruction* result = NULL; |
if (!instr->is_typed_elements()) { |
LOperand* obj = UseRegisterAtStart(instr->elements()); |
- result = new(zone()) LLoadKeyed(obj, key); |
+ result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key)); |
} else { |
ASSERT( |
(instr->representation().IsInteger32() && |
@@ -2209,15 +2223,20 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
(instr->representation().IsDouble() && |
(IsDoubleOrFloatElementsKind(instr->elements_kind())))); |
LOperand* backing_store = UseRegister(instr->elements()); |
- result = new(zone()) LLoadKeyed(backing_store, key); |
+ result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key)); |
} |
- DefineAsRegister(result); |
- bool can_deoptimize = instr->RequiresHoleCheck() || |
- (elements_kind == EXTERNAL_UINT32_ELEMENTS); |
- // An unsigned int array load might overflow and cause a deopt, make sure it |
- // has an environment. |
- return can_deoptimize ? AssignEnvironment(result) : result; |
+ if ((instr->is_external() || instr->is_fixed_typed_array()) ? |
+ // see LCodeGen::DoLoadKeyedExternalArray |
+ ((instr->elements_kind() == EXTERNAL_UINT32_ELEMENTS || |
+ instr->elements_kind() == UINT32_ELEMENTS) && |
+ !instr->CheckFlag(HInstruction::kUint32)) : |
+ // see LCodeGen::DoLoadKeyedFixedDoubleArray and |
+ // LCodeGen::DoLoadKeyedFixedArray |
+ instr->RequiresHoleCheck()) { |
+ result = AssignEnvironment(result); |
+ } |
+ return result; |
} |
@@ -2408,12 +2427,14 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { |
// We need a temporary register for write barrier of the map field. |
LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() : NULL; |
- LStoreNamedField* result = |
+ LInstruction* result = |
new(zone()) LStoreNamedField(obj, val, temp, temp_map); |
- if (instr->field_representation().IsHeapObject()) { |
- if (!instr->value()->type().IsHeapObject()) { |
- return AssignEnvironment(result); |
- } |
+ if (!instr->access().IsExternalMemory() && |
+ instr->field_representation().IsHeapObject() && |
+ (val->IsConstantOperand() |
+ ? HConstant::cast(instr->value())->HasSmiValue() |
+ : !instr->value()->type().IsHeapObject())) { |
+ result = AssignEnvironment(result); |
} |
return result; |
} |
@@ -2445,7 +2466,7 @@ LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
LOperand* context = UseAny(instr->context()); |
LStringCharCodeAt* result = |
new(zone()) LStringCharCodeAt(context, string, index); |
- return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
+ return AssignPointerMap(DefineAsRegister(result)); |
} |