Only assign environments when they are actually needed. (ia32 only)

R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/210783003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20231 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4ca46f3c
...@@ -1005,30 +1005,22 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { ...@@ -1005,30 +1005,22 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
LInstruction* goto_instr = CheckElideControlInstruction(instr); LInstruction* goto_instr = CheckElideControlInstruction(instr);
if (goto_instr != NULL) return goto_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(); HValue* value = instr->value();
Representation rep = value->representation(); Representation r = value->representation();
HType type = value->type(); HType type = value->type();
if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { ToBooleanStub::Types expected = instr->expected_input_types();
return new(zone()) LBranch(UseRegister(value), NULL); if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
}
bool needs_temp = expected.NeedsMap() || expected.IsEmpty();
LOperand* temp = needs_temp ? TempRegister() : NULL;
// The Generic stub does not have a deopt, so we need no environment. bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
if (expected.IsGeneric()) { type.IsJSArray() || type.IsHeapNumber() || type.IsString();
return new(zone()) LBranch(UseRegister(value), temp); 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);
} }
return 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));
} }
...@@ -1221,8 +1213,12 @@ LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { ...@@ -1221,8 +1213,12 @@ LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
LOperand* context = UseAny(instr->context()); // Deferred use. LOperand* context = UseAny(instr->context()); // Deferred use.
LOperand* input = UseRegisterAtStart(instr->value()); LOperand* input = UseRegisterAtStart(instr->value());
LMathAbs* result = new(zone()) LMathAbs(context, input); LInstruction* result =
return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(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) { ...@@ -1901,8 +1897,12 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* value = UseRegister(instr->value()); LOperand* value = UseRegister(instr->value());
// Temp register only necessary for minus zero check. // Temp register only necessary for minus zero check.
LOperand* temp = TempRegister(); LOperand* temp = TempRegister();
LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); LInstruction* result = DefineAsRegister(
return AssignEnvironment(DefineAsRegister(res)); new(zone()) LNumberUntagD(value, temp));
if (!instr->value()->representation().IsSmi()) {
result = AssignEnvironment(result);
}
return result;
} else if (to.IsSmi()) { } else if (to.IsSmi()) {
HValue* val = instr->value(); HValue* val = instr->value();
LOperand* value = UseRegister(val); LOperand* value = UseRegister(val);
...@@ -1921,8 +1921,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1921,8 +1921,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* xmm_temp = LOperand* xmm_temp =
(CpuFeatures::IsSafeForSnapshot(SSE2) && !truncating) (CpuFeatures::IsSafeForSnapshot(SSE2) && !truncating)
? FixedTemp(xmm1) : NULL; ? FixedTemp(xmm1) : NULL;
LTaggedToI* res = new(zone()) LTaggedToI(UseRegister(val), xmm_temp); LInstruction* result = DefineSameAsFirst(
return AssignEnvironment(DefineSameAsFirst(res)); 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()) { } else if (from.IsDouble()) {
...@@ -1946,8 +1951,10 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1946,8 +1951,10 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* value = needs_temp ? LOperand* value = needs_temp ?
UseTempRegister(instr->value()) : UseRegister(instr->value()); UseTempRegister(instr->value()) : UseRegister(instr->value());
LOperand* temp = needs_temp ? TempRegister() : NULL; LOperand* temp = needs_temp ? TempRegister() : NULL;
return AssignEnvironment( LInstruction* result =
DefineAsRegister(new(zone()) LDoubleToI(value, temp))); DefineAsRegister(new(zone()) LDoubleToI(value, temp));
if (!truncating) result = AssignEnvironment(result);
return result;
} }
} else if (from.IsInteger32()) { } else if (from.IsInteger32()) {
info()->MarkAsDeferredCalling(); info()->MarkAsDeferredCalling();
...@@ -1961,11 +1968,11 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ...@@ -1961,11 +1968,11 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* temp2 = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1) LOperand* temp2 = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1)
: NULL; : NULL;
LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2);
return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); return AssignPointerMap(DefineSameAsFirst(result));
} else { } else {
LOperand* temp = TempRegister(); LOperand* temp = TempRegister();
LNumberTagI* result = new(zone()) LNumberTagI(value, temp); LNumberTagI* result = new(zone()) LNumberTagI(value, temp);
return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); return AssignPointerMap(DefineSameAsFirst(result));
} }
} else if (to.IsSmi()) { } else if (to.IsSmi()) {
HValue* val = instr->value(); HValue* val = instr->value();
...@@ -2031,6 +2038,7 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { ...@@ -2031,6 +2038,7 @@ LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
} }
LCheckMaps* result = new(zone()) LCheckMaps(value); LCheckMaps* result = new(zone()) LCheckMaps(value);
if (!instr->CanOmitMapChecks()) { if (!instr->CanOmitMapChecks()) {
// Note: Only deopts in deferred code.
AssignEnvironment(result); AssignEnvironment(result);
if (instr->has_migration_target()) return AssignPointerMap(result); if (instr->has_migration_target()) return AssignPointerMap(result);
} }
...@@ -2139,7 +2147,10 @@ LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { ...@@ -2139,7 +2147,10 @@ LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
LOperand* context = UseRegisterAtStart(instr->value()); LOperand* context = UseRegisterAtStart(instr->value());
LInstruction* result = LInstruction* result =
DefineAsRegister(new(zone()) LLoadContextSlot(context)); 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) { ...@@ -2155,7 +2166,10 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
temp = NULL; temp = NULL;
} }
LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp); 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) { ...@@ -2197,11 +2211,11 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
LOperand* key = clobbers_key LOperand* key = clobbers_key
? UseTempRegister(instr->key()) ? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key()); : UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL; LInstruction* result = NULL;
if (!instr->is_typed_elements()) { if (!instr->is_typed_elements()) {
LOperand* obj = UseRegisterAtStart(instr->elements()); LOperand* obj = UseRegisterAtStart(instr->elements());
result = new(zone()) LLoadKeyed(obj, key); result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
} else { } else {
ASSERT( ASSERT(
(instr->representation().IsInteger32() && (instr->representation().IsInteger32() &&
...@@ -2209,15 +2223,20 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { ...@@ -2209,15 +2223,20 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
(instr->representation().IsDouble() && (instr->representation().IsDouble() &&
(IsDoubleOrFloatElementsKind(instr->elements_kind())))); (IsDoubleOrFloatElementsKind(instr->elements_kind()))));
LOperand* backing_store = UseRegister(instr->elements()); LOperand* backing_store = UseRegister(instr->elements());
result = new(zone()) LLoadKeyed(backing_store, key); result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
} }
DefineAsRegister(result); if ((instr->is_external() || instr->is_fixed_typed_array()) ?
bool can_deoptimize = instr->RequiresHoleCheck() || // see LCodeGen::DoLoadKeyedExternalArray
(elements_kind == EXTERNAL_UINT32_ELEMENTS); ((instr->elements_kind() == EXTERNAL_UINT32_ELEMENTS ||
// An unsigned int array load might overflow and cause a deopt, make sure it instr->elements_kind() == UINT32_ELEMENTS) &&
// has an environment. !instr->CheckFlag(HInstruction::kUint32)) :
return can_deoptimize ? AssignEnvironment(result) : result; // see LCodeGen::DoLoadKeyedFixedDoubleArray and
// LCodeGen::DoLoadKeyedFixedArray
instr->RequiresHoleCheck()) {
result = AssignEnvironment(result);
}
return result;
} }
...@@ -2408,12 +2427,14 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { ...@@ -2408,12 +2427,14 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
// We need a temporary register for write barrier of the map field. // We need a temporary register for write barrier of the map field.
LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() : NULL; LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() : NULL;
LStoreNamedField* result = LInstruction* result =
new(zone()) LStoreNamedField(obj, val, temp, temp_map); new(zone()) LStoreNamedField(obj, val, temp, temp_map);
if (instr->field_representation().IsHeapObject()) { if (!instr->access().IsExternalMemory() &&
if (!instr->value()->type().IsHeapObject()) { instr->field_representation().IsHeapObject() &&
return AssignEnvironment(result); (val->IsConstantOperand()
} ? HConstant::cast(instr->value())->HasSmiValue()
: !instr->value()->type().IsHeapObject())) {
result = AssignEnvironment(result);
} }
return result; return result;
} }
...@@ -2445,7 +2466,7 @@ LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { ...@@ -2445,7 +2466,7 @@ LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
LOperand* context = UseAny(instr->context()); LOperand* context = UseAny(instr->context());
LStringCharCodeAt* result = LStringCharCodeAt* result =
new(zone()) LStringCharCodeAt(context, string, index); new(zone()) LStringCharCodeAt(context, string, index);
return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); return AssignPointerMap(DefineAsRegister(result));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment