Commit 2742b303 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Introduce ObjectIsString operator.

This adds an ObjectIsString operator and hooks it up with
JSNativeContextSpecialization (to remove the use of some machine
operators there).

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1894523002

Cr-Commit-Position: refs/heads/master@{#35525}
parent dfb945d5
...@@ -49,12 +49,14 @@ Reduction ChangeLowering::Reduce(Node* node) { ...@@ -49,12 +49,14 @@ Reduction ChangeLowering::Reduce(Node* node) {
return StoreElement(node); return StoreElement(node);
case IrOpcode::kAllocate: case IrOpcode::kAllocate:
return Allocate(node); return Allocate(node);
case IrOpcode::kObjectIsNumber:
return ObjectIsNumber(node);
case IrOpcode::kObjectIsReceiver: case IrOpcode::kObjectIsReceiver:
return ObjectIsReceiver(node); return ObjectIsReceiver(node);
case IrOpcode::kObjectIsSmi: case IrOpcode::kObjectIsSmi:
return ObjectIsSmi(node); return ObjectIsSmi(node);
case IrOpcode::kObjectIsNumber: case IrOpcode::kObjectIsString:
return ObjectIsNumber(node); return ObjectIsString(node);
case IrOpcode::kObjectIsUndetectable: case IrOpcode::kObjectIsUndetectable:
return ObjectIsUndetectable(node); return ObjectIsUndetectable(node);
default: default:
...@@ -756,6 +758,25 @@ Reduction ChangeLowering::ObjectIsSmi(Node* node) { ...@@ -756,6 +758,25 @@ Reduction ChangeLowering::ObjectIsSmi(Node* node) {
return Changed(node); return Changed(node);
} }
Reduction ChangeLowering::ObjectIsString(Node* node) {
Node* input = NodeProperties::GetValueInput(node, 0);
Node* check = IsSmi(input);
Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* vtrue = jsgraph()->Int32Constant(0);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* vfalse =
graph()->NewNode(machine()->Uint32LessThan(),
LoadMapInstanceType(LoadHeapObjectMap(input, if_false)),
jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
Node* control = graph()->NewNode(common()->Merge(2), if_true, if_false);
node->ReplaceInput(0, vtrue);
node->AppendInput(graph()->zone(), vfalse);
node->AppendInput(graph()->zone(), control);
NodeProperties::ChangeOp(node, common()->Phi(MachineRepresentation::kBit, 2));
return Changed(node);
}
Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); } Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); }
......
...@@ -64,6 +64,7 @@ class ChangeLowering final : public Reducer { ...@@ -64,6 +64,7 @@ class ChangeLowering final : public Reducer {
Reduction ObjectIsNumber(Node* node); Reduction ObjectIsNumber(Node* node);
Reduction ObjectIsReceiver(Node* node); Reduction ObjectIsReceiver(Node* node);
Reduction ObjectIsSmi(Node* node); Reduction ObjectIsSmi(Node* node);
Reduction ObjectIsString(Node* node);
Reduction ObjectIsUndetectable(Node* node); Reduction ObjectIsUndetectable(Node* node);
Node* ComputeIndex(const ElementAccess& access, Node* const key); Node* ComputeIndex(const ElementAccess& access, Node* const key);
......
...@@ -157,13 +157,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( ...@@ -157,13 +157,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
// Perform map check on {receiver}. // Perform map check on {receiver}.
Type* receiver_type = access_info.receiver_type(); Type* receiver_type = access_info.receiver_type();
if (receiver_type->Is(Type::String())) { if (receiver_type->Is(Type::String())) {
// Emit an instance type check for strings. Node* check = graph()->NewNode(simplified()->ObjectIsString(), receiver);
Node* receiver_instance_type = this_effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
receiver_map, this_effect, fallthrough_control);
Node* check =
graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type,
jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
if (j == access_infos.size() - 1) { if (j == access_infos.size() - 1) {
this_control = this_control =
graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
......
...@@ -214,6 +214,7 @@ ...@@ -214,6 +214,7 @@
V(ObjectIsNumber) \ V(ObjectIsNumber) \
V(ObjectIsReceiver) \ V(ObjectIsReceiver) \
V(ObjectIsSmi) \ V(ObjectIsSmi) \
V(ObjectIsString) \
V(ObjectIsUndetectable) V(ObjectIsUndetectable)
// Opcodes for Machine-level operators. // Opcodes for Machine-level operators.
......
...@@ -1192,6 +1192,7 @@ class RepresentationSelector { ...@@ -1192,6 +1192,7 @@ class RepresentationSelector {
case IrOpcode::kObjectIsNumber: case IrOpcode::kObjectIsNumber:
case IrOpcode::kObjectIsReceiver: case IrOpcode::kObjectIsReceiver:
case IrOpcode::kObjectIsSmi: case IrOpcode::kObjectIsSmi:
case IrOpcode::kObjectIsString:
case IrOpcode::kObjectIsUndetectable: { case IrOpcode::kObjectIsUndetectable: {
ProcessInput(node, 0, UseInfo::AnyTagged()); ProcessInput(node, 0, UseInfo::AnyTagged());
SetOutput(node, MachineRepresentation::kBit); SetOutput(node, MachineRepresentation::kBit);
......
...@@ -193,6 +193,7 @@ const ElementAccess& ElementAccessOf(const Operator* op) { ...@@ -193,6 +193,7 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
V(ObjectIsNumber, Operator::kNoProperties, 1) \ V(ObjectIsNumber, Operator::kNoProperties, 1) \
V(ObjectIsReceiver, Operator::kNoProperties, 1) \ V(ObjectIsReceiver, Operator::kNoProperties, 1) \
V(ObjectIsSmi, Operator::kNoProperties, 1) \ V(ObjectIsSmi, Operator::kNoProperties, 1) \
V(ObjectIsString, Operator::kNoProperties, 1) \
V(ObjectIsUndetectable, Operator::kNoProperties, 1) V(ObjectIsUndetectable, Operator::kNoProperties, 1)
#define NO_THROW_OP_LIST(V) \ #define NO_THROW_OP_LIST(V) \
......
...@@ -171,6 +171,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject { ...@@ -171,6 +171,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* ObjectIsNumber(); const Operator* ObjectIsNumber();
const Operator* ObjectIsReceiver(); const Operator* ObjectIsReceiver();
const Operator* ObjectIsSmi(); const Operator* ObjectIsSmi();
const Operator* ObjectIsString();
const Operator* ObjectIsUndetectable(); const Operator* ObjectIsUndetectable();
const Operator* Allocate(PretenureFlag pretenure = NOT_TENURED); const Operator* Allocate(PretenureFlag pretenure = NOT_TENURED);
......
...@@ -250,6 +250,7 @@ class Typer::Visitor : public Reducer { ...@@ -250,6 +250,7 @@ class Typer::Visitor : public Reducer {
static Type* ObjectIsNumber(Type*, Typer*); static Type* ObjectIsNumber(Type*, Typer*);
static Type* ObjectIsReceiver(Type*, Typer*); static Type* ObjectIsReceiver(Type*, Typer*);
static Type* ObjectIsSmi(Type*, Typer*); static Type* ObjectIsSmi(Type*, Typer*);
static Type* ObjectIsString(Type*, Typer*);
static Type* ObjectIsUndetectable(Type*, Typer*); static Type* ObjectIsUndetectable(Type*, Typer*);
static Type* JSAddRanger(RangeType*, RangeType*, Typer*); static Type* JSAddRanger(RangeType*, RangeType*, Typer*);
...@@ -577,6 +578,11 @@ Type* Typer::Visitor::ObjectIsSmi(Type* type, Typer* t) { ...@@ -577,6 +578,11 @@ Type* Typer::Visitor::ObjectIsSmi(Type* type, Typer* t) {
return Type::Boolean(); return Type::Boolean();
} }
Type* Typer::Visitor::ObjectIsString(Type* type, Typer* t) {
if (type->Is(Type::String())) return t->singleton_true_;
if (!type->Maybe(Type::String())) return t->singleton_false_;
return Type::Boolean();
}
Type* Typer::Visitor::ObjectIsUndetectable(Type* type, Typer* t) { Type* Typer::Visitor::ObjectIsUndetectable(Type* type, Typer* t) {
if (type->Is(Type::Undetectable())) return t->singleton_true_; if (type->Is(Type::Undetectable())) return t->singleton_true_;
...@@ -1997,6 +2003,9 @@ Type* Typer::Visitor::TypeObjectIsSmi(Node* node) { ...@@ -1997,6 +2003,9 @@ Type* Typer::Visitor::TypeObjectIsSmi(Node* node) {
return TypeUnaryOp(node, ObjectIsSmi); return TypeUnaryOp(node, ObjectIsSmi);
} }
Type* Typer::Visitor::TypeObjectIsString(Node* node) {
return TypeUnaryOp(node, ObjectIsString);
}
Type* Typer::Visitor::TypeObjectIsUndetectable(Node* node) { Type* Typer::Visitor::TypeObjectIsUndetectable(Node* node) {
return TypeUnaryOp(node, ObjectIsUndetectable); return TypeUnaryOp(node, ObjectIsUndetectable);
......
...@@ -749,6 +749,7 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -749,6 +749,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kObjectIsNumber: case IrOpcode::kObjectIsNumber:
case IrOpcode::kObjectIsReceiver: case IrOpcode::kObjectIsReceiver:
case IrOpcode::kObjectIsSmi: case IrOpcode::kObjectIsSmi:
case IrOpcode::kObjectIsString:
case IrOpcode::kObjectIsUndetectable: case IrOpcode::kObjectIsUndetectable:
CheckValueInputIs(node, 0, Type::Any()); CheckValueInputIs(node, 0, Type::Any());
CheckUpperIs(node, Type::Boolean()); CheckUpperIs(node, Type::Boolean());
......
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