| Index: src/arm/lithium-arm.cc
|
| diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
|
| index ba44b509e1cc9f3d2e81b4131957e8f5ec513c0b..b9f6c33d400e24902139c980d58945bf7db48c65 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));
|
| }
|
|
|
|
|
|
|