if ((cond == lt) || (cond == gt)) {
__ JumpIfObjectType(right, scratch, scratch, FIRST_SPEC_OBJECT_TYPE, slow,
ge);
+ } else if (cond == eq) {
+ __ JumpIfHeapNumber(right, &heap_number);
} else {
Register right_type = scratch;
__ JumpIfObjectType(right, right_type, right_type, HEAP_NUMBER_TYPE,
&heap_number);
// Comparing JS objects with <=, >= is complicated.
- if (cond != eq) {
- __ Cmp(right_type, FIRST_SPEC_OBJECT_TYPE);
- __ B(ge, slow);
- // Normally here we fall through to return_equal, but undefined is
- // special: (undefined == undefined) == true, but
- // (undefined <= undefined) == false! See ECMAScript 11.8.5.
- if ((cond == le) || (cond == ge)) {
- __ Cmp(right_type, ODDBALL_TYPE);
- __ B(ne, &return_equal);
- __ JumpIfNotRoot(right, Heap::kUndefinedValueRootIndex, &return_equal);
- if (cond == le) {
- // undefined <= undefined should fail.
- __ Mov(result, GREATER);
- } else {
- // undefined >= undefined should fail.
- __ Mov(result, LESS);
- }
- __ Ret();
+ __ Cmp(right_type, FIRST_SPEC_OBJECT_TYPE);
+ __ B(ge, slow);
+ // Normally here we fall through to return_equal, but undefined is
+ // special: (undefined == undefined) == true, but
+ // (undefined <= undefined) == false! See ECMAScript 11.8.5.
+ if ((cond == le) || (cond == ge)) {
+ __ Cmp(right_type, ODDBALL_TYPE);
+ __ B(ne, &return_equal);
+ __ JumpIfNotRoot(right, Heap::kUndefinedValueRootIndex, &return_equal);
+ if (cond == le) {
+ // undefined <= undefined should fail.
+ __ Mov(result, GREATER);
+ } else {
+ // undefined >= undefined should fail.
+ __ Mov(result, LESS);
}
+ __ Ret();
}
}
Register right,
FPRegister left_d,
FPRegister right_d,
- Register scratch,
Label* slow,
bool strict) {
- DCHECK(!AreAliased(left, right, scratch));
DCHECK(!AreAliased(left_d, right_d));
DCHECK((left.is(x0) && right.is(x1)) ||
(right.is(x0) && left.is(x1)));
// If right is not a number and left is a smi, then strict equality cannot
// succeed. Return non-equal.
Label is_heap_number;
- __ JumpIfObjectType(right, scratch, scratch, HEAP_NUMBER_TYPE,
- &is_heap_number);
+ __ JumpIfHeapNumber(right, &is_heap_number);
// Register right is a non-zero pointer, which is a valid NOT_EQUAL result.
if (!right.is(result)) {
__ Mov(result, NOT_EQUAL);
} else {
// Smi compared non-strictly with a non-smi, non-heap-number. Call the
// runtime.
- __ JumpIfNotObjectType(right, scratch, scratch, HEAP_NUMBER_TYPE, slow);
+ __ JumpIfNotHeapNumber(right, slow);
}
// Left is the smi. Right is a heap number. Load right value into right_d, and
// If left is not a number and right is a smi then strict equality cannot
// succeed. Return non-equal.
Label is_heap_number;
- __ JumpIfObjectType(left, scratch, scratch, HEAP_NUMBER_TYPE,
- &is_heap_number);
+ __ JumpIfHeapNumber(left, &is_heap_number);
// Register left is a non-zero pointer, which is a valid NOT_EQUAL result.
if (!left.is(result)) {
__ Mov(result, NOT_EQUAL);
} else {
// Smi compared non-strictly with a non-smi, non-heap-number. Call the
// runtime.
- __ JumpIfNotObjectType(left, scratch, scratch, HEAP_NUMBER_TYPE, slow);
+ __ JumpIfNotHeapNumber(left, slow);
}
// Right is the smi. Left is a heap number. Load left value into left_d, and
static void CompareICStub_CheckInputType(MacroAssembler* masm, Register input,
- Register scratch,
CompareICState::State expected,
Label* fail) {
Label ok;
__ JumpIfNotSmi(input, fail);
} else if (expected == CompareICState::NUMBER) {
__ JumpIfSmi(input, &ok);
- __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
- DONT_DO_SMI_CHECK);
+ __ JumpIfNotHeapNumber(input, fail);
}
// We could be strict about internalized/non-internalized here, but as long as
// hydrogen doesn't care, the stub doesn't have to care either.
Condition cond = GetCondition();
Label miss;
- CompareICStub_CheckInputType(masm, lhs, x2, left(), &miss);
- CompareICStub_CheckInputType(masm, rhs, x3, right(), &miss);
+ CompareICStub_CheckInputType(masm, lhs, left(), &miss);
+ CompareICStub_CheckInputType(masm, rhs, right(), &miss);
Label slow; // Call builtin.
Label not_smis, both_loaded_as_doubles;
// rhs_d, left into lhs_d.
FPRegister rhs_d = d0;
FPRegister lhs_d = d1;
- EmitSmiNonsmiComparison(masm, lhs, rhs, lhs_d, rhs_d, x10, &slow, strict());
+ EmitSmiNonsmiComparison(masm, lhs, rhs, lhs_d, rhs_d, &slow, strict());
__ Bind(&both_loaded_as_doubles);
// The arguments have been converted to doubles and stored in rhs_d and
__ Bind(&index_not_smi_);
// If index is a heap number, try converting it to an integer.
- __ CheckMap(index_,
- result_,
- Heap::kHeapNumberMapRootIndex,
- index_not_number_,
- DONT_DO_SMI_CHECK);
+ __ JumpIfNotHeapNumber(index_, index_not_number_);
call_helper.BeforeCall(masm);
// Save object_ on the stack and pass index_ as argument for runtime call.
__ Push(object_, index_);
// Load rhs if it's a heap number.
__ JumpIfSmi(rhs, &handle_lhs);
- __ CheckMap(rhs, x10, Heap::kHeapNumberMapRootIndex, &maybe_undefined1,
- DONT_DO_SMI_CHECK);
+ __ JumpIfNotHeapNumber(rhs, &maybe_undefined1);
__ Ldr(rhs_d, FieldMemOperand(rhs, HeapNumber::kValueOffset));
// Load lhs if it's a heap number.
__ Bind(&handle_lhs);
__ JumpIfSmi(lhs, &values_in_d_regs);
- __ CheckMap(lhs, x10, Heap::kHeapNumberMapRootIndex, &maybe_undefined2,
- DONT_DO_SMI_CHECK);
+ __ JumpIfNotHeapNumber(lhs, &maybe_undefined2);
__ Ldr(lhs_d, FieldMemOperand(lhs, HeapNumber::kValueOffset));
__ Bind(&values_in_d_regs);
if (Token::IsOrderedRelationalCompareOp(op())) {
__ JumpIfNotRoot(rhs, Heap::kUndefinedValueRootIndex, &miss);
__ JumpIfSmi(lhs, &unordered);
- __ JumpIfNotObjectType(lhs, x10, x10, HEAP_NUMBER_TYPE, &maybe_undefined2);
+ __ JumpIfNotHeapNumber(lhs, &maybe_undefined2);
__ B(&unordered);
}
&if_true, &if_false, &fall_through);
// Only a HeapNumber can be -0.0, so return false if we have something else.
- __ CheckMap(x0, x1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK);
+ __ JumpIfNotHeapNumber(x0, if_false, DO_SMI_CHECK);
// Test the bit pattern.
__ Ldr(x10, FieldMemOperand(x0, HeapNumber::kValueOffset));
DCHECK(input_rep.IsSmiOrTagged());
return AssignEnvironment(
DefineAsRegister(new(zone()) LClampTToUint8(reg,
- TempRegister(),
TempDoubleRegister())));
}
}
};
-class LClampTToUint8 FINAL : public LTemplateInstruction<1, 1, 2> {
+class LClampTToUint8 FINAL : public LTemplateInstruction<1, 1, 1> {
public:
- LClampTToUint8(LOperand* unclamped, LOperand* temp1, LOperand* temp2) {
+ LClampTToUint8(LOperand* unclamped, LOperand* temp1) {
inputs_[0] = unclamped;
temps_[0] = temp1;
- temps_[1] = temp2;
}
LOperand* unclamped() { return inputs_[0]; }
LOperand* temp1() { return temps_[0]; }
- LOperand* temp2() { return temps_[1]; }
DECLARE_CONCRETE_INSTRUCTION(ClampTToUint8, "clamp-t-to-uint8")
};
}
+void LCodeGen::DeoptimizeIfNotHeapNumber(Register object, LInstruction* instr) {
+ __ CompareObjectMap(object, Heap::kHeapNumberMapRootIndex);
+ DeoptimizeIf(ne, instr, "not heap number");
+}
+
+
void LCodeGen::DeoptimizeIfBitSet(Register rt, int bit, LInstruction* instr,
const char* detail) {
DeoptimizeBranch(instr, detail, reg_bit_set, rt, bit);
EmitGoto(left_block);
} else if (left_block == next_block) {
branch.EmitInverted(chunk_->GetAssemblyLabel(right_block));
- } else if (right_block == next_block) {
- branch.Emit(chunk_->GetAssemblyLabel(left_block));
} else {
branch.Emit(chunk_->GetAssemblyLabel(left_block));
- __ B(chunk_->GetAssemblyLabel(right_block));
+ if (right_block != next_block) {
+ __ B(chunk_->GetAssemblyLabel(right_block));
+ }
}
}
void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
Register input = ToRegister(instr->unclamped());
Register result = ToRegister32(instr->result());
- Register scratch = ToRegister(instr->temp1());
Label done;
// Both smi and heap number cases are handled.
// Check for heap number.
Label is_heap_number;
- __ Ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
- __ JumpIfRoot(scratch, Heap::kHeapNumberMapRootIndex, &is_heap_number);
+ __ JumpIfHeapNumber(input, &is_heap_number);
// Check for undefined. Undefined is coverted to zero for clamping conversion.
DeoptimizeIfNotRoot(input, Heap::kUndefinedValueRootIndex, instr);
// Heap number case.
__ Bind(&is_heap_number);
DoubleRegister dbl_scratch = double_scratch();
- DoubleRegister dbl_scratch2 = ToDoubleRegister(instr->temp2());
+ DoubleRegister dbl_scratch2 = ToDoubleRegister(instr->temp1());
__ Ldr(dbl_scratch, FieldMemOperand(input, HeapNumber::kValueOffset));
__ ClampDoubleToUint8(result, dbl_scratch, dbl_scratch2);
instr->TrueLabel(chunk()));
} else {
Register value = ToRegister(instr->value());
- __ CheckMap(value, scratch, Heap::kHeapNumberMapRootIndex,
- instr->FalseLabel(chunk()), DO_SMI_CHECK);
+ __ JumpIfNotHeapNumber(value, instr->FalseLabel(chunk()), DO_SMI_CHECK);
__ Ldr(scratch, FieldMemOperand(value, HeapNumber::kValueOffset));
__ JumpIfMinusZero(scratch, instr->TrueLabel(chunk()));
}
Label runtime_allocation;
// Deoptimize if the input is not a HeapNumber.
- __ Ldr(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
- DeoptimizeIfNotRoot(temp1, Heap::kHeapNumberMapRootIndex, instr);
+ DeoptimizeIfNotHeapNumber(input, instr);
// If the argument is positive, we can return it as-is, without any need to
// allocate a new HeapNumber for the result. We have to do this in integer
} else if (exponent_type.IsTagged()) {
Label no_deopt;
__ JumpIfSmi(tagged_exponent, &no_deopt);
- DCHECK(!x0.is(tagged_exponent));
- __ Ldr(x0, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
- DeoptimizeIfNotRoot(x0, Heap::kHeapNumberMapRootIndex, instr);
+ DeoptimizeIfNotHeapNumber(tagged_exponent, instr);
__ Bind(&no_deopt);
MathPowStub stub(isolate(), MathPowStub::TAGGED);
__ CallStub(&stub);
Label convert_undefined;
// Heap number map check.
- __ Ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
if (can_convert_undefined_to_nan) {
- __ JumpIfNotRoot(scratch, Heap::kHeapNumberMapRootIndex,
- &convert_undefined);
+ __ JumpIfNotHeapNumber(input, &convert_undefined);
} else {
- DeoptimizeIfNotRoot(scratch, Heap::kHeapNumberMapRootIndex, instr);
+ DeoptimizeIfNotHeapNumber(input, instr);
}
// Load heap number.
Label done;
- // Load heap object map.
- __ Ldr(scratch1, FieldMemOperand(input, HeapObject::kMapOffset));
-
if (instr->truncating()) {
Register output = ToRegister(instr->result());
Label check_bools;
// If it's not a heap number, jump to undefined check.
- __ JumpIfNotRoot(scratch1, Heap::kHeapNumberMapRootIndex, &check_bools);
+ __ JumpIfNotHeapNumber(input, &check_bools);
// A heap number: load value and convert to int32 using truncating function.
__ TruncateHeapNumberToI(output, input);
Register output = ToRegister32(instr->result());
DoubleRegister dbl_scratch2 = ToDoubleRegister(temp2);
- DeoptimizeIfNotRoot(scratch1, Heap::kHeapNumberMapRootIndex, instr,
- "not a heap number");
+ DeoptimizeIfNotHeapNumber(input, instr);
// A heap number: load value and convert to int32 using non-truncating
// function. If the result is out of range, branch to deoptimize.
Factory* factory = isolate()->factory();
if (String::Equals(type_name, factory->number_string())) {
- DCHECK(instr->temp1() != NULL);
- Register map = ToRegister(instr->temp1());
-
__ JumpIfSmi(value, true_label);
- __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset));
- __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
- EmitBranch(instr, eq);
+
+ int true_block = instr->TrueDestination(chunk_);
+ int false_block = instr->FalseDestination(chunk_);
+ int next_block = GetNextEmittedBlock();
+
+ if (true_block == false_block) {
+ EmitGoto(true_block);
+ } else if (true_block == next_block) {
+ __ JumpIfNotHeapNumber(value, chunk_->GetAssemblyLabel(false_block));
+ } else {
+ __ JumpIfHeapNumber(value, chunk_->GetAssemblyLabel(true_block));
+ if (false_block != next_block) {
+ __ B(chunk_->GetAssemblyLabel(false_block));
+ }
+ }
} else if (String::Equals(type_name, factory->string_string())) {
DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL));
LInstruction* instr, const char* detail = NULL);
void DeoptimizeIfNotRoot(Register rt, Heap::RootListIndex index,
LInstruction* instr, const char* detail = NULL);
+ void DeoptimizeIfNotHeapNumber(Register object, LInstruction* instr);
void DeoptimizeIfMinusZero(DoubleRegister input, LInstruction* instr,
const char* detail = NULL);
void DeoptimizeIfBitSet(Register rt, int bit, LInstruction* instr,
}
+void MacroAssembler::JumpIfHeapNumber(Register object, Label* on_heap_number,
+ SmiCheckType smi_check_type) {
+ Label on_not_heap_number;
+ if (smi_check_type == DO_SMI_CHECK) {
+ JumpIfSmi(object, &on_not_heap_number);
+ }
-
-void MacroAssembler::JumpForHeapNumber(Register object,
- Register heap_number_map,
- Label* on_heap_number,
- Label* on_not_heap_number) {
- DCHECK(on_heap_number || on_not_heap_number);
AssertNotSmi(object);
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
-
- // Load the HeapNumber map if it is not passed.
- if (heap_number_map.Is(NoReg)) {
- heap_number_map = temps.AcquireX();
- LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
- } else {
- AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
- }
-
- DCHECK(!AreAliased(temp, heap_number_map));
-
Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
- Cmp(temp, heap_number_map);
-
- if (on_heap_number) {
- B(eq, on_heap_number);
- }
- if (on_not_heap_number) {
- B(ne, on_not_heap_number);
- }
-}
-
+ JumpIfRoot(temp, Heap::kHeapNumberMapRootIndex, on_heap_number);
-void MacroAssembler::JumpIfHeapNumber(Register object,
- Label* on_heap_number,
- Register heap_number_map) {
- JumpForHeapNumber(object,
- heap_number_map,
- on_heap_number,
- NULL);
+ Bind(&on_not_heap_number);
}
void MacroAssembler::JumpIfNotHeapNumber(Register object,
Label* on_not_heap_number,
- Register heap_number_map) {
- JumpForHeapNumber(object,
- heap_number_map,
- NULL,
- on_not_heap_number);
+ SmiCheckType smi_check_type) {
+ if (smi_check_type == DO_SMI_CHECK) {
+ JumpIfSmi(object, on_not_heap_number);
+ }
+
+ AssertNotSmi(object);
+
+ UseScratchRegisterScope temps(this);
+ Register temp = temps.AcquireX();
+ Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
+ JumpIfNotRoot(temp, Heap::kHeapNumberMapRootIndex, on_not_heap_number);
}
Label load_result_from_cache;
JumpIfSmi(object, &is_smi);
- CheckMap(object, scratch1, Heap::kHeapNumberMapRootIndex, not_found,
- DONT_DO_SMI_CHECK);
+ JumpIfNotHeapNumber(object, not_found);
STATIC_ASSERT(kDoubleSize == (kWRegSize * 2));
Add(scratch1, object, HeapNumber::kValueOffset - kHeapObjectTag);
}
-void MacroAssembler::CompareMap(Register obj,
- Register scratch,
- Handle<Map> map) {
+void MacroAssembler::CompareObjectMap(Register obj, Heap::RootListIndex index) {
+ UseScratchRegisterScope temps(this);
+ Register obj_map = temps.AcquireX();
+ Ldr(obj_map, FieldMemOperand(obj, HeapObject::kMapOffset));
+ CompareRoot(obj_map, index);
+}
+
+
+void MacroAssembler::CompareObjectMap(Register obj, Register scratch,
+ Handle<Map> map) {
Ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
CompareMap(scratch, map);
}
JumpIfSmi(obj, fail);
}
- CompareMap(obj, scratch, map);
+ CompareObjectMap(obj, scratch, map);
B(ne, fail);
}
JumpIfSmi(value_reg, &store_num);
// Ensure that the object is a heap number.
- CheckMap(value_reg, scratch1, isolate()->factory()->heap_number_map(),
- fail, DONT_DO_SMI_CHECK);
+ JumpIfNotHeapNumber(value_reg, fail);
Ldr(fpscratch1, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
- CompareMap(map, temp, isolate()->factory()->meta_map());
+ CompareObjectMap(map, temp, isolate()->factory()->meta_map());
Check(eq, kWrongAddressOrValuePassedToRecordWrite);
}
// Abort execution if argument is not a string, enabled via --debug-code.
void AssertString(Register object);
- void JumpForHeapNumber(Register object,
- Register heap_number_map,
- Label* on_heap_number,
- Label* on_not_heap_number = NULL);
- void JumpIfHeapNumber(Register object,
- Label* on_heap_number,
- Register heap_number_map = NoReg);
- void JumpIfNotHeapNumber(Register object,
- Label* on_not_heap_number,
- Register heap_number_map = NoReg);
+ void JumpIfHeapNumber(Register object, Label* on_heap_number,
+ SmiCheckType smi_check_type = DONT_DO_SMI_CHECK);
+ void JumpIfNotHeapNumber(Register object, Label* on_not_heap_number,
+ SmiCheckType smi_check_type = DONT_DO_SMI_CHECK);
// Sets the vs flag if the input is -0.0.
void TestForMinusZero(DoubleRegister input);
// Compare an object's map with the specified map. Condition flags are set
// with result of map compare.
- void CompareMap(Register obj,
- Register scratch,
- Handle<Map> map);
+ void CompareObjectMap(Register obj, Heap::RootListIndex index);
+
+ // Compare an object's map with the specified map. Condition flags are set
+ // with result of map compare.
+ void CompareObjectMap(Register obj, Register scratch, Handle<Map> map);
// As above, but the map of the object is already loaded into the register
// which is preserved by the code generated.