summaryrefslogtreecommitdiff
path: root/deps/v8/src/mips/lithium-codegen-mips.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/mips/lithium-codegen-mips.cc')
-rw-r--r--deps/v8/src/mips/lithium-codegen-mips.cc446
1 files changed, 250 insertions, 196 deletions
diff --git a/deps/v8/src/mips/lithium-codegen-mips.cc b/deps/v8/src/mips/lithium-codegen-mips.cc
index ae0d6283f4..1c8973fe7e 100644
--- a/deps/v8/src/mips/lithium-codegen-mips.cc
+++ b/deps/v8/src/mips/lithium-codegen-mips.cc
@@ -500,13 +500,18 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
HConstant* constant = chunk_->LookupConstant(op);
- ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
+ ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
return constant->handle();
}
bool LCodeGen::IsInteger32(LConstantOperand* op) const {
- return chunk_->LookupLiteralRepresentation(op).IsInteger32();
+ return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
+}
+
+
+bool LCodeGen::IsSmi(LConstantOperand* op) const {
+ return chunk_->LookupLiteralRepresentation(op).IsSmi();
}
@@ -516,6 +521,12 @@ int LCodeGen::ToInteger32(LConstantOperand* op) const {
}
+Smi* LCodeGen::ToSmi(LConstantOperand* op) const {
+ HConstant* constant = chunk_->LookupConstant(op);
+ return Smi::FromInt(constant->Integer32Value());
+}
+
+
double LCodeGen::ToDouble(LConstantOperand* op) const {
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(constant->HasDoubleValue());
@@ -916,8 +927,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
Handle<FixedArray> literals =
factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
- { ALLOW_HANDLE_DEREF(isolate(),
- "copying a ZoneList of handles into a FixedArray");
+ { AllowDeferredHandleDereference copy_handles;
for (int i = 0; i < deoptimization_literals_.length(); i++) {
literals->set(i, *deoptimization_literals_[i]);
}
@@ -1135,59 +1145,74 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
void LCodeGen::DoModI(LModI* instr) {
- Register scratch = scratch0();
- const Register left = ToRegister(instr->left());
- const Register result = ToRegister(instr->result());
+ HMod* hmod = instr->hydrogen();
+ HValue* left = hmod->left();
+ HValue* right = hmod->right();
+ if (hmod->HasPowerOf2Divisor()) {
+ const Register scratch = scratch0();
+ const Register left_reg = ToRegister(instr->left());
+ ASSERT(!left_reg.is(scratch));
+ const Register result_reg = ToRegister(instr->result());
+
+ // Note: The code below even works when right contains kMinInt.
+ int32_t divisor = Abs(right->GetInteger32Constant());
+
+ __ mov(scratch, left_reg);
+
+ Label left_is_not_negative, done;
+ if (left->CanBeNegative()) {
+ __ Branch(USE_DELAY_SLOT, &left_is_not_negative,
+ ge, left_reg, Operand(zero_reg));
+ __ subu(result_reg, zero_reg, left_reg);
+ __ And(result_reg, result_reg, divisor - 1);
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
+ }
+ __ Branch(USE_DELAY_SLOT, &done);
+ __ subu(result_reg, zero_reg, result_reg);
+ }
- Label done;
+ __ bind(&left_is_not_negative);
+ __ And(result_reg, scratch, divisor - 1);
+ __ bind(&done);
- if (instr->hydrogen()->HasPowerOf2Divisor()) {
- Register scratch = scratch0();
- ASSERT(!left.is(scratch));
- __ mov(scratch, left);
- int32_t p2constant = HConstant::cast(
- instr->hydrogen()->right())->Integer32Value();
- ASSERT(p2constant != 0);
- // Result always takes the sign of the dividend (left).
- p2constant = abs(p2constant);
-
- Label positive_dividend;
- __ Branch(USE_DELAY_SLOT, &positive_dividend, ge, left, Operand(zero_reg));
- __ subu(result, zero_reg, left);
- __ And(result, result, p2constant - 1);
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
- }
- __ Branch(USE_DELAY_SLOT, &done);
- __ subu(result, zero_reg, result);
- __ bind(&positive_dividend);
- __ And(result, scratch, p2constant - 1);
} else {
+ // TODO(svenpanne) Add right->has_fixed_right_arg() case.
+
+ const Register scratch = scratch0();
+ const Register left_reg = ToRegister(instr->left());
+ const Register result_reg = ToRegister(instr->result());
+
// div runs in the background while we check for special cases.
- Register right = EmitLoadRegister(instr->right(), scratch);
- __ div(left, right);
+ Register right_reg = EmitLoadRegister(instr->right(), scratch);
+ __ div(left_reg, right_reg);
- // Check for x % 0.
- if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
- DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
+ Label done;
+ // Check for x % 0, we have to deopt in this case because we can't return a
+ // NaN.
+ if (right->CanBeZero()) {
+ DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg));
}
- // Check for (kMinInt % -1).
- if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+ // Check for kMinInt % -1, we have to deopt if we care about -0, because we
+ // can't return that.
+ if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
Label left_not_min_int;
- __ Branch(&left_not_min_int, ne, left, Operand(kMinInt));
- DeoptimizeIf(eq, instr->environment(), right, Operand(-1));
+ __ Branch(&left_not_min_int, ne, left_reg, Operand(kMinInt));
+ // TODO(svenpanne) Don't deopt when we don't care about -0.
+ DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1));
__ bind(&left_not_min_int);
}
- __ Branch(USE_DELAY_SLOT, &done, ge, left, Operand(zero_reg));
- __ mfhi(result);
+ // TODO(svenpanne) Only emit the test/deopt if we have to.
+ __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg));
+ __ mfhi(result_reg);
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
}
+ __ bind(&done);
}
- __ bind(&done);
}
@@ -1489,7 +1514,11 @@ void LCodeGen::DoSubI(LSubI* instr) {
void LCodeGen::DoConstantI(LConstantI* instr) {
- ASSERT(instr->result()->IsRegister());
+ __ li(ToRegister(instr->result()), Operand(instr->value()));
+}
+
+
+void LCodeGen::DoConstantS(LConstantS* instr) {
__ li(ToRegister(instr->result()), Operand(instr->value()));
}
@@ -1504,7 +1533,7 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
void LCodeGen::DoConstantT(LConstantT* instr) {
Handle<Object> value = instr->value();
- ALLOW_HANDLE_DEREF(isolate(), "smi check");
+ AllowDeferredHandleDereference smi_check;
if (value->IsSmi()) {
__ li(ToRegister(instr->result()), Operand(value));
} else {
@@ -1600,11 +1629,35 @@ void LCodeGen::DoDateField(LDateField* instr) {
void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
- SeqStringSetCharGenerator::Generate(masm(),
- instr->encoding(),
- ToRegister(instr->string()),
- ToRegister(instr->index()),
- ToRegister(instr->value()));
+ Register string = ToRegister(instr->string());
+ Register index = ToRegister(instr->index());
+ Register value = ToRegister(instr->value());
+ Register scratch = scratch0();
+ String::Encoding encoding = instr->encoding();
+
+ if (FLAG_debug_code) {
+ __ lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
+ __ lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
+
+ __ And(at, at, Operand(kStringRepresentationMask | kStringEncodingMask));
+ static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+ static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+ __ Subu(at, at, Operand(encoding == String::ONE_BYTE_ENCODING
+ ? one_byte_seq_type : two_byte_seq_type));
+ __ Check(eq, "Unexpected string type", at, Operand(zero_reg));
+ }
+
+ __ Addu(scratch,
+ string,
+ Operand(SeqString::kHeaderSize - kHeapObjectTag));
+ if (encoding == String::ONE_BYTE_ENCODING) {
+ __ Addu(at, scratch, index);
+ __ sb(value, MemOperand(at));
+ } else {
+ __ sll(at, index, 1);
+ __ Addu(at, scratch, at);
+ __ sh(value, MemOperand(at));
+ }
}
@@ -1837,10 +1890,12 @@ void LCodeGen::DoBranch(LBranch* instr) {
int false_block = chunk_->LookupDestination(instr->false_block_id());
Representation r = instr->hydrogen()->value()->representation();
- if (r.IsInteger32()) {
+ if (r.IsInteger32() || r.IsSmi()) {
+ ASSERT(!info()->IsStub());
Register reg = ToRegister(instr->value());
EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
} else if (r.IsDouble()) {
+ ASSERT(!info()->IsStub());
DoubleRegister reg = ToDoubleRegister(instr->value());
// Test the double value. Zero and NaN are false.
EmitBranchF(true_block, false_block, nue, reg, kDoubleRegZero);
@@ -1849,9 +1904,11 @@ void LCodeGen::DoBranch(LBranch* instr) {
Register reg = ToRegister(instr->value());
HType type = instr->hydrogen()->value()->type();
if (type.IsBoolean()) {
+ ASSERT(!info()->IsStub());
__ LoadRoot(at, Heap::kTrueValueRootIndex);
EmitBranch(true_block, false_block, eq, reg, Operand(at));
} else if (type.IsSmi()) {
+ ASSERT(!info()->IsStub());
EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
} else {
Label* true_label = chunk_->GetAssemblyLabel(true_block);
@@ -2018,11 +2075,23 @@ void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
Operand cmp_right = Operand(0);
if (right->IsConstantOperand()) {
- cmp_left = ToRegister(left);
- cmp_right = Operand(ToInteger32(LConstantOperand::cast(right)));
+ int32_t value = ToInteger32(LConstantOperand::cast(right));
+ if (instr->hydrogen_value()->representation().IsSmi()) {
+ cmp_left = ToRegister(left);
+ cmp_right = Operand(Smi::FromInt(value));
+ } else {
+ cmp_left = ToRegister(left);
+ cmp_right = Operand(value);
+ }
} else if (left->IsConstantOperand()) {
- cmp_left = ToRegister(right);
- cmp_right = Operand(ToInteger32(LConstantOperand::cast(left)));
+ int32_t value = ToInteger32(LConstantOperand::cast(left));
+ if (instr->hydrogen_value()->representation().IsSmi()) {
+ cmp_left = ToRegister(right);
+ cmp_right = Operand(Smi::FromInt(value));
+ } else {
+ cmp_left = ToRegister(right);
+ cmp_right = Operand(value);
+ }
// We transposed the operands. Reverse the condition.
cond = ReverseCondition(cond);
} else {
@@ -2537,8 +2606,8 @@ void LCodeGen::DoReturn(LReturn* instr) {
int no_frame_start = -1;
if (NeedsEagerFrame()) {
__ mov(sp, fp);
- __ Pop(ra, fp);
no_frame_start = masm_->pc_offset();
+ __ Pop(ra, fp);
}
if (instr->has_constant_parameter_count()) {
int parameter_count = ToInteger32(instr->constant_parameter_count());
@@ -2681,7 +2750,8 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
- int offset = instr->hydrogen()->offset();
+ HObjectAccess access = instr->hydrogen()->access();
+ int offset = access.offset();
Register object = ToRegister(instr->object());
if (instr->hydrogen()->representation().IsDouble()) {
DoubleRegister result = ToDoubleRegister(instr->result());
@@ -2690,7 +2760,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
}
Register result = ToRegister(instr->result());
- if (instr->hydrogen()->is_in_object()) {
+ if (access.IsInobject()) {
__ lw(result, FieldMemOperand(object, offset));
} else {
__ lw(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
@@ -2758,9 +2828,7 @@ void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
bool last = (i == map_count - 1);
Handle<Map> map = instr->hydrogen()->types()->at(i);
Label check_passed;
- __ CompareMapAndBranch(
- object_map, map, &check_passed,
- eq, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS);
+ __ CompareMapAndBranch(object_map, map, &check_passed, eq, &check_passed);
if (last && !need_generic) {
DeoptimizeIf(al, instr->environment());
__ bind(&check_passed);
@@ -2886,7 +2954,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
key = ToRegister(instr->key());
}
int element_size_shift = ElementsKindToShiftSize(elements_kind);
- int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+ int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int additional_offset = instr->additional_index() << element_size_shift;
@@ -2960,7 +3028,7 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
Register scratch = scratch0();
int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
- int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+ int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int constant_key = 0;
if (key_is_constant) {
@@ -3005,7 +3073,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
// representation for the key to be an integer, the input gets replaced
// during bound check elimination with the index argument to the bounds
// check, which can be tagged, so that case must be handled here, too.
- if (instr->hydrogen()->key()->representation().IsTagged()) {
+ if (instr->hydrogen()->key()->representation().IsSmi()) {
__ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize);
__ addu(scratch, elements, scratch);
} else {
@@ -3616,7 +3684,10 @@ void LCodeGen::DoPower(LPower* instr) {
ASSERT(ToDoubleRegister(instr->left()).is(f2));
ASSERT(ToDoubleRegister(instr->result()).is(f0));
- if (exponent_type.IsTagged()) {
+ if (exponent_type.IsSmi()) {
+ MathPowStub stub(MathPowStub::TAGGED);
+ __ CallStub(&stub);
+ } else if (exponent_type.IsTagged()) {
Label no_deopt;
__ JumpIfSmi(a2, &no_deopt);
__ lw(t3, FieldMemOperand(a2, HeapObject::kMapOffset));
@@ -3864,14 +3935,17 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
__ li(a0, Operand(instr->arity()));
__ li(a2, Operand(instr->hydrogen()->property_cell()));
ElementsKind kind = instr->hydrogen()->elements_kind();
+ bool disable_allocation_sites =
+ (AllocationSiteInfo::GetMode(kind) == TRACK_ALLOCATION_SITE);
+
if (instr->arity() == 0) {
- ArrayNoArgumentConstructorStub stub(kind);
+ ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
} else if (instr->arity() == 1) {
- ArraySingleArgumentConstructorStub stub(kind);
+ ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
} else {
- ArrayNArgumentsConstructorStub stub(kind);
+ ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
}
}
@@ -3894,17 +3968,12 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
Register object = ToRegister(instr->object());
Register scratch = scratch0();
- int offset = instr->offset();
+ HObjectAccess access = instr->hydrogen()->access();
+ int offset = access.offset();
Handle<Map> transition = instr->transition();
- if (FLAG_track_fields && representation.IsSmi()) {
- Register value = ToRegister(instr->value());
- __ SmiTagCheckOverflow(value, value, scratch);
- if (!instr->hydrogen()->value()->range()->IsInSmiRange()) {
- DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
- }
- } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
+ if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
Register value = ToRegister(instr->value());
if (!instr->hydrogen()->value()->type().IsHeapObject()) {
__ And(scratch, value, Operand(kSmiTagMask));
@@ -3912,7 +3981,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
}
} else if (FLAG_track_double_fields && representation.IsDouble()) {
ASSERT(transition.is_null());
- ASSERT(instr->is_in_object());
+ ASSERT(access.IsInobject());
ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
DoubleRegister value = ToDoubleRegister(instr->value());
__ sdc1(value, FieldMemOperand(object, offset));
@@ -3945,7 +4014,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
HType type = instr->hydrogen()->value()->type();
SmiCheck check_needed =
type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
- if (instr->is_in_object()) {
+ if (access.IsInobject()) {
__ sw(value, FieldMemOperand(object, offset));
if (instr->hydrogen()->NeedsWriteBarrier()) {
// Update the write barrier for the object for in-object properties.
@@ -3996,7 +4065,7 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
if (instr->index()->IsConstantOperand()) {
int constant_index =
ToInteger32(LConstantOperand::cast(instr->index()));
- if (instr->hydrogen()->length()->representation().IsTagged()) {
+ if (instr->hydrogen()->length()->representation().IsSmi()) {
__ li(at, Operand(Smi::FromInt(constant_index)));
} else {
__ li(at, Operand(constant_index));
@@ -4029,7 +4098,7 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
key = ToRegister(instr->key());
}
int element_size_shift = ElementsKindToShiftSize(elements_kind);
- int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+ int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
int additional_offset = instr->additional_index() << element_size_shift;
@@ -4107,7 +4176,7 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
key = ToRegister(instr->key());
}
int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
- int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+ int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
? (element_size_shift - kSmiTagSize) : element_size_shift;
if (key_is_constant) {
__ Addu(scratch, elements, Operand((constant_key << element_size_shift) +
@@ -4157,7 +4226,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
// representation for the key to be an integer, the input gets replaced
// during bound check elimination with the index argument to the bounds
// check, which can be tagged, so that case must be handled here, too.
- if (instr->hydrogen()->key()->representation().IsTagged()) {
+ if (instr->hydrogen()->key()->representation().IsSmi()) {
__ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize);
__ addu(scratch, elements, scratch);
} else {
@@ -4407,6 +4476,21 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
}
+void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) {
+ LOperand* input = instr->value();
+ ASSERT(input->IsRegister());
+ LOperand* output = instr->result();
+ ASSERT(output->IsRegister());
+ Register scratch = scratch0();
+
+ __ SmiTagCheckOverflow(ToRegister(output), ToRegister(input), scratch);
+ if (!instr->hydrogen()->value()->HasRange() ||
+ !instr->hydrogen()->value()->range()->IsInSmiRange()) {
+ DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
+ }
+}
+
+
void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
LOperand* input = instr->value();
LOperand* output = instr->result();
@@ -4618,7 +4702,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg,
DoubleRegister result_reg,
- bool deoptimize_on_undefined,
+ bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode) {
@@ -4626,23 +4710,30 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
Label load_smi, heap_number, done;
- if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+ STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
+ NUMBER_CANDIDATE_IS_ANY_TAGGED);
+ if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
__ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
// Heap number map check.
__ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
- if (deoptimize_on_undefined) {
+ if (!allow_undefined_as_nan) {
DeoptimizeIf(ne, env, scratch, Operand(at));
} else {
- Label heap_number;
+ Label heap_number, convert;
__ Branch(&heap_number, eq, scratch, Operand(at));
+ // Convert undefined (and hole) to NaN.
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
+ if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
+ __ Branch(&convert, eq, input_reg, Operand(at));
+ __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
+ }
DeoptimizeIf(ne, env, input_reg, Operand(at));
- // Convert undefined to NaN.
+ __ bind(&convert);
__ LoadRoot(at, Heap::kNanValueRootIndex);
__ ldc1(result_reg, FieldMemOperand(at, HeapNumber::kValueOffset));
__ Branch(&done);
@@ -4658,14 +4749,6 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
DeoptimizeIf(eq, env, scratch, Operand(HeapNumber::kSignMask));
}
__ Branch(&done);
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_OR_HOLE) {
- __ SmiUntag(scratch, input_reg);
- DeoptimizeIf(Ugreater_equal, env, scratch, Operand(zero_reg));
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE) {
- __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
- __ Move(result_reg,
- FixedDoubleArray::hole_nan_as_double());
- __ Branch(&done);
} else {
__ SmiUntag(scratch, input_reg);
ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
@@ -4798,24 +4881,18 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
HValue* value = instr->hydrogen()->value();
if (value->type().IsSmi()) {
- if (value->IsLoadKeyed()) {
- HLoadKeyed* load = HLoadKeyed::cast(value);
- if (load->UsesMustHandleHole()) {
- if (load->hole_mode() == ALLOW_RETURN_HOLE) {
- mode = NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE;
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI_OR_HOLE;
- }
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI;
+ mode = NUMBER_CANDIDATE_IS_SMI;
+ } else if (value->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(value);
+ if (load->UsesMustHandleHole()) {
+ if (load->hole_mode() == ALLOW_RETURN_HOLE) {
+ mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
}
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI;
}
}
EmitNumberUntagD(input_reg, result_reg,
- instr->hydrogen()->deoptimize_on_undefined(),
+ instr->hydrogen()->allow_undefined_as_nan(),
instr->hydrogen()->deoptimize_on_minus_zero(),
instr->environment(),
mode);
@@ -4850,10 +4927,62 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
// Deopt if the operation did not succeed (except_flag != 0).
DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
+
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ Label done;
+ __ Branch(&done, ne, result_reg, Operand(zero_reg));
+ __ mfc1(scratch1, double_input.high());
+ __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
+ DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
+ __ bind(&done);
+ }
}
}
+void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
+ Register result_reg = ToRegister(instr->result());
+ Register scratch1 = scratch0();
+ Register scratch2 = ToRegister(instr->temp());
+ DoubleRegister double_input = ToDoubleRegister(instr->value());
+
+ if (instr->truncating()) {
+ Register scratch3 = ToRegister(instr->temp2());
+ FPURegister single_scratch = double_scratch0().low();
+ __ EmitECMATruncate(result_reg,
+ double_input,
+ single_scratch,
+ scratch1,
+ scratch2,
+ scratch3);
+ } else {
+ Register except_flag = scratch2;
+
+ __ EmitFPUTruncate(kRoundToMinusInf,
+ result_reg,
+ double_input,
+ scratch1,
+ double_scratch0(),
+ except_flag,
+ kCheckForInexactConversion);
+
+ // Deopt if the operation did not succeed (except_flag != 0).
+ DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
+
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ Label done;
+ __ Branch(&done, ne, result_reg, Operand(zero_reg));
+ __ mfc1(scratch1, double_input.high());
+ __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
+ DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
+ __ bind(&done);
+ }
+ }
+ __ SmiTagCheckOverflow(result_reg, result_reg, scratch1);
+ DeoptimizeIf(lt, instr->environment(), scratch1, Operand(zero_reg));
+}
+
+
void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
LOperand* input = instr->value();
__ And(at, ToRegister(input), Operand(kSmiTagMask));
@@ -4910,7 +5039,7 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
Register reg = ToRegister(instr->value());
Handle<JSFunction> target = instr->hydrogen()->target();
- ALLOW_HANDLE_DEREF(isolate(), "smi check");
+ AllowDeferredHandleDereference smi_check;
if (isolate()->heap()->InNewSpace(*target)) {
Register reg = ToRegister(instr->value());
Handle<JSGlobalPropertyCell> cell =
@@ -4928,10 +5057,9 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
void LCodeGen::DoCheckMapCommon(Register map_reg,
Handle<Map> map,
- CompareMapMode mode,
LEnvironment* env) {
Label success;
- __ CompareMapAndBranch(map_reg, map, &success, eq, &success, mode);
+ __ CompareMapAndBranch(map_reg, map, &success, eq, &success);
DeoptimizeIf(al, env);
__ bind(&success);
}
@@ -4947,11 +5075,10 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
__ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
for (int i = 0; i < map_set->length() - 1; i++) {
Handle<Map> map = map_set->at(i);
- __ CompareMapAndBranch(
- map_reg, map, &success, eq, &success, REQUIRE_EXACT_MAP);
+ __ CompareMapAndBranch(map_reg, map, &success, eq, &success);
}
Handle<Map> map = map_set->last();
- DoCheckMapCommon(map_reg, map, REQUIRE_EXACT_MAP, instr->environment());
+ DoCheckMapCommon(map_reg, map, instr->environment());
__ bind(&success);
}
@@ -5023,89 +5150,12 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
for (int i = 0; i < prototypes->length(); i++) {
__ LoadHeapObject(prototype_reg, prototypes->at(i));
__ lw(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
- DoCheckMapCommon(map_reg,
- maps->at(i),
- ALLOW_ELEMENT_TRANSITION_MAPS,
- instr->environment());
+ DoCheckMapCommon(map_reg, maps->at(i), instr->environment());
}
}
}
-void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
- class DeferredAllocateObject: public LDeferredCode {
- public:
- DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
- : LDeferredCode(codegen), instr_(instr) { }
- virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); }
- virtual LInstruction* instr() { return instr_; }
- private:
- LAllocateObject* instr_;
- };
-
- DeferredAllocateObject* deferred =
- new(zone()) DeferredAllocateObject(this, instr);
-
- Register result = ToRegister(instr->result());
- Register scratch = ToRegister(instr->temp());
- Register scratch2 = ToRegister(instr->temp2());
- Handle<JSFunction> constructor = instr->hydrogen()->constructor();
- Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
- int instance_size = initial_map->instance_size();
- ASSERT(initial_map->pre_allocated_property_fields() +
- initial_map->unused_property_fields() -
- initial_map->inobject_properties() == 0);
-
- __ Allocate(instance_size, result, scratch, scratch2, deferred->entry(),
- TAG_OBJECT);
-
- __ bind(deferred->exit());
- if (FLAG_debug_code) {
- Label is_in_new_space;
- __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
- __ Abort("Allocated object is not in new-space");
- __ bind(&is_in_new_space);
- }
-
- // Load the initial map.
- Register map = scratch;
- __ LoadHeapObject(map, constructor);
- __ lw(map, FieldMemOperand(map, JSFunction::kPrototypeOrInitialMapOffset));
-
- // Initialize map and fields of the newly allocated object.
- ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
- __ sw(map, FieldMemOperand(result, JSObject::kMapOffset));
- __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
- __ sw(scratch, FieldMemOperand(result, JSObject::kElementsOffset));
- __ sw(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset));
- if (initial_map->inobject_properties() != 0) {
- __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
- for (int i = 0; i < initial_map->inobject_properties(); i++) {
- int property_offset = JSObject::kHeaderSize + i * kPointerSize;
- __ sw(scratch, FieldMemOperand(result, property_offset));
- }
- }
-}
-
-
-void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
- Register result = ToRegister(instr->result());
- Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
- int instance_size = initial_map->instance_size();
-
- // TODO(3095996): Get rid of this. For now, we need to make the
- // result register contain a valid pointer because it is already
- // contained in the register pointer map.
- __ mov(result, zero_reg);
-
- PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
- __ li(a0, Operand(Smi::FromInt(instance_size)));
- __ push(a0);
- CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
- __ StoreToSafepointRegisterSlot(v0, result);
-}
-
-
void LCodeGen::DoAllocate(LAllocate* instr) {
class DeferredAllocate: public LDeferredCode {
public:
@@ -5130,7 +5180,10 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
}
if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
+ ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
+ } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+ flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
}
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
@@ -5169,11 +5222,12 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
}
if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
- CallRuntimeFromDeferred(
- Runtime::kAllocateInOldPointerSpace, 1, instr);
+ ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+ CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr);
+ } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+ CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr);
} else {
- CallRuntimeFromDeferred(
- Runtime::kAllocateInNewSpace, 1, instr);
+ CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
}
__ StoreToSafepointRegisterSlot(v0, result);
}