[Turbofan] Model ClassOf as a simplified operator
JSClassOf may lower to a call to a builtin, and needs to be modeled in a way that the effect chain can be maintained. Bug: v8:6929 Change-Id: Ida332e6d85e2eb8b33fcad810d195ef3e897ccb0 Reviewed-on: https://chromium-review.googlesource.com/727204 Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Commit-Queue: Michael Stanton <mvstanton@chromium.org> Cr-Commit-Position: refs/heads/master@{#48786}
This commit is contained in:
parent
9884bc5dee
commit
c877c77996
@ -763,6 +763,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
|
||||
case IrOpcode::kTypeOf:
|
||||
result = LowerTypeOf(node);
|
||||
break;
|
||||
case IrOpcode::kClassOf:
|
||||
result = LowerClassOf(node);
|
||||
break;
|
||||
case IrOpcode::kNewDoubleElements:
|
||||
result = LowerNewDoubleElements(node);
|
||||
break;
|
||||
@ -2209,7 +2212,18 @@ Node* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) {
|
||||
Node* EffectControlLinearizer::LowerTypeOf(Node* node) {
|
||||
Node* obj = node->InputAt(0);
|
||||
Callable const callable = Builtins::CallableFor(isolate(), Builtins::kTypeof);
|
||||
// TODO(mvstanton): is it okay to ignore the properties from the operator?
|
||||
Operator::Properties const properties = Operator::kEliminatable;
|
||||
CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate;
|
||||
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
|
||||
isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
|
||||
return __ Call(desc, __ HeapConstant(callable.code()), obj,
|
||||
__ NoContextConstant());
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::LowerClassOf(Node* node) {
|
||||
Node* obj = node->InputAt(0);
|
||||
Callable const callable =
|
||||
Builtins::CallableFor(isolate(), Builtins::kClassOf);
|
||||
Operator::Properties const properties = Operator::kEliminatable;
|
||||
CallDescriptor::Flags const flags = CallDescriptor::kNoAllocate;
|
||||
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
|
||||
|
@ -121,6 +121,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
|
||||
void LowerCheckEqualsInternalizedString(Node* node, Node* frame_state);
|
||||
void LowerCheckEqualsSymbol(Node* node, Node* frame_state);
|
||||
Node* LowerTypeOf(Node* node);
|
||||
Node* LowerClassOf(Node* node);
|
||||
Node* LowerToBoolean(Node* node);
|
||||
Node* LowerPlainPrimitiveToNumber(Node* node);
|
||||
Node* LowerPlainPrimitiveToWord32(Node* node);
|
||||
|
@ -126,15 +126,6 @@ void JSGenericLowering::LowerJSStrictEqual(Node* node) {
|
||||
Operator::kEliminatable);
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSClassOf(Node* node) {
|
||||
// The %_ClassOf intrinsic doesn't need the current context.
|
||||
NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
|
||||
Callable callable = Builtins::CallableFor(isolate(), Builtins::kClassOf);
|
||||
node->AppendInput(zone(), graph()->start());
|
||||
ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
|
||||
Operator::kEliminatable);
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSLoadProperty(Node* node) {
|
||||
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
|
||||
const PropertyAccess& p = PropertyAccessOf(node->op());
|
||||
|
@ -385,8 +385,11 @@ Reduction JSIntrinsicLowering::ReduceTheHole(Node* node) {
|
||||
|
||||
Reduction JSIntrinsicLowering::ReduceClassOf(Node* node) {
|
||||
RelaxEffectsAndControls(node);
|
||||
// The ClassOf operator has a single value input and control input.
|
||||
Node* control_input = NodeProperties::GetControlInput(node, 0);
|
||||
node->TrimInputCount(2);
|
||||
NodeProperties::ChangeOp(node, javascript()->ClassOf());
|
||||
node->ReplaceInput(1, control_input);
|
||||
NodeProperties::ChangeOp(node, simplified()->ClassOf());
|
||||
return Changed(node);
|
||||
}
|
||||
|
||||
|
@ -592,7 +592,6 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
|
||||
V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \
|
||||
V(CreateKeyValueArray, Operator::kEliminatable, 2, 1) \
|
||||
V(HasProperty, Operator::kNoProperties, 2, 1) \
|
||||
V(ClassOf, Operator::kPure, 1, 1) \
|
||||
V(HasInPrototypeChain, Operator::kNoProperties, 2, 1) \
|
||||
V(InstanceOf, Operator::kNoProperties, 2, 1) \
|
||||
V(OrdinaryHasInstance, Operator::kNoProperties, 2, 1) \
|
||||
|
@ -121,11 +121,7 @@
|
||||
V(JSToObject) \
|
||||
V(JSToString)
|
||||
|
||||
#define JS_OTHER_UNOP_LIST(V) V(JSClassOf)
|
||||
|
||||
#define JS_SIMPLE_UNOP_LIST(V) \
|
||||
JS_CONVERSION_UNOP_LIST(V) \
|
||||
JS_OTHER_UNOP_LIST(V)
|
||||
#define JS_SIMPLE_UNOP_LIST(V) JS_CONVERSION_UNOP_LIST(V)
|
||||
|
||||
#define JS_OBJECT_OP_LIST(V) \
|
||||
V(JSCreate) \
|
||||
@ -345,6 +341,7 @@
|
||||
V(CompareMaps) \
|
||||
V(ConvertTaggedHoleToUndefined) \
|
||||
V(TypeOf) \
|
||||
V(ClassOf) \
|
||||
V(Allocate) \
|
||||
V(LoadFieldByIndex) \
|
||||
V(LoadField) \
|
||||
|
@ -2345,6 +2345,7 @@ class RepresentationSelector {
|
||||
}
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kClassOf:
|
||||
case IrOpcode::kTypeOf: {
|
||||
return VisitUnop(node, UseInfo::AnyTagged(),
|
||||
MachineRepresentation::kTaggedPointer);
|
||||
@ -2990,7 +2991,6 @@ class RepresentationSelector {
|
||||
// All JavaScript operators except JSToNumber have uniform handling.
|
||||
#define OPCODE_CASE(name) case IrOpcode::k##name:
|
||||
JS_SIMPLE_BINOP_LIST(OPCODE_CASE)
|
||||
JS_OTHER_UNOP_LIST(OPCODE_CASE)
|
||||
JS_OBJECT_OP_LIST(OPCODE_CASE)
|
||||
JS_CONTEXT_OP_LIST(OPCODE_CASE)
|
||||
JS_OTHER_OP_LIST(OPCODE_CASE)
|
||||
|
@ -558,6 +558,7 @@ DeoptimizeReason DeoptimizeReasonOf(const Operator* op) {
|
||||
V(StringToLowerCaseIntl, Operator::kNoProperties, 1, 0) \
|
||||
V(StringToUpperCaseIntl, Operator::kNoProperties, 1, 0) \
|
||||
V(TypeOf, Operator::kNoProperties, 1, 1) \
|
||||
V(ClassOf, Operator::kNoProperties, 1, 1) \
|
||||
V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0) \
|
||||
V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0) \
|
||||
V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1, 0) \
|
||||
|
@ -369,6 +369,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
|
||||
const Operator* ReferenceEqual();
|
||||
|
||||
const Operator* TypeOf();
|
||||
const Operator* ClassOf();
|
||||
|
||||
const Operator* ToBoolean(ToBooleanHints hints);
|
||||
|
||||
|
@ -1079,7 +1079,7 @@ Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
|
||||
|
||||
// JS unary operators.
|
||||
|
||||
Type* Typer::Visitor::TypeJSClassOf(Node* node) {
|
||||
Type* Typer::Visitor::TypeClassOf(Node* node) {
|
||||
return Type::InternalizedStringOrNull();
|
||||
}
|
||||
|
||||
|
@ -675,7 +675,7 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
// Type is Boolean.
|
||||
CheckTypeIs(node, Type::Boolean());
|
||||
break;
|
||||
case IrOpcode::kJSClassOf:
|
||||
case IrOpcode::kClassOf:
|
||||
// Type is InternaliedString \/ Null.
|
||||
CheckTypeIs(node, Type::InternalizedStringOrNull());
|
||||
break;
|
||||
|
@ -431,7 +431,6 @@ TEST_MONOTONICITY(ToName)
|
||||
TEST_MONOTONICITY(ToNumber)
|
||||
TEST_MONOTONICITY(ToObject)
|
||||
TEST_MONOTONICITY(ToString)
|
||||
TEST_MONOTONICITY(ClassOf)
|
||||
#undef TEST_MONOTONICITY
|
||||
|
||||
// JS BINOPs with CompareOperationHint
|
||||
@ -489,6 +488,7 @@ TEST_MONOTONICITY(ObjectIsString)
|
||||
TEST_MONOTONICITY(ObjectIsSymbol)
|
||||
TEST_MONOTONICITY(ObjectIsUndetectable)
|
||||
TEST_MONOTONICITY(TypeOf)
|
||||
TEST_MONOTONICITY(ClassOf)
|
||||
#undef TEST_MONOTONICITY
|
||||
|
||||
// SIMPLIFIED UNOPs with ToBooleanHint
|
||||
|
Loading…
Reference in New Issue
Block a user