Commit a5d251de authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Introduce TypedObjectState common operator.

This adds a new TypedObjectState operator, which is a version of
ObjectState that carries along MachineTypes for the inputs, so we
can tell the deoptimizer how to interpret the inputs, instead of
having to force everything to Tagged.

Drive-by-fix: Remove the unused id parameter from ObjectState.

R=tebbi@chromium.org
BUG=v8:5609

Review-Url: https://codereview.chromium.org/2488623002
Cr-Commit-Position: refs/heads/master@{#40832}
parent e4bae133
...@@ -235,6 +235,12 @@ OsrGuardType OsrGuardTypeOf(Operator const* op) { ...@@ -235,6 +235,12 @@ OsrGuardType OsrGuardTypeOf(Operator const* op) {
return OpParameter<OsrGuardType>(op); return OpParameter<OsrGuardType>(op);
} }
ZoneVector<MachineType> const* MachineTypesOf(Operator const* op) {
DCHECK(op->opcode() == IrOpcode::kTypedObjectState ||
op->opcode() == IrOpcode::kTypedStateValues);
return OpParameter<const ZoneVector<MachineType>*>(op);
}
#define CACHED_OP_LIST(V) \ #define CACHED_OP_LIST(V) \
V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1) \ V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1) \
V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \ V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \
...@@ -1004,24 +1010,32 @@ const Operator* CommonOperatorBuilder::StateValues(int arguments) { ...@@ -1004,24 +1010,32 @@ const Operator* CommonOperatorBuilder::StateValues(int arguments) {
arguments, 0, 0, 1, 0, 0); // counts arguments, 0, 0, 1, 0, 0); // counts
} }
const Operator* CommonOperatorBuilder::TypedStateValues(
const ZoneVector<MachineType>* types) {
return new (zone()) Operator1<const ZoneVector<MachineType>*>( // --
IrOpcode::kTypedStateValues, Operator::kPure, // opcode
"TypedStateValues", // name
static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts
types); // parameter
}
const Operator* CommonOperatorBuilder::ObjectState(int pointer_slots, int id) { const Operator* CommonOperatorBuilder::ObjectState(int pointer_slots) {
return new (zone()) Operator1<int>( // -- return new (zone()) Operator1<int>( // --
IrOpcode::kObjectState, Operator::kPure, // opcode IrOpcode::kObjectState, Operator::kPure, // opcode
"ObjectState", // name "ObjectState", // name
pointer_slots, 0, 0, 1, 0, 0, id); // counts pointer_slots, 0, 0, 1, 0, 0, // counts
pointer_slots); // parameter
} }
const Operator* CommonOperatorBuilder::TypedObjectState(
const Operator* CommonOperatorBuilder::TypedStateValues(
const ZoneVector<MachineType>* types) { const ZoneVector<MachineType>* types) {
return new (zone()) Operator1<const ZoneVector<MachineType>*>( // -- return new (zone()) Operator1<const ZoneVector<MachineType>*>( // --
IrOpcode::kTypedStateValues, Operator::kPure, // opcode IrOpcode::kTypedObjectState, Operator::kPure, // opcode
"TypedStateValues", // name "TypedObjectState", // name
static_cast<int>(types->size()), 0, 0, 1, 0, 0, types); // counts static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts
types); // parameter
} }
const Operator* CommonOperatorBuilder::FrameState( const Operator* CommonOperatorBuilder::FrameState(
BailoutId bailout_id, OutputFrameStateCombine state_combine, BailoutId bailout_id, OutputFrameStateCombine state_combine,
const FrameStateFunctionInfo* function_info) { const FrameStateFunctionInfo* function_info) {
......
...@@ -181,6 +181,9 @@ size_t hash_value(OsrGuardType type); ...@@ -181,6 +181,9 @@ size_t hash_value(OsrGuardType type);
std::ostream& operator<<(std::ostream&, OsrGuardType); std::ostream& operator<<(std::ostream&, OsrGuardType);
OsrGuardType OsrGuardTypeOf(Operator const*); OsrGuardType OsrGuardTypeOf(Operator const*);
ZoneVector<MachineType> const* MachineTypesOf(Operator const*)
WARN_UNUSED_RESULT;
// Interface for building common operators that can be used at any level of IR, // Interface for building common operators that can be used at any level of IR,
// including JavaScript, mid-level, and low-level. // including JavaScript, mid-level, and low-level.
class V8_EXPORT_PRIVATE CommonOperatorBuilder final class V8_EXPORT_PRIVATE CommonOperatorBuilder final
...@@ -240,8 +243,9 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final ...@@ -240,8 +243,9 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final
const Operator* BeginRegion(RegionObservability); const Operator* BeginRegion(RegionObservability);
const Operator* FinishRegion(); const Operator* FinishRegion();
const Operator* StateValues(int arguments); const Operator* StateValues(int arguments);
const Operator* ObjectState(int pointer_slots, int id);
const Operator* TypedStateValues(const ZoneVector<MachineType>* types); const Operator* TypedStateValues(const ZoneVector<MachineType>* types);
const Operator* ObjectState(int pointer_slots);
const Operator* TypedObjectState(const ZoneVector<MachineType>* types);
const Operator* FrameState(BailoutId bailout_id, const Operator* FrameState(BailoutId bailout_id,
OutputFrameStateCombine state_combine, OutputFrameStateCombine state_combine,
const FrameStateFunctionInfo* function_info); const FrameStateFunctionInfo* function_info);
......
...@@ -1578,8 +1578,8 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { ...@@ -1578,8 +1578,8 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
} }
int input_count = static_cast<int>(cache_->fields().size()); int input_count = static_cast<int>(cache_->fields().size());
Node* new_object_state = Node* new_object_state =
graph()->NewNode(common()->ObjectState(input_count, vobj->id()), graph()->NewNode(common()->ObjectState(input_count), input_count,
input_count, &cache_->fields().front()); &cache_->fields().front());
vobj->SetObjectState(new_object_state); vobj->SetObjectState(new_object_state);
TRACE( TRACE(
"Creating object state #%d for vobj %p (from node #%d) at effect " "Creating object state #%d for vobj %p (from node #%d) at effect "
......
...@@ -434,6 +434,7 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, ...@@ -434,6 +434,7 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
case IrOpcode::kHeapConstant: case IrOpcode::kHeapConstant:
return g->UseImmediate(input); return g->UseImmediate(input);
case IrOpcode::kObjectState: case IrOpcode::kObjectState:
case IrOpcode::kTypedObjectState:
UNREACHABLE(); UNREACHABLE();
break; break;
default: default:
...@@ -485,6 +486,10 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, ...@@ -485,6 +486,10 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor,
FrameStateInputKind kind, Zone* zone) { FrameStateInputKind kind, Zone* zone) {
switch (input->opcode()) { switch (input->opcode()) {
case IrOpcode::kObjectState: { case IrOpcode::kObjectState: {
UNREACHABLE();
return 0;
}
case IrOpcode::kTypedObjectState: {
size_t id = deduplicator->GetObjectId(input); size_t id = deduplicator->GetObjectId(input);
if (id == StateObjectDeduplicator::kNotDuplicated) { if (id == StateObjectDeduplicator::kNotDuplicated) {
size_t entries = 0; size_t entries = 0;
...@@ -492,10 +497,12 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, ...@@ -492,10 +497,12 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor,
descriptor->fields().push_back( descriptor->fields().push_back(
StateValueDescriptor::Recursive(zone, id)); StateValueDescriptor::Recursive(zone, id));
StateValueDescriptor* new_desc = &descriptor->fields().back(); StateValueDescriptor* new_desc = &descriptor->fields().back();
for (Edge edge : input->input_edges()) { int const input_count = input->op()->ValueInputCount();
ZoneVector<MachineType> const* types = MachineTypesOf(input->op());
for (int i = 0; i < input_count; ++i) {
entries += AddOperandToStateValueDescriptor( entries += AddOperandToStateValueDescriptor(
new_desc, inputs, g, deduplicator, edge.to(), new_desc, inputs, g, deduplicator, input->InputAt(i),
MachineType::AnyTagged(), kind, zone); types->at(i), kind, zone);
} }
return entries; return entries;
} else { } else {
...@@ -506,7 +513,6 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, ...@@ -506,7 +513,6 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor,
StateValueDescriptor::Duplicate(zone, id)); StateValueDescriptor::Duplicate(zone, id));
return 0; return 0;
} }
break;
} }
default: { default: {
inputs->push_back(OperandForDeopt(g, input, kind, type.representation())); inputs->push_back(OperandForDeopt(g, input, kind, type.representation()));
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
V(StateValues) \ V(StateValues) \
V(TypedStateValues) \ V(TypedStateValues) \
V(ObjectState) \ V(ObjectState) \
V(TypedObjectState) \
V(Call) \ V(Call) \
V(Parameter) \ V(Parameter) \
V(OsrValue) \ V(OsrValue) \
......
...@@ -1012,6 +1012,36 @@ class RepresentationSelector { ...@@ -1012,6 +1012,36 @@ class RepresentationSelector {
SetOutput(node, MachineRepresentation::kTagged); SetOutput(node, MachineRepresentation::kTagged);
} }
void VisitObjectState(Node* node) {
if (propagate()) {
for (int i = 0; i < node->InputCount(); i++) {
EnqueueInput(node, i, UseInfo::Any());
}
} else if (lower()) {
Zone* zone = jsgraph_->zone();
ZoneVector<MachineType>* types =
new (zone->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(node->InputCount(), zone);
for (int i = 0; i < node->InputCount(); i++) {
Node* input = node->InputAt(i);
NodeInfo* input_info = GetInfo(input);
Type* input_type = TypeOf(input);
MachineRepresentation rep = input_type->IsInhabited()
? input_info->representation()
: MachineRepresentation::kNone;
MachineType machine_type(rep, DeoptValueSemanticOf(input_type));
DCHECK(machine_type.representation() !=
MachineRepresentation::kWord32 ||
machine_type.semantic() == MachineSemantic::kInt32 ||
machine_type.semantic() == MachineSemantic::kUint32);
(*types)[i] = machine_type;
}
NodeProperties::ChangeOp(node,
jsgraph_->common()->TypedObjectState(types));
}
SetOutput(node, MachineRepresentation::kTagged);
}
const Operator* Int32Op(Node* node) { const Operator* Int32Op(Node* node) {
return changer_->Int32OperatorFor(node->opcode()); return changer_->Int32OperatorFor(node->opcode());
} }
...@@ -2456,6 +2486,8 @@ class RepresentationSelector { ...@@ -2456,6 +2486,8 @@ class RepresentationSelector {
return; return;
case IrOpcode::kStateValues: case IrOpcode::kStateValues:
return VisitStateValues(node); return VisitStateValues(node);
case IrOpcode::kObjectState:
return VisitObjectState(node);
case IrOpcode::kTypeGuard: { case IrOpcode::kTypeGuard: {
// We just get rid of the sigma here. In principle, it should be // We just get rid of the sigma here. In principle, it should be
// possible to refine the truncation and representation based on // possible to refine the truncation and representation based on
...@@ -2497,7 +2529,6 @@ class RepresentationSelector { ...@@ -2497,7 +2529,6 @@ class RepresentationSelector {
case IrOpcode::kThrow: case IrOpcode::kThrow:
case IrOpcode::kBeginRegion: case IrOpcode::kBeginRegion:
case IrOpcode::kProjection: case IrOpcode::kProjection:
case IrOpcode::kObjectState:
case IrOpcode::kOsrValue: case IrOpcode::kOsrValue:
// All JavaScript operators except JSToNumber have uniform handling. // All JavaScript operators except JSToNumber have uniform handling.
#define OPCODE_CASE(name) case IrOpcode::k##name: #define OPCODE_CASE(name) case IrOpcode::k##name:
......
...@@ -274,8 +274,7 @@ MachineType StateValuesAccess::iterator::type() { ...@@ -274,8 +274,7 @@ MachineType StateValuesAccess::iterator::type() {
return MachineType::AnyTagged(); return MachineType::AnyTagged();
} else { } else {
DCHECK_EQ(IrOpcode::kTypedStateValues, state->opcode()); DCHECK_EQ(IrOpcode::kTypedStateValues, state->opcode());
const ZoneVector<MachineType>* types = ZoneVector<MachineType> const* types = MachineTypesOf(state->op());
OpParameter<const ZoneVector<MachineType>*>(state);
return (*types)[Top()->index]; return (*types)[Top()->index];
} }
} }
......
...@@ -820,12 +820,15 @@ Type* Typer::Visitor::TypeFrameState(Node* node) { ...@@ -820,12 +820,15 @@ Type* Typer::Visitor::TypeFrameState(Node* node) {
Type* Typer::Visitor::TypeStateValues(Node* node) { return Type::Internal(); } Type* Typer::Visitor::TypeStateValues(Node* node) { return Type::Internal(); }
Type* Typer::Visitor::TypeObjectState(Node* node) { return Type::Internal(); }
Type* Typer::Visitor::TypeTypedStateValues(Node* node) { Type* Typer::Visitor::TypeTypedStateValues(Node* node) {
return Type::Internal(); return Type::Internal();
} }
Type* Typer::Visitor::TypeObjectState(Node* node) { return Type::Internal(); }
Type* Typer::Visitor::TypeTypedObjectState(Node* node) {
return Type::Internal();
}
Type* Typer::Visitor::TypeCall(Node* node) { return Type::Any(); } Type* Typer::Visitor::TypeCall(Node* node) { return Type::Any(); }
......
...@@ -488,8 +488,9 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -488,8 +488,9 @@ void Verifier::Visitor::Check(Node* node) {
break; break;
} }
case IrOpcode::kStateValues: case IrOpcode::kStateValues:
case IrOpcode::kObjectState:
case IrOpcode::kTypedStateValues: case IrOpcode::kTypedStateValues:
case IrOpcode::kObjectState:
case IrOpcode::kTypedObjectState:
// TODO(jarin): what are the constraints on these? // TODO(jarin): what are the constraints on these?
break; break;
case IrOpcode::kCall: case IrOpcode::kCall:
......
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