From 51c209c60915ec5e91703500a645f9edea29feae Mon Sep 17 00:00:00 2001 From: "svenpanne@chromium.org" Date: Tue, 1 Apr 2014 07:21:31 +0000 Subject: [PATCH] Only assign environments when they are actually needed. (ARM and ARM64 only) Twin of https://codereview.chromium.org/210783003/ and https://codereview.chromium.org/211153003/. Cleaned up DoChange a bit on the way, making things more uniform across platforms, removed useless comments etc. R=yangguo@chromium.org Review URL: https://codereview.chromium.org/214613004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20376 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 159 +++++++++++++++++++++---------------- src/arm64/lithium-arm64.cc | 190 ++++++++++++++++++++++----------------------- src/arm64/lithium-arm64.h | 2 +- src/ia32/lithium-ia32.cc | 52 +++++-------- src/x64/lithium-x64.cc | 56 ++++++------- 5 files changed, 227 insertions(+), 232 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index ba44b50..b9f6c33 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -931,18 +931,20 @@ LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { if (goto_instr != NULL) return goto_instr; HValue* value = instr->value(); - LBranch* result = new(zone()) LBranch(UseRegister(value)); - // 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. - Representation rep = value->representation(); + Representation r = value->representation(); HType type = value->type(); ToBooleanStub::Types expected = instr->expected_input_types(); - if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean() && - !expected.IsGeneric()) { - return AssignEnvironment(result); + if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); + + bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() || + type.IsJSArray() || type.IsHeapNumber() || type.IsString(); + LInstruction* branch = new(zone()) LBranch(UseRegister(value)); + if (!easy_case && + ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) || + !expected.IsGeneric())) { + branch = AssignEnvironment(branch); } - return result; + return branch; } @@ -1138,8 +1140,11 @@ LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { ? NULL : UseFixed(instr->context(), cp); LOperand* input = UseRegister(instr->value()); - LMathAbs* result = new(zone()) LMathAbs(context, input); - return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); + LInstruction* result = + DefineAsRegister(new(zone()) LMathAbs(context, input)); + if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); + if (!r.IsDouble()) result = AssignEnvironment(result); + return result; } @@ -1291,8 +1296,18 @@ LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { LOperand* dividend = UseRegister(instr->left()); LOperand* divisor = UseRegister(instr->right()); LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); - LDivI* div = new(zone()) LDivI(dividend, divisor, temp); - return AssignEnvironment(DefineAsRegister(div)); + LInstruction* result = + DefineAsRegister(new(zone()) LDivI(dividend, divisor, temp)); + if (instr->CheckFlag(HValue::kCanBeDivByZero) || + instr->CheckFlag(HValue::kBailoutOnMinusZero) || + (instr->CheckFlag(HValue::kCanOverflow) && + (!CpuFeatures::IsSupported(SUDIV) || + !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) || + (!instr->IsMathFloorOfDiv() && + !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { + result = AssignEnvironment(result); + } + return result; } @@ -1837,20 +1852,21 @@ LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { LInstruction* LChunkBuilder::DoChange(HChange* instr) { Representation from = instr->from(); Representation to = instr->to(); + HValue* val = instr->value(); if (from.IsSmi()) { if (to.IsTagged()) { - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); return DefineSameAsFirst(new(zone()) LDummyUse(value)); } from = Representation::Tagged(); } if (from.IsTagged()) { if (to.IsDouble()) { - LOperand* value = UseRegister(instr->value()); - LNumberUntagD* res = new(zone()) LNumberUntagD(value); - return AssignEnvironment(DefineAsRegister(res)); + LOperand* value = UseRegister(val); + LInstruction* result = DefineAsRegister(new(zone()) LNumberUntagD(value)); + if (!val->representation().IsSmi()) result = AssignEnvironment(result); + return result; } else if (to.IsSmi()) { - HValue* val = instr->value(); LOperand* value = UseRegister(val); if (val->type().IsSmi()) { return DefineSameAsFirst(new(zone()) LDummyUse(value)); @@ -1858,66 +1874,62 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); } else { ASSERT(to.IsInteger32()); - LOperand* value = NULL; - LInstruction* res = NULL; - HValue* val = instr->value(); if (val->type().IsSmi() || val->representation().IsSmi()) { - value = UseRegisterAtStart(val); - res = DefineAsRegister(new(zone()) LSmiUntag(value, false)); + LOperand* value = UseRegisterAtStart(val); + return DefineAsRegister(new(zone()) LSmiUntag(value, false)); } else { - value = UseRegister(val); + LOperand* value = UseRegister(val); LOperand* temp1 = TempRegister(); LOperand* temp2 = FixedTemp(d11); - res = DefineSameAsFirst(new(zone()) LTaggedToI(value, - temp1, - temp2)); - res = AssignEnvironment(res); + LInstruction* result = + DefineSameAsFirst(new(zone()) LTaggedToI(value, temp1, temp2)); + if (!val->representation().IsSmi()) { + // Note: Only deopts in deferred code. + result = AssignEnvironment(result); + } + return result; } - return res; } } else if (from.IsDouble()) { if (to.IsTagged()) { info()->MarkAsDeferredCalling(); - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); LOperand* temp1 = TempRegister(); LOperand* temp2 = TempRegister(); - - // Make sure that the temp and result_temp registers are - // different. LUnallocated* result_temp = TempRegister(); LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); - Define(result, result_temp); - return AssignPointerMap(result); + return AssignPointerMap(Define(result, result_temp)); } else if (to.IsSmi()) { - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); return AssignEnvironment( DefineAsRegister(new(zone()) LDoubleToSmi(value))); } else { ASSERT(to.IsInteger32()); - LOperand* value = UseRegister(instr->value()); - LDoubleToI* res = new(zone()) LDoubleToI(value); - return AssignEnvironment(DefineAsRegister(res)); + LOperand* value = UseRegister(val); + LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value)); + if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result); + return result; } } else if (from.IsInteger32()) { info()->MarkAsDeferredCalling(); if (to.IsTagged()) { - HValue* val = instr->value(); - LOperand* value = UseRegisterAtStart(val); if (!instr->CheckFlag(HValue::kCanOverflow)) { + LOperand* value = UseRegisterAtStart(val); return DefineAsRegister(new(zone()) LSmiTag(value)); } else if (val->CheckFlag(HInstruction::kUint32)) { + LOperand* value = UseRegisterAtStart(val); LOperand* temp1 = TempRegister(); LOperand* temp2 = TempRegister(); LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); - return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); + return AssignPointerMap(DefineAsRegister(result)); } else { + LOperand* value = UseRegisterAtStart(val); LOperand* temp1 = TempRegister(); LOperand* temp2 = TempRegister(); LNumberTagI* result = new(zone()) LNumberTagI(value, temp1, temp2); - return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); + return AssignPointerMap(DefineAsRegister(result)); } } else if (to.IsSmi()) { - HValue* val = instr->value(); LOperand* value = UseRegister(val); LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); if (instr->CheckFlag(HValue::kCanOverflow)) { @@ -1926,12 +1938,10 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { return result; } else { ASSERT(to.IsDouble()); - if (instr->value()->CheckFlag(HInstruction::kUint32)) { - return DefineAsRegister( - new(zone()) LUint32ToDouble(UseRegister(instr->value()))); + if (val->CheckFlag(HInstruction::kUint32)) { + return DefineAsRegister(new(zone()) LUint32ToDouble(UseRegister(val))); } else { - return DefineAsRegister( - new(zone()) LInteger32ToDouble(Use(instr->value()))); + return DefineAsRegister(new(zone()) LInteger32ToDouble(Use(val))); } } } @@ -1973,6 +1983,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); } @@ -2072,7 +2083,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; } @@ -2087,7 +2101,10 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { value = UseRegister(instr->value()); } LInstruction* result = new(zone()) LStoreContextSlot(context, value); - return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; + if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { + result = AssignEnvironment(result); + } + return result; } @@ -2122,7 +2139,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { ASSERT(instr->key()->representation().IsSmiOrInteger32()); ElementsKind elements_kind = instr->elements_kind(); LOperand* key = UseRegisterOrConstantAtStart(instr->key()); - LLoadKeyed* result = NULL; + LInstruction* result = NULL; if (!instr->is_typed_elements()) { LOperand* obj = NULL; @@ -2132,24 +2149,28 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { ASSERT(instr->representation().IsSmiOrTagged()); obj = UseRegisterAtStart(instr->elements()); } - result = new(zone()) LLoadKeyed(obj, key); + result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key)); } else { ASSERT( (instr->representation().IsInteger32() && - !IsDoubleOrFloatElementsKind(instr->elements_kind())) || + !IsDoubleOrFloatElementsKind(elements_kind)) || (instr->representation().IsDouble() && - IsDoubleOrFloatElementsKind(instr->elements_kind()))); + IsDoubleOrFloatElementsKind(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); - // An unsigned int array load might overflow and cause a deopt, make sure it - // has an environment. - bool can_deoptimize = instr->RequiresHoleCheck() || - elements_kind == EXTERNAL_UINT32_ELEMENTS || - elements_kind == UINT32_ELEMENTS; - return can_deoptimize ? AssignEnvironment(result) : result; + if ((instr->is_external() || instr->is_fixed_typed_array()) ? + // see LCodeGen::DoLoadKeyedExternalArray + ((elements_kind == EXTERNAL_UINT32_ELEMENTS || + elements_kind == UINT32_ELEMENTS) && + !instr->CheckFlag(HInstruction::kUint32)) : + // see LCodeGen::DoLoadKeyedFixedDoubleArray and + // LCodeGen::DoLoadKeyedFixedArray + instr->RequiresHoleCheck()) { + result = AssignEnvironment(result); + } + return result; } @@ -2280,11 +2301,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { // We need a temporary register for write barrier of the map field. LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; - LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp); - if (instr->field_representation().IsHeapObject()) { - if (!instr->value()->type().IsHeapObject()) { - return AssignEnvironment(result); - } + LInstruction* result = new(zone()) LStoreNamedField(obj, val, temp); + if (!instr->access().IsExternalMemory() && + instr->field_representation().IsHeapObject() && + !instr->value()->type().IsHeapObject()) { + result = AssignEnvironment(result); } return result; } @@ -2316,7 +2337,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)); } diff --git a/src/arm64/lithium-arm64.cc b/src/arm64/lithium-arm64.cc index 4bed135..1888aff 100644 --- a/src/arm64/lithium-arm64.cc +++ b/src/arm64/lithium-arm64.cc @@ -1074,63 +1074,61 @@ LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) { LInstruction* LChunkBuilder::DoChange(HChange* instr) { Representation from = instr->from(); Representation to = instr->to(); - + HValue* val = instr->value(); if (from.IsSmi()) { if (to.IsTagged()) { - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); return DefineSameAsFirst(new(zone()) LDummyUse(value)); } from = Representation::Tagged(); } - if (from.IsTagged()) { if (to.IsDouble()) { - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); LOperand* temp = TempRegister(); - LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); - return AssignEnvironment(DefineAsRegister(res)); + LInstruction* result = + DefineAsRegister(new(zone()) LNumberUntagD(value, temp)); + if (!val->representation().IsSmi()) result = AssignEnvironment(result); + return result; } else if (to.IsSmi()) { - LOperand* value = UseRegister(instr->value()); - if (instr->value()->type().IsSmi()) { + LOperand* value = UseRegister(val); + if (val->type().IsSmi()) { return DefineSameAsFirst(new(zone()) LDummyUse(value)); } return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); } else { ASSERT(to.IsInteger32()); - LInstruction* res = NULL; - - if (instr->value()->type().IsSmi() || - instr->value()->representation().IsSmi()) { - LOperand* value = UseRegisterAtStart(instr->value()); - res = DefineAsRegister(new(zone()) LSmiUntag(value, false)); + if (val->type().IsSmi() || val->representation().IsSmi()) { + LOperand* value = UseRegisterAtStart(val); + return DefineAsRegister(new(zone()) LSmiUntag(value, false)); } else { - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); LOperand* temp1 = TempRegister(); LOperand* temp2 = instr->CanTruncateToInt32() ? NULL : FixedTemp(d24); - res = DefineAsRegister(new(zone()) LTaggedToI(value, temp1, temp2)); - res = AssignEnvironment(res); + LInstruction* result = + DefineAsRegister(new(zone()) LTaggedToI(value, temp1, temp2)); + if (!val->representation().IsSmi()) { + // Note: Only deopts in deferred code. + result = AssignEnvironment(result); + } + return result; } - - return res; } } else if (from.IsDouble()) { if (to.IsTagged()) { info()->MarkAsDeferredCalling(); - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); LOperand* temp1 = TempRegister(); LOperand* temp2 = TempRegister(); - LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); return AssignPointerMap(DefineAsRegister(result)); } else { ASSERT(to.IsSmi() || to.IsInteger32()); - LOperand* value = UseRegister(instr->value()); - if (instr->CanTruncateToInt32()) { - LTruncateDoubleToIntOrSmi* result = - new(zone()) LTruncateDoubleToIntOrSmi(value); - return DefineAsRegister(result); + LOperand* value = UseRegister(val); + return DefineAsRegister(new(zone()) LTruncateDoubleToIntOrSmi(value)); } else { + LOperand* value = UseRegister(val); LDoubleToIntOrSmi* result = new(zone()) LDoubleToIntOrSmi(value); return AssignEnvironment(DefineAsRegister(result)); } @@ -1138,37 +1136,35 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { } else if (from.IsInteger32()) { info()->MarkAsDeferredCalling(); if (to.IsTagged()) { - if (instr->value()->CheckFlag(HInstruction::kUint32)) { - LOperand* value = UseRegister(instr->value()); - LNumberTagU* result = new(zone()) LNumberTagU(value, - TempRegister(), - TempRegister()); - return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); + if (val->CheckFlag(HInstruction::kUint32)) { + LOperand* value = UseRegister(val); + LNumberTagU* result = + new(zone()) LNumberTagU(value, TempRegister(), TempRegister()); + return AssignPointerMap(DefineAsRegister(result)); } else { STATIC_ASSERT((kMinInt == Smi::kMinValue) && (kMaxInt == Smi::kMaxValue)); - LOperand* value = UseRegisterAtStart(instr->value()); + LOperand* value = UseRegisterAtStart(val); return DefineAsRegister(new(zone()) LSmiTag(value)); } } else if (to.IsSmi()) { - LOperand* value = UseRegisterAtStart(instr->value()); + LOperand* value = UseRegisterAtStart(val); LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); - if (instr->value()->CheckFlag(HInstruction::kUint32)) { + if (val->CheckFlag(HInstruction::kUint32)) { result = AssignEnvironment(result); } return result; } else { ASSERT(to.IsDouble()); - if (instr->value()->CheckFlag(HInstruction::kUint32)) { + if (val->CheckFlag(HInstruction::kUint32)) { return DefineAsRegister( - new(zone()) LUint32ToDouble(UseRegisterAtStart(instr->value()))); + new(zone()) LUint32ToDouble(UseRegisterAtStart(val))); } else { return DefineAsRegister( - new(zone()) LInteger32ToDouble(UseRegisterAtStart(instr->value()))); + new(zone()) LInteger32ToDouble(UseRegisterAtStart(val))); } } } - UNREACHABLE(); return NULL; } @@ -1189,21 +1185,20 @@ LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { - if (instr->CanOmitMapChecks()) { - // LCheckMaps does nothing in this case. - return new(zone()) LCheckMaps(NULL); - } else { - LOperand* value = UseRegisterAtStart(instr->value()); - LOperand* temp = TempRegister(); - - if (instr->has_migration_target()) { - info()->MarkAsDeferredCalling(); - LInstruction* result = new(zone()) LCheckMaps(value, temp); - return AssignPointerMap(AssignEnvironment(result)); - } else { - return AssignEnvironment(new(zone()) LCheckMaps(value, temp)); - } + LOperand* value = NULL; + LOperand* temp = NULL; + if (!instr->CanOmitMapChecks()) { + value = UseRegisterAtStart(instr->value()); + temp = TempRegister(); + if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); + } + LInstruction* result = new(zone()) LCheckMaps(value, temp); + if (!instr->CanOmitMapChecks()) { + // Note: Only deopts in deferred code. + result = AssignEnvironment(result); + if (instr->has_migration_target()) return AssignPointerMap(result); } + return result; } @@ -1418,8 +1413,12 @@ LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { LOperand* divisor = UseRegister(instr->right()); LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) ? NULL : TempRegister(); - LDivI* div = new(zone()) LDivI(dividend, divisor, temp); - return AssignEnvironment(DefineAsRegister(div)); + LInstruction* result = + DefineAsRegister(new(zone()) LDivI(dividend, divisor, temp)); + if (!instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { + result = AssignEnvironment(result); + } + return result; } @@ -1622,7 +1621,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; } @@ -1687,17 +1689,14 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { IsDoubleOrFloatElementsKind(instr->elements_kind()))); LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister(); - LLoadKeyedExternal* result = - new(zone()) LLoadKeyedExternal(elements, key, temp); - // An unsigned int array load might overflow and cause a deopt. Make sure it - // has an environment. - if (instr->RequiresHoleCheck() || - elements_kind == EXTERNAL_UINT32_ELEMENTS || - elements_kind == UINT32_ELEMENTS) { - return AssignEnvironment(DefineAsRegister(result)); - } else { - return DefineAsRegister(result); + LInstruction* result = DefineAsRegister( + new(zone()) LLoadKeyedExternal(elements, key, temp)); + if ((elements_kind == EXTERNAL_UINT32_ELEMENTS || + elements_kind == UINT32_ELEMENTS) && + !instr->CheckFlag(HInstruction::kUint32)) { + result = AssignEnvironment(result); } + return result; } } @@ -1885,13 +1884,10 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) { bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero); - bool needs_environment = can_overflow || bailout_on_minus_zero; HValue* least_const = instr->BetterLeftOperand(); HValue* most_const = instr->BetterRightOperand(); - LOperand* left; - // LMulConstI can handle a subset of constants: // With support for overflow detection: // -1, 0, 1, 2 @@ -1911,26 +1907,27 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) { IsPowerOf2(constant_abs - 1))))) { LConstantOperand* right = UseConstant(most_const); bool need_register = IsPowerOf2(constant_abs) && !small_constant; - left = need_register ? UseRegister(least_const) - : UseRegisterAtStart(least_const); - LMulConstIS* mul = new(zone()) LMulConstIS(left, right); - if (needs_environment) AssignEnvironment(mul); - return DefineAsRegister(mul); + LOperand* left = need_register ? UseRegister(least_const) + : UseRegisterAtStart(least_const); + LInstruction* result = + DefineAsRegister(new(zone()) LMulConstIS(left, right)); + if ((bailout_on_minus_zero && constant <= 0) || can_overflow) { + result = AssignEnvironment(result); + } + return result; } } - left = UseRegisterAtStart(least_const); // LMulI/S can handle all cases, but it requires that a register is // allocated for the second operand. - LInstruction* result; - if (instr->representation().IsSmi()) { - LOperand* right = UseRegisterAtStart(most_const); - result = DefineAsRegister(new(zone()) LMulS(left, right)); - } else { - LOperand* right = UseRegisterAtStart(most_const); - result = DefineAsRegister(new(zone()) LMulI(left, right)); + LOperand* left = UseRegisterAtStart(least_const); + LOperand* right = UseRegisterAtStart(most_const); + LInstruction* result = instr->representation().IsSmi() + ? DefineAsRegister(new(zone()) LMulS(left, right)) + : DefineAsRegister(new(zone()) LMulI(left, right)); + if ((bailout_on_minus_zero && least_const != most_const) || can_overflow) { + result = AssignEnvironment(result); } - if (needs_environment) AssignEnvironment(result); return result; } else if (instr->representation().IsDouble()) { return DoArithmeticD(Token::MUL, instr); @@ -2160,7 +2157,10 @@ LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { value = UseRegister(instr->value()); } LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp); - return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; + if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { + result = AssignEnvironment(result); + } + return result; } @@ -2294,7 +2294,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)); } @@ -2430,21 +2430,15 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { LOperand* temp1 = TempRegister(); LOperand* temp2 = TempRegister(); LOperand* temp3 = TempRegister(); - LMathAbsTagged* result = - new(zone()) LMathAbsTagged(context, input, temp1, temp2, temp3); - return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); + LInstruction* result = DefineAsRegister( + new(zone()) LMathAbsTagged(context, input, temp1, temp2, temp3)); + // Note: Only deopts in deferred code. + return AssignEnvironment(AssignPointerMap(result)); } else { LOperand* input = UseRegisterAtStart(instr->value()); - LMathAbs* result = new(zone()) LMathAbs(input); - if (r.IsDouble()) { - // The Double case can never fail so it doesn't need an environment. - return DefineAsRegister(result); - } else { - ASSERT(r.IsInteger32() || r.IsSmi()); - // The Integer32 and Smi cases need an environment because they can - // deoptimize on minimum representable number. - return AssignEnvironment(DefineAsRegister(result)); - } + LInstruction* result = DefineAsRegister(new(zone()) LMathAbs(input)); + if (!r.IsDouble()) result = AssignEnvironment(result); + return result; } } case kMathExp: { diff --git a/src/arm64/lithium-arm64.h b/src/arm64/lithium-arm64.h index fcb1552..d47a84f 100644 --- a/src/arm64/lithium-arm64.h +++ b/src/arm64/lithium-arm64.h @@ -927,7 +927,7 @@ class LCheckInstanceType V8_FINAL : public LTemplateInstruction<0, 1, 1> { class LCheckMaps V8_FINAL : public LTemplateInstruction<0, 1, 1> { public: - explicit LCheckMaps(LOperand* value, LOperand* temp = NULL) { + explicit LCheckMaps(LOperand* value, LOperand* temp) { inputs_[0] = value; temps_[0] = temp; } diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 384a21c..6eb5343 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -1882,29 +1882,23 @@ LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { LInstruction* LChunkBuilder::DoChange(HChange* instr) { Representation from = instr->from(); Representation to = instr->to(); + HValue* val = instr->value(); if (from.IsSmi()) { if (to.IsTagged()) { - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); return DefineSameAsFirst(new(zone()) LDummyUse(value)); } from = Representation::Tagged(); } - // Only mark conversions that might need to allocate as calling rather than - // all changes. This makes simple, non-allocating conversion not have to force - // building a stack frame. if (from.IsTagged()) { if (to.IsDouble()) { - LOperand* value = UseRegister(instr->value()); - // Temp register only necessary for minus zero check. + LOperand* value = UseRegister(val); LOperand* temp = TempRegister(); - LInstruction* result = DefineAsRegister( - new(zone()) LNumberUntagD(value, temp)); - if (!instr->value()->representation().IsSmi()) { - result = AssignEnvironment(result); - } + LInstruction* result = + DefineAsRegister(new(zone()) LNumberUntagD(value, temp)); + if (!val->representation().IsSmi()) result = AssignEnvironment(result); return result; } else if (to.IsSmi()) { - HValue* val = instr->value(); LOperand* value = UseRegister(val); if (val->type().IsSmi()) { return DefineSameAsFirst(new(zone()) LDummyUse(value)); @@ -1912,18 +1906,18 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); } else { ASSERT(to.IsInteger32()); - HValue* val = instr->value(); if (val->type().IsSmi() || val->representation().IsSmi()) { LOperand* value = UseRegister(val); return DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); } else { + LOperand* value = UseRegister(val); bool truncating = instr->CanTruncateToInt32(); LOperand* xmm_temp = (CpuFeatures::IsSafeForSnapshot(SSE2) && !truncating) ? FixedTemp(xmm1) : NULL; - LInstruction* result = DefineSameAsFirst( - new(zone()) LTaggedToI(UseRegister(val), xmm_temp)); - if (!instr->value()->representation().IsSmi()) { + LInstruction* result = + DefineSameAsFirst(new(zone()) LTaggedToI(value, xmm_temp)); + if (!val->representation().IsSmi()) { // Note: Only deopts in deferred code. result = AssignEnvironment(result); } @@ -1933,23 +1927,20 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { } else if (from.IsDouble()) { if (to.IsTagged()) { info()->MarkAsDeferredCalling(); - LOperand* value = UseRegisterAtStart(instr->value()); + LOperand* value = UseRegisterAtStart(val); LOperand* temp = FLAG_inline_new ? TempRegister() : NULL; - - // Make sure that temp and result_temp are different registers. LUnallocated* result_temp = TempRegister(); LNumberTagD* result = new(zone()) LNumberTagD(value, temp); return AssignPointerMap(Define(result, result_temp)); } else if (to.IsSmi()) { - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); return AssignEnvironment( DefineAsRegister(new(zone()) LDoubleToSmi(value))); } else { ASSERT(to.IsInteger32()); bool truncating = instr->CanTruncateToInt32(); bool needs_temp = CpuFeatures::IsSafeForSnapshot(SSE2) && !truncating; - LOperand* value = needs_temp ? - UseTempRegister(instr->value()) : UseRegister(instr->value()); + LOperand* value = needs_temp ? UseTempRegister(val) : UseRegister(val); LOperand* temp = needs_temp ? TempRegister() : NULL; LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value, temp)); @@ -1959,23 +1950,23 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { } else if (from.IsInteger32()) { info()->MarkAsDeferredCalling(); if (to.IsTagged()) { - HValue* val = instr->value(); - LOperand* value = UseRegister(val); if (!instr->CheckFlag(HValue::kCanOverflow)) { + LOperand* value = UseRegister(val); return DefineSameAsFirst(new(zone()) LSmiTag(value)); } else if (val->CheckFlag(HInstruction::kUint32)) { + LOperand* value = UseRegister(val); LOperand* temp1 = TempRegister(); - LOperand* temp2 = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1) - : NULL; + LOperand* temp2 = + CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1) : NULL; LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); return AssignPointerMap(DefineSameAsFirst(result)); } else { + LOperand* value = UseRegister(val); LOperand* temp = TempRegister(); LNumberTagI* result = new(zone()) LNumberTagI(value, temp); return AssignPointerMap(DefineSameAsFirst(result)); } } else if (to.IsSmi()) { - HValue* val = instr->value(); LOperand* value = UseRegister(val); LInstruction* result = DefineSameAsFirst(new(zone()) LSmiTag(value)); if (instr->CheckFlag(HValue::kCanOverflow)) { @@ -1984,13 +1975,12 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { return result; } else { ASSERT(to.IsDouble()); - if (instr->value()->CheckFlag(HInstruction::kUint32)) { + if (val->CheckFlag(HInstruction::kUint32)) { LOperand* temp = FixedTemp(xmm1); return DefineAsRegister( - new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp)); + new(zone()) LUint32ToDouble(UseRegister(val), temp)); } else { - return DefineAsRegister( - new(zone()) LInteger32ToDouble(Use(instr->value()))); + return DefineAsRegister(new(zone()) LInteger32ToDouble(Use(val))); } } } diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 9d99e91..f766ba4 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1804,26 +1804,21 @@ LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { LInstruction* LChunkBuilder::DoChange(HChange* instr) { Representation from = instr->from(); Representation to = instr->to(); + HValue* val = instr->value(); if (from.IsSmi()) { if (to.IsTagged()) { - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); return DefineSameAsFirst(new(zone()) LDummyUse(value)); } from = Representation::Tagged(); } - // Only mark conversions that might need to allocate as calling rather than - // all changes. This makes simple, non-allocating conversion not have to force - // building a stack frame. if (from.IsTagged()) { if (to.IsDouble()) { - LOperand* value = UseRegister(instr->value()); - LInstruction* res = DefineAsRegister(new(zone()) LNumberUntagD(value)); - if (!instr->value()->representation().IsSmi()) { - res = AssignEnvironment(res); - } - return res; + LOperand* value = UseRegister(val); + LInstruction* result = DefineAsRegister(new(zone()) LNumberUntagD(value)); + if (!val->representation().IsSmi()) result = AssignEnvironment(result); + return result; } else if (to.IsSmi()) { - HValue* val = instr->value(); LOperand* value = UseRegister(val); if (val->type().IsSmi()) { return DefineSameAsFirst(new(zone()) LDummyUse(value)); @@ -1831,78 +1826,73 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); } else { ASSERT(to.IsInteger32()); - HValue* val = instr->value(); - LOperand* value = UseRegister(val); if (val->type().IsSmi() || val->representation().IsSmi()) { + LOperand* value = UseRegister(val); return DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); } else { + LOperand* value = UseRegister(val); bool truncating = instr->CanTruncateToInt32(); LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1); - LInstruction* res = + LInstruction* result = DefineSameAsFirst(new(zone()) LTaggedToI(value, xmm_temp)); - if (!instr->value()->representation().IsSmi()) { + if (!val->representation().IsSmi()) { // Note: Only deopts in deferred code. - res = AssignEnvironment(res); + result = AssignEnvironment(result); } - return res; + return result; } } } else if (from.IsDouble()) { if (to.IsTagged()) { info()->MarkAsDeferredCalling(); - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); LOperand* temp = TempRegister(); - - // Make sure that temp and result_temp are different registers. LUnallocated* result_temp = TempRegister(); LNumberTagD* result = new(zone()) LNumberTagD(value, temp); return AssignPointerMap(Define(result, result_temp)); } else if (to.IsSmi()) { - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); return AssignEnvironment( DefineAsRegister(new(zone()) LDoubleToSmi(value))); } else { ASSERT(to.IsInteger32()); - LOperand* value = UseRegister(instr->value()); + LOperand* value = UseRegister(val); LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value)); - if (!instr->CanTruncateToInt32()) { - result = AssignEnvironment(result); - } + if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result); return result; } } else if (from.IsInteger32()) { info()->MarkAsDeferredCalling(); if (to.IsTagged()) { - HValue* val = instr->value(); - LOperand* value = UseRegister(val); if (!instr->CheckFlag(HValue::kCanOverflow)) { + LOperand* value = UseRegister(val); return DefineAsRegister(new(zone()) LSmiTag(value)); } else if (val->CheckFlag(HInstruction::kUint32)) { + LOperand* value = UseRegister(val); LOperand* temp1 = TempRegister(); LOperand* temp2 = FixedTemp(xmm1); LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); return AssignPointerMap(DefineSameAsFirst(result)); } else { + LOperand* value = UseRegister(val); LNumberTagI* result = new(zone()) LNumberTagI(value); return AssignPointerMap(DefineSameAsFirst(result)); } } else if (to.IsSmi()) { - HValue* val = instr->value(); LOperand* value = UseRegister(val); LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); if (instr->CheckFlag(HValue::kCanOverflow)) { - ASSERT(val->CheckFlag(HValue::kUint32)); result = AssignEnvironment(result); } return result; } else { - if (instr->value()->CheckFlag(HInstruction::kUint32)) { + ASSERT(to.IsDouble()); + if (val->CheckFlag(HInstruction::kUint32)) { LOperand* temp = FixedTemp(xmm1); return DefineAsRegister( - new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp)); + new(zone()) LUint32ToDouble(UseRegister(val), temp)); } else { - ASSERT(to.IsDouble()); - LOperand* value = Use(instr->value()); + LOperand* value = Use(val); return DefineAsRegister(new(zone()) LInteger32ToDouble(value)); } } -- 2.7.4