[intrinsics] Kill the %_IsMinusZero intrinsic.
By now only the default %TypedArray%.prototype.sort compare function and the JS implementation of SameValueZero were still using the odd %_IsMinusZero intrinsic, whose semantics both included a number check (actually HeapNumber test) plus testing if the heap number stores the special -0 value. In both cases we already know that we deal with number so we can reduce it to a simple number test for -0, which can be expressed via dividing 1 by that value and checking the sign of the result. In case of the compare function, we can be even smarter and work with the reciprocal values in case x and y are equal to 0 (although long term we should probably rewrite the fast case for the typed array sorting function in C++ anyway, which will be way, way faster than our handwritten callback-style, type-feedback polluted JS implementation). R=yangguo@chromium.org Review URL: https://codereview.chromium.org/1680783002 Cr-Commit-Position: refs/heads/master@{#33833}
This commit is contained in:
parent
edeaa188a6
commit
00f7d1f5f8
@ -69,8 +69,6 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
|
||||
return ReduceMathSqrt(node);
|
||||
case Runtime::kInlineValueOf:
|
||||
return ReduceValueOf(node);
|
||||
case Runtime::kInlineIsMinusZero:
|
||||
return ReduceIsMinusZero(node);
|
||||
case Runtime::kInlineFixedArrayGet:
|
||||
return ReduceFixedArrayGet(node);
|
||||
case Runtime::kInlineFixedArraySet:
|
||||
@ -338,30 +336,6 @@ Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op) {
|
||||
}
|
||||
|
||||
|
||||
Reduction JSIntrinsicLowering::ReduceIsMinusZero(Node* node) {
|
||||
Node* value = NodeProperties::GetValueInput(node, 0);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
|
||||
Node* double_lo =
|
||||
graph()->NewNode(machine()->Float64ExtractLowWord32(), value);
|
||||
Node* check1 = graph()->NewNode(machine()->Word32Equal(), double_lo,
|
||||
jsgraph()->ZeroConstant());
|
||||
|
||||
Node* double_hi =
|
||||
graph()->NewNode(machine()->Float64ExtractHighWord32(), value);
|
||||
Node* check2 = graph()->NewNode(
|
||||
machine()->Word32Equal(), double_hi,
|
||||
jsgraph()->Int32Constant(static_cast<int32_t>(0x80000000)));
|
||||
|
||||
ReplaceWithValue(node, node, effect);
|
||||
|
||||
Node* and_result = graph()->NewNode(machine()->Word32And(), check1, check2);
|
||||
|
||||
return Change(node, machine()->Word32Equal(), and_result,
|
||||
jsgraph()->Int32Constant(1));
|
||||
}
|
||||
|
||||
|
||||
Reduction JSIntrinsicLowering::ReduceFixedArrayGet(Node* node) {
|
||||
Node* base = node->InputAt(0);
|
||||
Node* index = node->InputAt(1);
|
||||
|
@ -44,7 +44,6 @@ class JSIntrinsicLowering final : public AdvancedReducer {
|
||||
Reduction ReduceDoubleHi(Node* node);
|
||||
Reduction ReduceDoubleLo(Node* node);
|
||||
Reduction ReduceIncrementStatsCounter(Node* node);
|
||||
Reduction ReduceIsMinusZero(Node* node);
|
||||
Reduction ReduceIsInstanceType(Node* node, InstanceType instance_type);
|
||||
Reduction ReduceIsJSReceiver(Node* node);
|
||||
Reduction ReduceIsSmi(Node* node);
|
||||
|
@ -1564,7 +1564,6 @@ Type* Typer::Visitor::TypeJSCallRuntime(Node* node) {
|
||||
case Runtime::kInlineIsArray:
|
||||
case Runtime::kInlineIsDate:
|
||||
case Runtime::kInlineIsTypedArray:
|
||||
case Runtime::kInlineIsMinusZero:
|
||||
case Runtime::kInlineIsRegExp:
|
||||
return Type::Boolean();
|
||||
case Runtime::kInlineDoubleLo:
|
||||
|
@ -1743,14 +1743,6 @@ LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
|
||||
HCompareMinusZeroAndBranch* instr) {
|
||||
LOperand* value = UseRegister(instr->value());
|
||||
LOperand* scratch = TempRegister();
|
||||
return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
|
||||
DCHECK(instr->value()->representation().IsTagged());
|
||||
LOperand* value = UseRegisterAtStart(instr->value());
|
||||
|
@ -47,7 +47,6 @@ class LCodeGen;
|
||||
V(ClampIToUint8) \
|
||||
V(ClampTToUint8) \
|
||||
V(ClassOfTestAndBranch) \
|
||||
V(CompareMinusZeroAndBranch) \
|
||||
V(CompareNumericAndBranch) \
|
||||
V(CmpObjectEqAndBranch) \
|
||||
V(CmpHoleAndBranch) \
|
||||
@ -991,22 +990,6 @@ class LCmpHoleAndBranch final : public LControlInstruction<1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
|
||||
inputs_[0] = value;
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
LOperand* value() { return inputs_[0]; }
|
||||
LOperand* temp() { return temps_[0]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
|
||||
"cmp-minus-zero-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
|
||||
};
|
||||
|
||||
|
||||
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LIsStringAndBranch(LOperand* value, LOperand* temp) {
|
||||
|
@ -2313,33 +2313,6 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
|
||||
Representation rep = instr->hydrogen()->value()->representation();
|
||||
DCHECK(!rep.IsInteger32());
|
||||
Register scratch = ToRegister(instr->temp());
|
||||
|
||||
if (rep.IsDouble()) {
|
||||
DwVfpRegister value = ToDoubleRegister(instr->value());
|
||||
__ VFPCompareAndSetFlags(value, 0.0);
|
||||
EmitFalseBranch(instr, ne);
|
||||
__ VmovHigh(scratch, value);
|
||||
__ cmp(scratch, Operand(0x80000000));
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
__ CheckMap(value,
|
||||
scratch,
|
||||
Heap::kHeapNumberMapRootIndex,
|
||||
instr->FalseLabel(chunk()),
|
||||
DO_SMI_CHECK);
|
||||
__ ldr(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset));
|
||||
__ ldr(ip, FieldMemOperand(value, HeapNumber::kMantissaOffset));
|
||||
__ cmp(scratch, Operand(0x80000000));
|
||||
__ cmp(ip, Operand(0x00000000), eq);
|
||||
}
|
||||
EmitBranch(instr, eq);
|
||||
}
|
||||
|
||||
|
||||
Condition LCodeGen::EmitIsString(Register input,
|
||||
Register temp1,
|
||||
Label* is_not_string,
|
||||
|
@ -1567,14 +1567,6 @@ LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
|
||||
HCompareMinusZeroAndBranch* instr) {
|
||||
LOperand* value = UseRegister(instr->value());
|
||||
LOperand* scratch = TempRegister();
|
||||
return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
|
||||
DCHECK(instr->value()->representation().IsTagged());
|
||||
LOperand* value = UseRegisterAtStart(instr->value());
|
||||
|
@ -55,7 +55,6 @@ class LCodeGen;
|
||||
V(CmpMapAndBranch) \
|
||||
V(CmpObjectEqAndBranch) \
|
||||
V(CmpT) \
|
||||
V(CompareMinusZeroAndBranch) \
|
||||
V(CompareNumericAndBranch) \
|
||||
V(ConstantD) \
|
||||
V(ConstantE) \
|
||||
@ -1146,22 +1145,6 @@ class LCmpT final : public LTemplateInstruction<1, 3, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
|
||||
inputs_[0] = value;
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
LOperand* value() { return inputs_[0]; }
|
||||
LOperand* temp() { return temps_[0]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
|
||||
"cmp-minus-zero-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
|
||||
};
|
||||
|
||||
|
||||
class LCompareNumericAndBranch final : public LControlInstruction<2, 0> {
|
||||
public:
|
||||
LCompareNumericAndBranch(LOperand* left, LOperand* right) {
|
||||
|
@ -2327,24 +2327,6 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
|
||||
Representation rep = instr->hydrogen()->value()->representation();
|
||||
DCHECK(!rep.IsInteger32());
|
||||
Register scratch = ToRegister(instr->temp());
|
||||
|
||||
if (rep.IsDouble()) {
|
||||
__ JumpIfMinusZero(ToDoubleRegister(instr->value()),
|
||||
instr->TrueLabel(chunk()));
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
__ JumpIfNotHeapNumber(value, instr->FalseLabel(chunk()), DO_SMI_CHECK);
|
||||
__ Ldr(scratch, FieldMemOperand(value, HeapNumber::kValueOffset));
|
||||
__ JumpIfMinusZero(scratch, instr->TrueLabel(chunk()));
|
||||
}
|
||||
EmitGoto(instr->FalseDestination(chunk()));
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
|
||||
LOperand* left = instr->left();
|
||||
LOperand* right = instr->right();
|
||||
|
@ -783,7 +783,6 @@ bool HInstruction::CanDeoptimize() {
|
||||
case HValue::kCompareGeneric:
|
||||
case HValue::kCompareHoleAndBranch:
|
||||
case HValue::kCompareMap:
|
||||
case HValue::kCompareMinusZeroAndBranch:
|
||||
case HValue::kCompareNumericAndBranch:
|
||||
case HValue::kCompareObjectEqAndBranch:
|
||||
case HValue::kConstant:
|
||||
@ -3326,31 +3325,6 @@ bool HCompareNumericAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
|
||||
}
|
||||
|
||||
|
||||
bool HCompareMinusZeroAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
|
||||
if (FLAG_fold_constants && value()->IsConstant()) {
|
||||
HConstant* constant = HConstant::cast(value());
|
||||
if (constant->HasDoubleValue()) {
|
||||
*block = IsMinusZero(constant->DoubleValue())
|
||||
? FirstSuccessor() : SecondSuccessor();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (value()->representation().IsSmiOrInteger32()) {
|
||||
// A Smi or Integer32 cannot contain minus zero.
|
||||
*block = SecondSuccessor();
|
||||
return true;
|
||||
}
|
||||
*block = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void HCompareMinusZeroAndBranch::InferRepresentation(
|
||||
HInferRepresentationPhase* h_infer) {
|
||||
ChangeRepresentation(value()->representation());
|
||||
}
|
||||
|
||||
|
||||
std::ostream& HGoto::PrintDataTo(std::ostream& os) const { // NOLINT
|
||||
return os << *SuccessorAt(0);
|
||||
}
|
||||
|
@ -79,7 +79,6 @@ class LChunkBuilder;
|
||||
V(CompareNumericAndBranch) \
|
||||
V(CompareHoleAndBranch) \
|
||||
V(CompareGeneric) \
|
||||
V(CompareMinusZeroAndBranch) \
|
||||
V(CompareObjectEqAndBranch) \
|
||||
V(CompareMap) \
|
||||
V(Constant) \
|
||||
@ -4345,27 +4344,6 @@ class HCompareHoleAndBranch final : public HUnaryControlInstruction {
|
||||
};
|
||||
|
||||
|
||||
class HCompareMinusZeroAndBranch final : public HUnaryControlInstruction {
|
||||
public:
|
||||
DECLARE_INSTRUCTION_FACTORY_P1(HCompareMinusZeroAndBranch, HValue*);
|
||||
|
||||
void InferRepresentation(HInferRepresentationPhase* h_infer) override;
|
||||
|
||||
Representation RequiredInputRepresentation(int index) override {
|
||||
return representation();
|
||||
}
|
||||
|
||||
bool KnownSuccessorBlock(HBasicBlock** block) override;
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch)
|
||||
|
||||
private:
|
||||
explicit HCompareMinusZeroAndBranch(HValue* value)
|
||||
: HUnaryControlInstruction(value, NULL, NULL) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
|
||||
public:
|
||||
DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
|
||||
|
@ -71,12 +71,6 @@ void HRangeAnalysisPhase::Run() {
|
||||
instr->to().IsSmiOrInteger32());
|
||||
PropagateMinusZeroChecks(instr->value());
|
||||
}
|
||||
} else if (value->IsCompareMinusZeroAndBranch()) {
|
||||
HCompareMinusZeroAndBranch* instr =
|
||||
HCompareMinusZeroAndBranch::cast(value);
|
||||
if (instr->value()->representation().IsSmiOrInteger32()) {
|
||||
PropagateMinusZeroChecks(instr->value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12232,15 +12232,6 @@ void HOptimizedGraphBuilder::GenerateIsJSReceiver(CallRuntime* call) {
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
|
||||
DCHECK(call->arguments()->length() == 1);
|
||||
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
||||
HValue* value = Pop();
|
||||
HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
|
||||
return ast_context()->ReturnControl(result, call->id());
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
|
||||
DCHECK(call->arguments()->length() == 1);
|
||||
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
||||
|
@ -2225,7 +2225,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
F(ToNumber) \
|
||||
F(IsJSReceiver) \
|
||||
F(MathPow) \
|
||||
F(IsMinusZero) \
|
||||
F(HasCachedArrayIndex) \
|
||||
F(GetCachedArrayIndex) \
|
||||
F(FastOneByteArrayJoin) \
|
||||
|
@ -2217,34 +2217,6 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
|
||||
Representation rep = instr->hydrogen()->value()->representation();
|
||||
DCHECK(!rep.IsInteger32());
|
||||
Register scratch = ToRegister(instr->temp());
|
||||
|
||||
if (rep.IsDouble()) {
|
||||
XMMRegister value = ToDoubleRegister(instr->value());
|
||||
XMMRegister xmm_scratch = double_scratch0();
|
||||
__ xorps(xmm_scratch, xmm_scratch);
|
||||
__ ucomisd(xmm_scratch, value);
|
||||
EmitFalseBranch(instr, not_equal);
|
||||
__ movmskpd(scratch, value);
|
||||
__ test(scratch, Immediate(1));
|
||||
EmitBranch(instr, not_zero);
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
|
||||
__ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK);
|
||||
__ cmp(FieldOperand(value, HeapNumber::kExponentOffset),
|
||||
Immediate(0x1));
|
||||
EmitFalseBranch(instr, no_overflow);
|
||||
__ cmp(FieldOperand(value, HeapNumber::kMantissaOffset),
|
||||
Immediate(0x00000000));
|
||||
EmitBranch(instr, equal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Condition LCodeGen::EmitIsString(Register input,
|
||||
Register temp1,
|
||||
Label* is_not_string,
|
||||
|
@ -1709,14 +1709,6 @@ LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
|
||||
HCompareMinusZeroAndBranch* instr) {
|
||||
LOperand* value = UseRegister(instr->value());
|
||||
LOperand* scratch = TempRegister();
|
||||
return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
|
||||
DCHECK(instr->value()->representation().IsTagged());
|
||||
LOperand* temp = TempRegister();
|
||||
|
@ -51,7 +51,6 @@ class LCodeGen;
|
||||
V(ClampIToUint8) \
|
||||
V(ClampTToUint8) \
|
||||
V(ClassOfTestAndBranch) \
|
||||
V(CompareMinusZeroAndBranch) \
|
||||
V(CompareNumericAndBranch) \
|
||||
V(CmpObjectEqAndBranch) \
|
||||
V(CmpHoleAndBranch) \
|
||||
@ -974,22 +973,6 @@ class LCmpHoleAndBranch final : public LControlInstruction<1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
|
||||
inputs_[0] = value;
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
LOperand* value() { return inputs_[0]; }
|
||||
LOperand* temp() { return temps_[0]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
|
||||
"cmp-minus-zero-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
|
||||
};
|
||||
|
||||
|
||||
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LIsStringAndBranch(LOperand* value, LOperand* temp) {
|
||||
|
@ -2221,32 +2221,6 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
|
||||
Representation rep = instr->hydrogen()->value()->representation();
|
||||
DCHECK(!rep.IsInteger32());
|
||||
Register scratch = ToRegister(instr->temp());
|
||||
|
||||
if (rep.IsDouble()) {
|
||||
DoubleRegister value = ToDoubleRegister(instr->value());
|
||||
EmitFalseBranchF(instr, ne, value, kDoubleRegZero);
|
||||
__ FmoveHigh(scratch, value);
|
||||
__ li(at, 0x80000000);
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
__ CheckMap(value,
|
||||
scratch,
|
||||
Heap::kHeapNumberMapRootIndex,
|
||||
instr->FalseLabel(chunk()),
|
||||
DO_SMI_CHECK);
|
||||
__ lw(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset));
|
||||
EmitFalseBranch(instr, ne, scratch, Operand(0x80000000));
|
||||
__ lw(scratch, FieldMemOperand(value, HeapNumber::kMantissaOffset));
|
||||
__ mov(at, zero_reg);
|
||||
}
|
||||
EmitBranch(instr, eq, scratch, Operand(at));
|
||||
}
|
||||
|
||||
|
||||
Condition LCodeGen::EmitIsString(Register input,
|
||||
Register temp1,
|
||||
Label* is_not_string,
|
||||
|
@ -1690,14 +1690,6 @@ LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
|
||||
HCompareMinusZeroAndBranch* instr) {
|
||||
LOperand* value = UseRegister(instr->value());
|
||||
LOperand* scratch = TempRegister();
|
||||
return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
|
||||
DCHECK(instr->value()->representation().IsTagged());
|
||||
LOperand* temp = TempRegister();
|
||||
|
@ -47,7 +47,6 @@ class LCodeGen;
|
||||
V(ClampIToUint8) \
|
||||
V(ClampTToUint8) \
|
||||
V(ClassOfTestAndBranch) \
|
||||
V(CompareMinusZeroAndBranch) \
|
||||
V(CompareNumericAndBranch) \
|
||||
V(CmpObjectEqAndBranch) \
|
||||
V(CmpHoleAndBranch) \
|
||||
@ -969,22 +968,6 @@ class LCmpHoleAndBranch final : public LControlInstruction<1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
|
||||
inputs_[0] = value;
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
LOperand* value() { return inputs_[0]; }
|
||||
LOperand* temp() { return temps_[0]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
|
||||
"cmp-minus-zero-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
|
||||
};
|
||||
|
||||
|
||||
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LIsStringAndBranch(LOperand* value, LOperand* temp) {
|
||||
|
@ -2338,35 +2338,6 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
|
||||
Representation rep = instr->hydrogen()->value()->representation();
|
||||
DCHECK(!rep.IsInteger32());
|
||||
Register scratch = ToRegister(instr->temp());
|
||||
|
||||
if (rep.IsDouble()) {
|
||||
DoubleRegister value = ToDoubleRegister(instr->value());
|
||||
EmitFalseBranchF(instr, ne, value, kDoubleRegZero);
|
||||
__ FmoveHigh(scratch, value);
|
||||
// Only use low 32-bits of value.
|
||||
__ dsll32(scratch, scratch, 0);
|
||||
__ dsrl32(scratch, scratch, 0);
|
||||
__ li(at, 0x80000000);
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
__ CheckMap(value,
|
||||
scratch,
|
||||
Heap::kHeapNumberMapRootIndex,
|
||||
instr->FalseLabel(chunk()),
|
||||
DO_SMI_CHECK);
|
||||
__ lwu(scratch, FieldMemOperand(value, HeapNumber::kExponentOffset));
|
||||
EmitFalseBranch(instr, ne, scratch, Operand(0x80000000));
|
||||
__ lwu(scratch, FieldMemOperand(value, HeapNumber::kMantissaOffset));
|
||||
__ mov(at, zero_reg);
|
||||
}
|
||||
EmitBranch(instr, eq, scratch, Operand(at));
|
||||
}
|
||||
|
||||
|
||||
Condition LCodeGen::EmitIsString(Register input,
|
||||
Register temp1,
|
||||
Label* is_not_string,
|
||||
|
@ -1696,14 +1696,6 @@ LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
|
||||
HCompareMinusZeroAndBranch* instr) {
|
||||
LOperand* value = UseRegister(instr->value());
|
||||
LOperand* scratch = TempRegister();
|
||||
return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
|
||||
DCHECK(instr->value()->representation().IsTagged());
|
||||
LOperand* temp = TempRegister();
|
||||
|
@ -49,7 +49,6 @@ class LCodeGen;
|
||||
V(ClampIToUint8) \
|
||||
V(ClampTToUint8) \
|
||||
V(ClassOfTestAndBranch) \
|
||||
V(CompareMinusZeroAndBranch) \
|
||||
V(CompareNumericAndBranch) \
|
||||
V(CmpObjectEqAndBranch) \
|
||||
V(CmpHoleAndBranch) \
|
||||
@ -987,22 +986,6 @@ class LCmpHoleAndBranch final : public LControlInstruction<1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
|
||||
inputs_[0] = value;
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
LOperand* value() { return inputs_[0]; }
|
||||
LOperand* temp() { return temps_[0]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
|
||||
"cmp-minus-zero-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
|
||||
};
|
||||
|
||||
|
||||
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LIsStringAndBranch(LOperand* value, LOperand* temp) {
|
||||
|
@ -2374,27 +2374,6 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
|
||||
Representation rep = instr->hydrogen()->value()->representation();
|
||||
DCHECK(!rep.IsInteger32());
|
||||
Register scratch = ToRegister(instr->temp());
|
||||
|
||||
if (rep.IsDouble()) {
|
||||
DoubleRegister value = ToDoubleRegister(instr->value());
|
||||
__ fcmpu(value, kDoubleRegZero);
|
||||
EmitFalseBranch(instr, ne);
|
||||
__ TestDoubleSign(value, scratch);
|
||||
EmitBranch(instr, lt);
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
__ CheckMap(value, scratch, Heap::kHeapNumberMapRootIndex,
|
||||
instr->FalseLabel(chunk()), DO_SMI_CHECK);
|
||||
__ TestHeapNumberIsMinusZero(value, scratch, ip);
|
||||
EmitBranch(instr, eq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Condition LCodeGen::EmitIsString(Register input, Register temp1,
|
||||
Label* is_not_string,
|
||||
SmiCheck check_needed = INLINE_SMI_CHECK) {
|
||||
|
@ -1706,14 +1706,6 @@ LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
|
||||
HCompareMinusZeroAndBranch* instr) {
|
||||
LOperand* value = UseRegister(instr->value());
|
||||
LOperand* scratch = TempRegister();
|
||||
return new (zone()) LCompareMinusZeroAndBranch(value, scratch);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
|
||||
DCHECK(instr->value()->representation().IsTagged());
|
||||
LOperand* value = UseRegisterAtStart(instr->value());
|
||||
|
@ -47,7 +47,6 @@ class LCodeGen;
|
||||
V(ClampIToUint8) \
|
||||
V(ClampTToUint8) \
|
||||
V(ClassOfTestAndBranch) \
|
||||
V(CompareMinusZeroAndBranch) \
|
||||
V(CompareNumericAndBranch) \
|
||||
V(CmpObjectEqAndBranch) \
|
||||
V(CmpHoleAndBranch) \
|
||||
@ -953,22 +952,6 @@ class LCmpHoleAndBranch final : public LControlInstruction<1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LCompareMinusZeroAndBranch(LOperand* value, LOperand* temp) {
|
||||
inputs_[0] = value;
|
||||
temps_[0] = temp;
|
||||
}
|
||||
|
||||
LOperand* value() { return inputs_[0]; }
|
||||
LOperand* temp() { return temps_[0]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
|
||||
"cmp-minus-zero-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
|
||||
};
|
||||
|
||||
|
||||
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LIsStringAndBranch(LOperand* value, LOperand* temp) {
|
||||
|
@ -2283,33 +2283,6 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
|
||||
Representation rep = instr->hydrogen()->value()->representation();
|
||||
DCHECK(!rep.IsInteger32());
|
||||
|
||||
if (rep.IsDouble()) {
|
||||
XMMRegister value = ToDoubleRegister(instr->value());
|
||||
XMMRegister xmm_scratch = double_scratch0();
|
||||
__ Xorpd(xmm_scratch, xmm_scratch);
|
||||
__ Ucomisd(xmm_scratch, value);
|
||||
EmitFalseBranch(instr, not_equal);
|
||||
__ Movmskpd(kScratchRegister, value);
|
||||
__ testl(kScratchRegister, Immediate(1));
|
||||
EmitBranch(instr, not_zero);
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
|
||||
__ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK);
|
||||
__ cmpl(FieldOperand(value, HeapNumber::kExponentOffset),
|
||||
Immediate(0x1));
|
||||
EmitFalseBranch(instr, no_overflow);
|
||||
__ cmpl(FieldOperand(value, HeapNumber::kMantissaOffset),
|
||||
Immediate(0x00000000));
|
||||
EmitBranch(instr, equal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Condition LCodeGen::EmitIsString(Register input,
|
||||
Register temp1,
|
||||
Label* is_not_string,
|
||||
|
@ -1702,13 +1702,6 @@ LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
|
||||
HCompareMinusZeroAndBranch* instr) {
|
||||
LOperand* value = UseRegister(instr->value());
|
||||
return new(zone()) LCompareMinusZeroAndBranch(value);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
|
||||
DCHECK(instr->value()->representation().IsTagged());
|
||||
LOperand* value = UseRegisterAtStart(instr->value());
|
||||
|
@ -47,7 +47,6 @@ class LCodeGen;
|
||||
V(ClampIToUint8) \
|
||||
V(ClampTToUint8) \
|
||||
V(ClassOfTestAndBranch) \
|
||||
V(CompareMinusZeroAndBranch) \
|
||||
V(CompareNumericAndBranch) \
|
||||
V(CmpObjectEqAndBranch) \
|
||||
V(CmpHoleAndBranch) \
|
||||
@ -967,20 +966,6 @@ class LCmpHoleAndBranch final : public LControlInstruction<1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 0> {
|
||||
public:
|
||||
explicit LCompareMinusZeroAndBranch(LOperand* value) {
|
||||
inputs_[0] = value;
|
||||
}
|
||||
|
||||
LOperand* value() { return inputs_[0]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
|
||||
"cmp-minus-zero-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
|
||||
};
|
||||
|
||||
|
||||
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
explicit LIsStringAndBranch(LOperand* value, LOperand* temp) {
|
||||
|
@ -2505,29 +2505,6 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
|
||||
Representation rep = instr->hydrogen()->value()->representation();
|
||||
DCHECK(!rep.IsInteger32());
|
||||
|
||||
if (rep.IsDouble()) {
|
||||
X87Register input = ToX87Register(instr->value());
|
||||
X87LoadForUsage(input);
|
||||
__ FXamMinusZero();
|
||||
EmitBranch(instr, equal);
|
||||
} else {
|
||||
Register value = ToRegister(instr->value());
|
||||
Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
|
||||
__ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK);
|
||||
__ cmp(FieldOperand(value, HeapNumber::kExponentOffset),
|
||||
Immediate(0x1));
|
||||
EmitFalseBranch(instr, no_overflow);
|
||||
__ cmp(FieldOperand(value, HeapNumber::kMantissaOffset),
|
||||
Immediate(0x00000000));
|
||||
EmitBranch(instr, equal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Condition LCodeGen::EmitIsString(Register input,
|
||||
Register temp1,
|
||||
Label* is_not_string,
|
||||
|
@ -1715,13 +1715,6 @@ LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
|
||||
HCompareMinusZeroAndBranch* instr) {
|
||||
LOperand* value = UseRegisterAtStart(instr->value());
|
||||
return new (zone()) LCompareMinusZeroAndBranch(value);
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
|
||||
DCHECK(instr->value()->representation().IsTagged());
|
||||
LOperand* temp = TempRegister();
|
||||
|
@ -52,7 +52,6 @@ class LCodeGen;
|
||||
V(ClampTToUint8NoSSE2) \
|
||||
V(ClassOfTestAndBranch) \
|
||||
V(ClobberDoubles) \
|
||||
V(CompareMinusZeroAndBranch) \
|
||||
V(CompareNumericAndBranch) \
|
||||
V(CmpObjectEqAndBranch) \
|
||||
V(CmpHoleAndBranch) \
|
||||
@ -990,18 +989,6 @@ class LCmpHoleAndBranch final : public LControlInstruction<1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LCompareMinusZeroAndBranch final : public LControlInstruction<1, 0> {
|
||||
public:
|
||||
explicit LCompareMinusZeroAndBranch(LOperand* value) { inputs_[0] = value; }
|
||||
|
||||
LOperand* value() { return inputs_[0]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CompareMinusZeroAndBranch,
|
||||
"cmp-minus-zero-and-branch")
|
||||
DECLARE_HYDROGEN_ACCESSOR(CompareMinusZeroAndBranch)
|
||||
};
|
||||
|
||||
|
||||
class LIsStringAndBranch final : public LControlInstruction<1, 1> {
|
||||
public:
|
||||
LIsStringAndBranch(LOperand* value, LOperand* temp) {
|
||||
|
@ -3024,32 +3024,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
Label* fall_through = NULL;
|
||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||
&if_true, &if_false, &fall_through);
|
||||
|
||||
__ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK);
|
||||
__ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
|
||||
__ ldr(r1, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
|
||||
__ cmp(r2, Operand(0x80000000));
|
||||
__ cmp(r1, Operand(0x00000000), eq);
|
||||
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
Split(eq, if_true, if_false, fall_through);
|
||||
|
||||
context()->Plug(if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
@ -2833,33 +2833,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
Label* fall_through = NULL;
|
||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||
&if_true, &if_false, &fall_through);
|
||||
|
||||
// Only a HeapNumber can be -0.0, so return false if we have something else.
|
||||
__ JumpIfNotHeapNumber(x0, if_false, DO_SMI_CHECK);
|
||||
|
||||
// Test the bit pattern.
|
||||
__ Ldr(x10, FieldMemOperand(x0, HeapNumber::kValueOffset));
|
||||
__ Cmp(x10, 1); // Set V on 0x8000000000000000.
|
||||
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
Split(vs, if_true, if_false, fall_through);
|
||||
|
||||
context()->Plug(if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
@ -535,7 +535,6 @@ class FullCodeGenerator: public AstVisitor {
|
||||
F(IsJSReceiver) \
|
||||
F(IsSimdValue) \
|
||||
F(MathPow) \
|
||||
F(IsMinusZero) \
|
||||
F(HasCachedArrayIndex) \
|
||||
F(GetCachedArrayIndex) \
|
||||
F(GetSuperConstructor) \
|
||||
|
@ -2903,33 +2903,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
Label* fall_through = NULL;
|
||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||
&if_true, &if_false, &fall_through);
|
||||
|
||||
Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
|
||||
__ CheckMap(eax, map, if_false, DO_SMI_CHECK);
|
||||
// Check if the exponent half is 0x80000000. Comparing against 1 and
|
||||
// checking for overflow is the shortest possible encoding.
|
||||
__ cmp(FieldOperand(eax, HeapNumber::kExponentOffset), Immediate(0x1));
|
||||
__ j(no_overflow, if_false);
|
||||
__ cmp(FieldOperand(eax, HeapNumber::kMantissaOffset), Immediate(0x0));
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
|
||||
context()->Plug(if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
@ -3010,36 +3010,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
Label* fall_through = NULL;
|
||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||
&if_true, &if_false, &fall_through);
|
||||
|
||||
__ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK);
|
||||
__ lw(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset));
|
||||
__ lw(a1, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
|
||||
__ li(t0, 0x80000000);
|
||||
Label not_nan;
|
||||
__ Branch(¬_nan, ne, a2, Operand(t0));
|
||||
__ mov(t0, zero_reg);
|
||||
__ mov(a2, a1);
|
||||
__ bind(¬_nan);
|
||||
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
Split(eq, a2, Operand(t0), if_true, if_false, fall_through);
|
||||
|
||||
context()->Plug(if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
@ -3020,36 +3020,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
Label* fall_through = NULL;
|
||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||
&if_true, &if_false, &fall_through);
|
||||
|
||||
__ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK);
|
||||
__ lwu(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset));
|
||||
__ lwu(a1, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
|
||||
__ li(a4, 0x80000000);
|
||||
Label not_nan;
|
||||
__ Branch(¬_nan, ne, a2, Operand(a4));
|
||||
__ mov(a4, zero_reg);
|
||||
__ mov(a2, a1);
|
||||
__ bind(¬_nan);
|
||||
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
Split(eq, a2, Operand(a4), if_true, if_false, fall_through);
|
||||
|
||||
context()->Plug(if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
@ -3011,28 +3011,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
Label* fall_through = NULL;
|
||||
context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
|
||||
&if_false, &fall_through);
|
||||
|
||||
__ CheckMap(r3, r4, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK);
|
||||
__ TestHeapNumberIsMinusZero(r3, r4, r5);
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
Split(eq, if_true, if_false, fall_through);
|
||||
|
||||
context()->Plug(if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
@ -2889,33 +2889,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
Label* fall_through = NULL;
|
||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||
&if_true, &if_false, &fall_through);
|
||||
|
||||
Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
|
||||
__ CheckMap(rax, map, if_false, DO_SMI_CHECK);
|
||||
__ cmpl(FieldOperand(rax, HeapNumber::kExponentOffset),
|
||||
Immediate(0x1));
|
||||
__ j(no_overflow, if_false);
|
||||
__ cmpl(FieldOperand(rax, HeapNumber::kMantissaOffset),
|
||||
Immediate(0x00000000));
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
|
||||
context()->Plug(if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
@ -2903,33 +2903,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
Label materialize_true, materialize_false;
|
||||
Label* if_true = NULL;
|
||||
Label* if_false = NULL;
|
||||
Label* fall_through = NULL;
|
||||
context()->PrepareTest(&materialize_true, &materialize_false,
|
||||
&if_true, &if_false, &fall_through);
|
||||
|
||||
Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
|
||||
__ CheckMap(eax, map, if_false, DO_SMI_CHECK);
|
||||
// Check if the exponent half is 0x80000000. Comparing against 1 and
|
||||
// checking for overflow is the shortest possible encoding.
|
||||
__ cmp(FieldOperand(eax, HeapNumber::kExponentOffset), Immediate(0x1));
|
||||
__ j(no_overflow, if_false);
|
||||
__ cmp(FieldOperand(eax, HeapNumber::kMantissaOffset), Immediate(0x0));
|
||||
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
|
||||
Split(equal, if_true, if_false, fall_through);
|
||||
|
||||
context()->Plug(if_true, if_false);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 1);
|
||||
|
@ -43,11 +43,11 @@ utils.ImportFromExperimental(function(from) {
|
||||
|
||||
// ES5, section 9.12
|
||||
function SameValue(x, y) {
|
||||
if (typeof x != typeof y) return false;
|
||||
if (typeof x !== typeof y) return false;
|
||||
if (IS_NUMBER(x)) {
|
||||
if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
|
||||
// x is +0 and y is -0 or vice versa.
|
||||
if (x === 0 && y === 0 && %_IsMinusZero(x) != %_IsMinusZero(y)) {
|
||||
if (x === 0 && y === 0 && 1/x !== 1/y) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -58,7 +58,7 @@ function SameValue(x, y) {
|
||||
|
||||
// ES6, section 7.2.4
|
||||
function SameValueZero(x, y) {
|
||||
if (typeof x != typeof y) return false;
|
||||
if (typeof x !== typeof y) return false;
|
||||
if (IS_NUMBER(x)) {
|
||||
if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
|
||||
}
|
||||
|
@ -567,22 +567,20 @@ function TypedArrayReverse() {
|
||||
|
||||
|
||||
function TypedArrayComparefn(x, y) {
|
||||
if (IsNaN(x) && IsNaN(y)) {
|
||||
return IsNaN(y) ? 0 : 1;
|
||||
}
|
||||
if (IsNaN(x)) {
|
||||
return 1;
|
||||
}
|
||||
if (x === 0 && x === y) {
|
||||
if (%_IsMinusZero(x)) {
|
||||
if (!%_IsMinusZero(y)) {
|
||||
return -1;
|
||||
x = 1 / x;
|
||||
y = 1 / y;
|
||||
}
|
||||
} else if (%_IsMinusZero(y)) {
|
||||
if (x < y) {
|
||||
return -1;
|
||||
} else if (x > y) {
|
||||
return 1;
|
||||
} else if (IsNaN(x) && IsNaN(y)) {
|
||||
return IsNaN(y) ? 0 : 1;
|
||||
} else if (IsNaN(x)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return x - y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2207,25 +2207,6 @@ void MacroAssembler::TestDoubleIsMinusZero(DoubleRegister input,
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::TestHeapNumberIsMinusZero(Register input,
|
||||
Register scratch1,
|
||||
Register scratch2) {
|
||||
#if V8_TARGET_ARCH_PPC64
|
||||
LoadP(scratch1, FieldMemOperand(input, HeapNumber::kValueOffset));
|
||||
rotldi(scratch1, scratch1, 1);
|
||||
cmpi(scratch1, Operand(1));
|
||||
#else
|
||||
lwz(scratch1, FieldMemOperand(input, HeapNumber::kExponentOffset));
|
||||
lwz(scratch2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
|
||||
Label done;
|
||||
cmpi(scratch2, Operand::Zero());
|
||||
bne(&done);
|
||||
lis(scratch2, Operand(SIGN_EXT_IMM16(0x8000)));
|
||||
cmp(scratch1, scratch2);
|
||||
bind(&done);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::TestDoubleSign(DoubleRegister input, Register scratch) {
|
||||
#if V8_TARGET_ARCH_PPC64
|
||||
MovDoubleToInt64(scratch, input);
|
||||
|
@ -876,8 +876,6 @@ class MacroAssembler : public Assembler {
|
||||
// CR_EQ in cr7 holds the result.
|
||||
void TestDoubleIsMinusZero(DoubleRegister input, Register scratch1,
|
||||
Register scratch2);
|
||||
void TestHeapNumberIsMinusZero(Register input, Register scratch1,
|
||||
Register scratch2);
|
||||
|
||||
// Check the sign of a double.
|
||||
// CR_LT in cr7 holds the result.
|
||||
|
@ -238,16 +238,6 @@ RUNTIME_FUNCTION(Runtime_MathFround) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_IsMinusZero) {
|
||||
SealHandleScope shs(isolate);
|
||||
DCHECK(args.length() == 1);
|
||||
CONVERT_ARG_CHECKED(Object, obj, 0);
|
||||
if (!obj->IsHeapNumber()) return isolate->heap()->false_value();
|
||||
HeapNumber* number = HeapNumber::cast(obj);
|
||||
return isolate->heap()->ToBoolean(IsMinusZero(number->value()));
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_GenerateRandomNumbers) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 1);
|
||||
|
@ -388,7 +388,6 @@ namespace internal {
|
||||
F(RoundNumber, 1, 1) \
|
||||
F(MathSqrt, 1, 1) \
|
||||
F(MathFround, 1, 1) \
|
||||
F(IsMinusZero, 1, 1) \
|
||||
F(GenerateRandomNumbers, 1, 1)
|
||||
|
||||
|
||||
|
@ -104,18 +104,6 @@ TEST(IsFunction) {
|
||||
}
|
||||
|
||||
|
||||
TEST(IsMinusZero) {
|
||||
FunctionTester T("(function(a) { return %_IsMinusZero(a); })", flags);
|
||||
|
||||
T.CheckFalse(T.Val(1));
|
||||
T.CheckFalse(T.Val(1.1));
|
||||
T.CheckTrue(T.Val(-0.0));
|
||||
T.CheckFalse(T.Val(-2));
|
||||
T.CheckFalse(T.Val(-2.3));
|
||||
T.CheckFalse(T.undefined());
|
||||
}
|
||||
|
||||
|
||||
TEST(IsRegExp) {
|
||||
FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags);
|
||||
|
||||
|
@ -37,31 +37,8 @@ assertEquals(0, add(0, 0));
|
||||
assertEquals(-0, add(-0, -0));
|
||||
|
||||
|
||||
function test(x, y) {
|
||||
assertTrue(%_IsMinusZero(-0));
|
||||
assertTrue(%_IsMinusZero(1/(-Infinity)));
|
||||
assertTrue(%_IsMinusZero(x));
|
||||
|
||||
assertFalse(%_IsMinusZero(0));
|
||||
assertFalse(%_IsMinusZero(1/Infinity));
|
||||
assertFalse(%_IsMinusZero(0.1));
|
||||
assertFalse(%_IsMinusZero(-0.2));
|
||||
assertFalse(%_IsMinusZero({}));
|
||||
assertFalse(%_IsMinusZero(""));
|
||||
assertFalse(%_IsMinusZero("-0"));
|
||||
assertFalse(%_IsMinusZero(function() {}));
|
||||
assertFalse(%_IsMinusZero(y));
|
||||
}
|
||||
|
||||
test(-0, 1.2);
|
||||
test(-0, 1.2);
|
||||
%OptimizeFunctionOnNextCall(test);
|
||||
test(-0, 1.2);
|
||||
assertOptimized(test);
|
||||
|
||||
|
||||
function testsin() {
|
||||
assertTrue(%_IsMinusZero(Math.sin(-0)));
|
||||
assertEquals(-0, Math.sin(-0));
|
||||
}
|
||||
|
||||
testsin();
|
||||
@ -71,8 +48,7 @@ testsin();
|
||||
|
||||
|
||||
function testfloor() {
|
||||
assertTrue(%_IsMinusZero(Math.floor(-0)));
|
||||
assertFalse(%_IsMinusZero(Math.floor(2)));
|
||||
assertEquals(-0, Math.floor(-0));
|
||||
}
|
||||
|
||||
testfloor();
|
||||
|
@ -26,10 +26,6 @@ function test() {
|
||||
|
||||
assertTrue(%_IsJSReceiver(new Date()));
|
||||
assertFalse(%_IsJSReceiver(1));
|
||||
|
||||
assertTrue(%_IsMinusZero(-0.0));
|
||||
assertFalse(%_IsMinusZero(1));
|
||||
assertFalse(%_IsMinusZero(""));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user