Commit dbb52a1c authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[bigint,compiler] Fully implement ToNumeric bytecode.

TBR: rmcilroy@chromium.org
Bug: v8:6791
Change-Id: I4ac2bdce353d987a2fe45149d8556b6591569a01
Reviewed-on: https://chromium-review.googlesource.com/771191
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49528}
parent a8152658
...@@ -2521,9 +2521,25 @@ void BytecodeGraphBuilder::VisitToNumber() { ...@@ -2521,9 +2521,25 @@ void BytecodeGraphBuilder::VisitToNumber() {
} }
void BytecodeGraphBuilder::VisitToNumeric() { void BytecodeGraphBuilder::VisitToNumeric() {
// TODO(neis): This is currently only correct in the absence of bigints. PrepareEagerCheckpoint();
DCHECK(!FLAG_harmony_bigint); Node* object = environment()->LookupAccumulator();
VisitToNumber();
// If we have some kind of Number feedback, we do the same lowering as for
// ToNumber.
FeedbackSlot slot =
feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(0));
JSTypeHintLowering::LoweringResult lowering =
TryBuildSimplifiedToNumber(object, slot);
Node* node = nullptr;
if (lowering.IsSideEffectFree()) {
node = lowering.value();
} else {
DCHECK(!lowering.Changed());
node = NewNode(javascript()->ToNumeric(), object);
}
environment()->BindAccumulator(node, Environment::kAttachFrameState);
} }
void BytecodeGraphBuilder::VisitJump() { BuildJump(); } void BytecodeGraphBuilder::VisitJump() { BuildJump(); }
......
...@@ -63,6 +63,7 @@ bool CanBeNullOrUndefined(Node* node) { ...@@ -63,6 +63,7 @@ bool CanBeNullOrUndefined(Node* node) {
case IrOpcode::kJSToLength: case IrOpcode::kJSToLength:
case IrOpcode::kJSToName: case IrOpcode::kJSToName:
case IrOpcode::kJSToNumber: case IrOpcode::kJSToNumber:
case IrOpcode::kJSToNumeric:
case IrOpcode::kJSToString: case IrOpcode::kJSToString:
return false; return false;
case IrOpcode::kHeapConstant: { case IrOpcode::kHeapConstant: {
......
...@@ -75,6 +75,7 @@ REPLACE_STUB_CALL(Equal) ...@@ -75,6 +75,7 @@ REPLACE_STUB_CALL(Equal)
REPLACE_STUB_CALL(ToInteger) REPLACE_STUB_CALL(ToInteger)
REPLACE_STUB_CALL(ToLength) REPLACE_STUB_CALL(ToLength)
REPLACE_STUB_CALL(ToNumber) REPLACE_STUB_CALL(ToNumber)
REPLACE_STUB_CALL(ToNumeric)
REPLACE_STUB_CALL(ToName) REPLACE_STUB_CALL(ToName)
REPLACE_STUB_CALL(ToObject) REPLACE_STUB_CALL(ToObject)
REPLACE_STUB_CALL(ToString) REPLACE_STUB_CALL(ToString)
......
...@@ -581,6 +581,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) { ...@@ -581,6 +581,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
V(ToLength, Operator::kNoProperties, 1, 1) \ V(ToLength, Operator::kNoProperties, 1, 1) \
V(ToName, Operator::kNoProperties, 1, 1) \ V(ToName, Operator::kNoProperties, 1, 1) \
V(ToNumber, Operator::kNoProperties, 1, 1) \ V(ToNumber, Operator::kNoProperties, 1, 1) \
V(ToNumeric, Operator::kNoProperties, 1, 1) \
V(ToObject, Operator::kFoldable, 1, 1) \ V(ToObject, Operator::kFoldable, 1, 1) \
V(ToString, Operator::kNoProperties, 1, 1) \ V(ToString, Operator::kNoProperties, 1, 1) \
V(Create, Operator::kNoProperties, 2, 1) \ V(Create, Operator::kNoProperties, 2, 1) \
......
...@@ -656,6 +656,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final ...@@ -656,6 +656,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* ToLength(); const Operator* ToLength();
const Operator* ToName(); const Operator* ToName();
const Operator* ToNumber(); const Operator* ToNumber();
const Operator* ToNumeric();
const Operator* ToObject(); const Operator* ToObject();
const Operator* ToString(); const Operator* ToString();
......
...@@ -364,7 +364,7 @@ class JSBinopReduction final { ...@@ -364,7 +364,7 @@ class JSBinopReduction final {
Node* ConvertPlainPrimitiveToNumber(Node* node) { Node* ConvertPlainPrimitiveToNumber(Node* node) {
DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive())); DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
// Avoid inserting too many eager ToNumber() operations. // Avoid inserting too many eager ToNumber() operations.
Reduction const reduction = lowering_->ReduceJSToNumberInput(node); Reduction const reduction = lowering_->ReduceJSToNumberOrNumericInput(node);
if (reduction.Changed()) return reduction.replacement(); if (reduction.Changed()) return reduction.replacement();
if (NodeProperties::GetType(node)->Is(Type::Number())) { if (NodeProperties::GetType(node)->Is(Type::Number())) {
return node; return node;
...@@ -900,8 +900,9 @@ Reduction JSTypedLowering::ReduceJSToLength(Node* node) { ...@@ -900,8 +900,9 @@ Reduction JSTypedLowering::ReduceJSToLength(Node* node) {
return NoChange(); return NoChange();
} }
Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { Reduction JSTypedLowering::ReduceJSToNumberOrNumericInput(Node* input) {
// Try constant-folding of JSToNumber with constant inputs. // Try constant-folding of JSToNumber/JSToNumeric with constant inputs. Here
// we only cover cases where ToNumber and ToNumeric coincide.
Type* input_type = NodeProperties::GetType(input); Type* input_type = NodeProperties::GetType(input);
if (input_type->Is(Type::String())) { if (input_type->Is(Type::String())) {
HeapObjectMatcher m(input); HeapObjectMatcher m(input);
...@@ -933,10 +934,10 @@ Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { ...@@ -933,10 +934,10 @@ Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
return NoChange(); return NoChange();
} }
Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { Reduction JSTypedLowering::ReduceJSToNumberOrNumeric(Node* node) {
// Try to reduce the input first. // Try to reduce the input first.
Node* const input = node->InputAt(0); Node* const input = node->InputAt(0);
Reduction reduction = ReduceJSToNumberInput(input); Reduction reduction = ReduceJSToNumberOrNumericInput(input);
if (reduction.Changed()) { if (reduction.Changed()) {
ReplaceWithValue(node, reduction.replacement()); ReplaceWithValue(node, reduction.replacement());
return reduction; return reduction;
...@@ -945,6 +946,10 @@ Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { ...@@ -945,6 +946,10 @@ Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
if (input_type->Is(Type::PlainPrimitive())) { if (input_type->Is(Type::PlainPrimitive())) {
RelaxEffectsAndControls(node); RelaxEffectsAndControls(node);
node->TrimInputCount(1); node->TrimInputCount(1);
// For a PlainPrimitive, ToNumeric is the same as ToNumber.
Type* node_type = NodeProperties::GetType(node);
NodeProperties::SetType(
node, Type::Intersect(node_type, Type::Number(), graph()->zone()));
NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber()); NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber());
return Changed(node); return Changed(node);
} }
...@@ -2070,7 +2075,8 @@ Reduction JSTypedLowering::Reduce(Node* node) { ...@@ -2070,7 +2075,8 @@ Reduction JSTypedLowering::Reduce(Node* node) {
case IrOpcode::kJSToName: case IrOpcode::kJSToName:
return ReduceJSToName(node); return ReduceJSToName(node);
case IrOpcode::kJSToNumber: case IrOpcode::kJSToNumber:
return ReduceJSToNumber(node); case IrOpcode::kJSToNumeric:
return ReduceJSToNumberOrNumeric(node);
case IrOpcode::kJSToString: case IrOpcode::kJSToString:
return ReduceJSToString(node); return ReduceJSToString(node);
case IrOpcode::kJSToObject: case IrOpcode::kJSToObject:
......
...@@ -53,8 +53,8 @@ class V8_EXPORT_PRIVATE JSTypedLowering final ...@@ -53,8 +53,8 @@ class V8_EXPORT_PRIVATE JSTypedLowering final
Reduction ReduceJSToInteger(Node* node); Reduction ReduceJSToInteger(Node* node);
Reduction ReduceJSToLength(Node* node); Reduction ReduceJSToLength(Node* node);
Reduction ReduceJSToName(Node* node); Reduction ReduceJSToName(Node* node);
Reduction ReduceJSToNumberInput(Node* input); Reduction ReduceJSToNumberOrNumericInput(Node* input);
Reduction ReduceJSToNumber(Node* node); Reduction ReduceJSToNumberOrNumeric(Node* node);
Reduction ReduceJSToStringInput(Node* input); Reduction ReduceJSToStringInput(Node* input);
Reduction ReduceJSToString(Node* node); Reduction ReduceJSToString(Node* node);
Reduction ReduceJSToObject(Node* node); Reduction ReduceJSToObject(Node* node);
......
...@@ -318,6 +318,7 @@ InductionVariable* LoopVariableOptimizer::TryGetInductionVariable(Node* phi) { ...@@ -318,6 +318,7 @@ InductionVariable* LoopVariableOptimizer::TryGetInductionVariable(Node* phi) {
} }
// TODO(jarin) Support both sides. // TODO(jarin) Support both sides.
// XXX
if (arith->InputAt(0) != phi) { if (arith->InputAt(0) != phi) {
if ((arith->InputAt(0)->opcode() != IrOpcode::kJSToNumber && if ((arith->InputAt(0)->opcode() != IrOpcode::kJSToNumber &&
arith->InputAt(0)->opcode() != IrOpcode::kSpeculativeToNumber) || arith->InputAt(0)->opcode() != IrOpcode::kSpeculativeToNumber) ||
......
...@@ -120,6 +120,7 @@ ...@@ -120,6 +120,7 @@
V(JSToLength) \ V(JSToLength) \
V(JSToName) \ V(JSToName) \
V(JSToNumber) \ V(JSToNumber) \
V(JSToNumeric) \
V(JSToObject) \ V(JSToObject) \
V(JSToString) V(JSToString)
......
...@@ -245,7 +245,7 @@ Type* OperationTyper::ConvertReceiver(Type* type) { ...@@ -245,7 +245,7 @@ Type* OperationTyper::ConvertReceiver(Type* type) {
return type; return type;
} }
Type* OperationTyper::ToNumber(Type* type) { Type* OperationTyper::ToNumberOrNumeric(Object::Conversion mode, Type* type) {
if (type->Is(Type::Number())) return type; if (type->Is(Type::Number())) return type;
if (type->Is(Type::NullOrUndefined())) { if (type->Is(Type::NullOrUndefined())) {
if (type->Is(Type::Null())) return cache_.kSingletonZero; if (type->Is(Type::Null())) return cache_.kSingletonZero;
...@@ -269,7 +269,19 @@ Type* OperationTyper::ToNumber(Type* type) { ...@@ -269,7 +269,19 @@ Type* OperationTyper::ToNumber(Type* type) {
} }
return Type::Intersect(type, Type::Number(), zone()); return Type::Intersect(type, Type::Number(), zone());
} }
return Type::Number(); if (type->Is(Type::BigInt())) {
return mode == Object::Conversion::kToNumber ? Type::None() : type;
}
return mode == Object::Conversion::kToNumber ? Type::Number()
: Type::Numeric();
}
Type* OperationTyper::ToNumber(Type* type) {
return ToNumberOrNumeric(Object::Conversion::kToNumber, type);
}
Type* OperationTyper::ToNumeric(Type* type) {
return ToNumberOrNumeric(Object::Conversion::kToNumeric, type);
} }
Type* OperationTyper::NumberAbs(Type* type) { Type* OperationTyper::NumberAbs(Type* type) {
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/base/flags.h" #include "src/base/flags.h"
#include "src/compiler/opcodes.h" #include "src/compiler/opcodes.h"
#include "src/objects.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -31,9 +32,9 @@ class V8_EXPORT_PRIVATE OperationTyper { ...@@ -31,9 +32,9 @@ class V8_EXPORT_PRIVATE OperationTyper {
Type* Merge(Type* left, Type* right); Type* Merge(Type* left, Type* right);
Type* ToPrimitive(Type* type); Type* ToPrimitive(Type* type);
// Helpers for number operation typing.
Type* ToNumber(Type* type); Type* ToNumber(Type* type);
Type* ToNumeric(Type* type);
Type* WeakenRange(Type* current_range, Type* previous_range); Type* WeakenRange(Type* current_range, Type* previous_range);
// Number unary operators. // Number unary operators.
...@@ -73,6 +74,8 @@ class V8_EXPORT_PRIVATE OperationTyper { ...@@ -73,6 +74,8 @@ class V8_EXPORT_PRIVATE OperationTyper {
private: private:
typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome; typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome;
Type* ToNumberOrNumeric(Object::Conversion mode, Type* type);
ComparisonOutcome Invert(ComparisonOutcome); ComparisonOutcome Invert(ComparisonOutcome);
Type* Invert(Type*); Type* Invert(Type*);
Type* FalsifyUndefined(ComparisonOutcome); Type* FalsifyUndefined(ComparisonOutcome);
......
...@@ -93,6 +93,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) { ...@@ -93,6 +93,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) {
case IrOpcode::kJSToLength: case IrOpcode::kJSToLength:
case IrOpcode::kJSToName: case IrOpcode::kJSToName:
case IrOpcode::kJSToNumber: case IrOpcode::kJSToNumber:
case IrOpcode::kJSToNumeric:
case IrOpcode::kJSToObject: case IrOpcode::kJSToObject:
case IrOpcode::kJSToString: case IrOpcode::kJSToString:
......
...@@ -1558,15 +1558,18 @@ class RepresentationSelector { ...@@ -1558,15 +1558,18 @@ class RepresentationSelector {
} }
return; return;
} }
case IrOpcode::kJSToNumber: { case IrOpcode::kJSToNumber:
case IrOpcode::kJSToNumeric: {
VisitInputs(node); VisitInputs(node);
// TODO(bmeurer): Optimize somewhat based on input type? // TODO(bmeurer): Optimize somewhat based on input type?
if (truncation.IsUsedAsWord32()) { if (truncation.IsUsedAsWord32()) {
SetOutput(node, MachineRepresentation::kWord32); SetOutput(node, MachineRepresentation::kWord32);
if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this); if (lower())
lowering->DoJSToNumberOrNumericTruncatesToWord32(node, this);
} else if (truncation.IsUsedAsFloat64()) { } else if (truncation.IsUsedAsFloat64()) {
SetOutput(node, MachineRepresentation::kFloat64); SetOutput(node, MachineRepresentation::kFloat64);
if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this); if (lower())
lowering->DoJSToNumberOrNumericTruncatesToFloat64(node, this);
} else { } else {
SetOutput(node, MachineRepresentation::kTagged); SetOutput(node, MachineRepresentation::kTagged);
} }
...@@ -3181,9 +3184,10 @@ void SimplifiedLowering::LowerAllNodes() { ...@@ -3181,9 +3184,10 @@ void SimplifiedLowering::LowerAllNodes() {
selector.Run(this); selector.Run(this);
} }
void SimplifiedLowering::DoJSToNumberTruncatesToFloat64( void SimplifiedLowering::DoJSToNumberOrNumericTruncatesToFloat64(
Node* node, RepresentationSelector* selector) { Node* node, RepresentationSelector* selector) {
DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode()); DCHECK(node->opcode() == IrOpcode::kJSToNumber ||
node->opcode() == IrOpcode::kJSToNumeric);
Node* value = node->InputAt(0); Node* value = node->InputAt(0);
Node* context = node->InputAt(1); Node* context = node->InputAt(1);
Node* frame_state = node->InputAt(2); Node* frame_state = node->InputAt(2);
...@@ -3206,12 +3210,16 @@ void SimplifiedLowering::DoJSToNumberTruncatesToFloat64( ...@@ -3206,12 +3210,16 @@ void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
Node* efalse0 = effect; Node* efalse0 = effect;
Node* vfalse0; Node* vfalse0;
{ {
vfalse0 = efalse0 = if_false0 = Operator const* op = node->opcode() == IrOpcode::kJSToNumber
graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context, ? ToNumberOperator()
frame_state, efalse0, if_false0); : ToNumericOperator();
Node* code = node->opcode() == IrOpcode::kJSToNumber ? ToNumberCode()
: ToNumericCode();
vfalse0 = efalse0 = if_false0 = graph()->NewNode(
op, code, value, context, frame_state, efalse0, if_false0);
// Update potential {IfException} uses of {node} to point to the above // Update potential {IfException} uses of {node} to point to the above
// {ToNumber} stub call node instead. // stub call node instead.
Node* on_exception = nullptr; Node* on_exception = nullptr;
if (NodeProperties::IsExceptionalCall(node, &on_exception)) { if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
NodeProperties::ReplaceControlInput(on_exception, vfalse0); NodeProperties::ReplaceControlInput(on_exception, vfalse0);
...@@ -3271,9 +3279,10 @@ void SimplifiedLowering::DoJSToNumberTruncatesToFloat64( ...@@ -3271,9 +3279,10 @@ void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
selector->DeferReplacement(node, value); selector->DeferReplacement(node, value);
} }
void SimplifiedLowering::DoJSToNumberTruncatesToWord32( void SimplifiedLowering::DoJSToNumberOrNumericTruncatesToWord32(
Node* node, RepresentationSelector* selector) { Node* node, RepresentationSelector* selector) {
DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode()); DCHECK(node->opcode() == IrOpcode::kJSToNumber ||
node->opcode() == IrOpcode::kJSToNumeric);
Node* value = node->InputAt(0); Node* value = node->InputAt(0);
Node* context = node->InputAt(1); Node* context = node->InputAt(1);
Node* frame_state = node->InputAt(2); Node* frame_state = node->InputAt(2);
...@@ -3293,12 +3302,16 @@ void SimplifiedLowering::DoJSToNumberTruncatesToWord32( ...@@ -3293,12 +3302,16 @@ void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
Node* efalse0 = effect; Node* efalse0 = effect;
Node* vfalse0; Node* vfalse0;
{ {
vfalse0 = efalse0 = if_false0 = Operator const* op = node->opcode() == IrOpcode::kJSToNumber
graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context, ? ToNumberOperator()
frame_state, efalse0, if_false0); : ToNumericOperator();
Node* code = node->opcode() == IrOpcode::kJSToNumber ? ToNumberCode()
: ToNumericCode();
vfalse0 = efalse0 = if_false0 = graph()->NewNode(
op, code, value, context, frame_state, efalse0, if_false0);
// Update potential {IfException} uses of {node} to point to the above // Update potential {IfException} uses of {node} to point to the above
// {ToNumber} stub call node instead. // stub call node instead.
Node* on_exception = nullptr; Node* on_exception = nullptr;
if (NodeProperties::IsExceptionalCall(node, &on_exception)) { if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
NodeProperties::ReplaceControlInput(on_exception, vfalse0); NodeProperties::ReplaceControlInput(on_exception, vfalse0);
...@@ -3798,6 +3811,14 @@ Node* SimplifiedLowering::ToNumberCode() { ...@@ -3798,6 +3811,14 @@ Node* SimplifiedLowering::ToNumberCode() {
return to_number_code_.get(); return to_number_code_.get();
} }
Node* SimplifiedLowering::ToNumericCode() {
if (!to_numeric_code_.is_set()) {
Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumeric);
to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
}
return to_numeric_code_.get();
}
Operator const* SimplifiedLowering::ToNumberOperator() { Operator const* SimplifiedLowering::ToNumberOperator() {
if (!to_number_operator_.is_set()) { if (!to_number_operator_.is_set()) {
Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumber); Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumber);
...@@ -3810,6 +3831,18 @@ Operator const* SimplifiedLowering::ToNumberOperator() { ...@@ -3810,6 +3831,18 @@ Operator const* SimplifiedLowering::ToNumberOperator() {
return to_number_operator_.get(); return to_number_operator_.get();
} }
Operator const* SimplifiedLowering::ToNumericOperator() {
if (!to_numeric_operator_.is_set()) {
Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumeric);
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), callable.descriptor(), 0, flags,
Operator::kNoProperties);
to_numeric_operator_.set(common()->Call(desc));
}
return to_numeric_operator_.get();
}
#undef TRACE #undef TRACE
} // namespace compiler } // namespace compiler
......
...@@ -30,9 +30,9 @@ class SimplifiedLowering final { ...@@ -30,9 +30,9 @@ class SimplifiedLowering final {
void DoMax(Node* node, Operator const* op, MachineRepresentation rep); void DoMax(Node* node, Operator const* op, MachineRepresentation rep);
void DoMin(Node* node, Operator const* op, MachineRepresentation rep); void DoMin(Node* node, Operator const* op, MachineRepresentation rep);
void DoJSToNumberTruncatesToFloat64(Node* node, void DoJSToNumberOrNumericTruncatesToFloat64(
RepresentationSelector* selector); Node* node, RepresentationSelector* selector);
void DoJSToNumberTruncatesToWord32(Node* node, void DoJSToNumberOrNumericTruncatesToWord32(Node* node,
RepresentationSelector* selector); RepresentationSelector* selector);
void DoShift(Node* node, Operator const* op, Type* rhs_type); void DoShift(Node* node, Operator const* op, Type* rhs_type);
void DoIntegral32ToBit(Node* node); void DoIntegral32ToBit(Node* node);
...@@ -48,7 +48,9 @@ class SimplifiedLowering final { ...@@ -48,7 +48,9 @@ class SimplifiedLowering final {
Zone* const zone_; Zone* const zone_;
TypeCache const& type_cache_; TypeCache const& type_cache_;
SetOncePointer<Node> to_number_code_; SetOncePointer<Node> to_number_code_;
SetOncePointer<Node> to_numeric_code_;
SetOncePointer<Operator const> to_number_operator_; SetOncePointer<Operator const> to_number_operator_;
SetOncePointer<Operator const> to_numeric_operator_;
// TODO(danno): SimplifiedLowering shouldn't know anything about the source // TODO(danno): SimplifiedLowering shouldn't know anything about the source
// positions table, but must for now since there currently is no other way to // positions table, but must for now since there currently is no other way to
...@@ -67,7 +69,9 @@ class SimplifiedLowering final { ...@@ -67,7 +69,9 @@ class SimplifiedLowering final {
Node* Uint32Mod(Node* const node); Node* Uint32Mod(Node* const node);
Node* ToNumberCode(); Node* ToNumberCode();
Node* ToNumericCode();
Operator const* ToNumberOperator(); Operator const* ToNumberOperator();
Operator const* ToNumericOperator();
friend class RepresentationSelector; friend class RepresentationSelector;
......
...@@ -270,6 +270,7 @@ class Typer::Visitor : public Reducer { ...@@ -270,6 +270,7 @@ class Typer::Visitor : public Reducer {
static Type* ToLength(Type*, Typer*); static Type* ToLength(Type*, Typer*);
static Type* ToName(Type*, Typer*); static Type* ToName(Type*, Typer*);
static Type* ToNumber(Type*, Typer*); static Type* ToNumber(Type*, Typer*);
static Type* ToNumeric(Type*, Typer*);
static Type* ToObject(Type*, Typer*); static Type* ToObject(Type*, Typer*);
static Type* ToString(Type*, Typer*); static Type* ToString(Type*, Typer*);
#define DECLARE_METHOD(Name) \ #define DECLARE_METHOD(Name) \
...@@ -492,6 +493,10 @@ Type* Typer::Visitor::ToNumber(Type* type, Typer* t) { ...@@ -492,6 +493,10 @@ Type* Typer::Visitor::ToNumber(Type* type, Typer* t) {
return t->operation_typer_.ToNumber(type); return t->operation_typer_.ToNumber(type);
} }
// static
Type* Typer::Visitor::ToNumeric(Type* type, Typer* t) {
return t->operation_typer_.ToNumeric(type);
}
// static // static
Type* Typer::Visitor::ToObject(Type* type, Typer* t) { Type* Typer::Visitor::ToObject(Type* type, Typer* t) {
...@@ -1095,6 +1100,10 @@ Type* Typer::Visitor::TypeJSToNumber(Node* node) { ...@@ -1095,6 +1100,10 @@ Type* Typer::Visitor::TypeJSToNumber(Node* node) {
return TypeUnaryOp(node, ToNumber); return TypeUnaryOp(node, ToNumber);
} }
Type* Typer::Visitor::TypeJSToNumeric(Node* node) {
return TypeUnaryOp(node, ToNumeric);
}
Type* Typer::Visitor::TypeJSToObject(Node* node) { Type* Typer::Visitor::TypeJSToObject(Node* node) {
return TypeUnaryOp(node, ToObject); return TypeUnaryOp(node, ToObject);
} }
......
...@@ -631,6 +631,10 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -631,6 +631,10 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
// Type is Number. // Type is Number.
CheckTypeIs(node, Type::Number()); CheckTypeIs(node, Type::Number());
break; break;
case IrOpcode::kJSToNumeric:
// Type is Numeric.
CheckTypeIs(node, Type::Numeric());
break;
case IrOpcode::kJSToString: case IrOpcode::kJSToString:
// Type is String. // Type is String.
CheckTypeIs(node, Type::String()); CheckTypeIs(node, Type::String());
......
...@@ -3719,7 +3719,7 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -3719,7 +3719,7 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
old_value = register_allocator()->NewRegister(); old_value = register_allocator()->NewRegister();
// Convert old value into a number before saving it. // Convert old value into a number before saving it.
// TODO(ignition): Think about adding proper PostInc/PostDec bytecodes // TODO(ignition): Think about adding proper PostInc/PostDec bytecodes
// instead of this ToNumber + Inc/Dec dance. // instead of this ToNumeric + Inc/Dec dance.
builder() builder()
->ToNumeric(feedback_index(count_slot)) ->ToNumeric(feedback_index(count_slot))
.StoreAccumulatorInRegister(old_value); .StoreAccumulatorInRegister(old_value);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment