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
This commit is contained in:
parent
0d04cba759
commit
51c209c609
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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: {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user