From a5d251defebb69c4a39634fc8de8a6b074c3daf3 Mon Sep 17 00:00:00 2001 From: bmeurer Date: Tue, 8 Nov 2016 05:44:55 -0800 Subject: [PATCH] [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} --- src/compiler/common-operator.cc | 34 ++++++++++++++++++++-------- src/compiler/common-operator.h | 6 ++++- src/compiler/escape-analysis.cc | 4 ++-- src/compiler/instruction-selector.cc | 14 ++++++++---- src/compiler/opcodes.h | 1 + src/compiler/simplified-lowering.cc | 33 ++++++++++++++++++++++++++- src/compiler/state-values-utils.cc | 3 +-- src/compiler/typer.cc | 7 ++++-- src/compiler/verifier.cc | 3 ++- 9 files changed, 82 insertions(+), 23 deletions(-) diff --git a/src/compiler/common-operator.cc b/src/compiler/common-operator.cc index 12a06530e3..736a961e40 100644 --- a/src/compiler/common-operator.cc +++ b/src/compiler/common-operator.cc @@ -235,6 +235,12 @@ OsrGuardType OsrGuardTypeOf(Operator const* op) { return OpParameter(op); } +ZoneVector const* MachineTypesOf(Operator const* op) { + DCHECK(op->opcode() == IrOpcode::kTypedObjectState || + op->opcode() == IrOpcode::kTypedStateValues); + return OpParameter*>(op); +} + #define CACHED_OP_LIST(V) \ V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1) \ V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1) \ @@ -1004,23 +1010,31 @@ const Operator* CommonOperatorBuilder::StateValues(int arguments) { arguments, 0, 0, 1, 0, 0); // counts } - -const Operator* CommonOperatorBuilder::ObjectState(int pointer_slots, int id) { - return new (zone()) Operator1( // -- - IrOpcode::kObjectState, Operator::kPure, // opcode - "ObjectState", // name - pointer_slots, 0, 0, 1, 0, 0, id); // counts -} - - const Operator* CommonOperatorBuilder::TypedStateValues( const ZoneVector* types) { return new (zone()) Operator1*>( // -- IrOpcode::kTypedStateValues, Operator::kPure, // opcode "TypedStateValues", // name - static_cast(types->size()), 0, 0, 1, 0, 0, types); // counts + static_cast(types->size()), 0, 0, 1, 0, 0, // counts + types); // parameter } +const Operator* CommonOperatorBuilder::ObjectState(int pointer_slots) { + return new (zone()) Operator1( // -- + IrOpcode::kObjectState, Operator::kPure, // opcode + "ObjectState", // name + pointer_slots, 0, 0, 1, 0, 0, // counts + pointer_slots); // parameter +} + +const Operator* CommonOperatorBuilder::TypedObjectState( + const ZoneVector* types) { + return new (zone()) Operator1*>( // -- + IrOpcode::kTypedObjectState, Operator::kPure, // opcode + "TypedObjectState", // name + static_cast(types->size()), 0, 0, 1, 0, 0, // counts + types); // parameter +} const Operator* CommonOperatorBuilder::FrameState( BailoutId bailout_id, OutputFrameStateCombine state_combine, diff --git a/src/compiler/common-operator.h b/src/compiler/common-operator.h index 0fbf0bfda2..96f14f9d82 100644 --- a/src/compiler/common-operator.h +++ b/src/compiler/common-operator.h @@ -181,6 +181,9 @@ size_t hash_value(OsrGuardType type); std::ostream& operator<<(std::ostream&, OsrGuardType); OsrGuardType OsrGuardTypeOf(Operator const*); +ZoneVector const* MachineTypesOf(Operator const*) + WARN_UNUSED_RESULT; + // Interface for building common operators that can be used at any level of IR, // including JavaScript, mid-level, and low-level. class V8_EXPORT_PRIVATE CommonOperatorBuilder final @@ -240,8 +243,9 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final const Operator* BeginRegion(RegionObservability); const Operator* FinishRegion(); const Operator* StateValues(int arguments); - const Operator* ObjectState(int pointer_slots, int id); const Operator* TypedStateValues(const ZoneVector* types); + const Operator* ObjectState(int pointer_slots); + const Operator* TypedObjectState(const ZoneVector* types); const Operator* FrameState(BailoutId bailout_id, OutputFrameStateCombine state_combine, const FrameStateFunctionInfo* function_info); diff --git a/src/compiler/escape-analysis.cc b/src/compiler/escape-analysis.cc index 7ce5e37e8c..f75a83b975 100644 --- a/src/compiler/escape-analysis.cc +++ b/src/compiler/escape-analysis.cc @@ -1578,8 +1578,8 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { } int input_count = static_cast(cache_->fields().size()); Node* new_object_state = - graph()->NewNode(common()->ObjectState(input_count, vobj->id()), - input_count, &cache_->fields().front()); + graph()->NewNode(common()->ObjectState(input_count), input_count, + &cache_->fields().front()); vobj->SetObjectState(new_object_state); TRACE( "Creating object state #%d for vobj %p (from node #%d) at effect " diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index 1889b6917f..2b48f7ded1 100644 --- a/src/compiler/instruction-selector.cc +++ b/src/compiler/instruction-selector.cc @@ -434,6 +434,7 @@ InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, case IrOpcode::kHeapConstant: return g->UseImmediate(input); case IrOpcode::kObjectState: + case IrOpcode::kTypedObjectState: UNREACHABLE(); break; default: @@ -485,6 +486,10 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, FrameStateInputKind kind, Zone* zone) { switch (input->opcode()) { case IrOpcode::kObjectState: { + UNREACHABLE(); + return 0; + } + case IrOpcode::kTypedObjectState: { size_t id = deduplicator->GetObjectId(input); if (id == StateObjectDeduplicator::kNotDuplicated) { size_t entries = 0; @@ -492,10 +497,12 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, descriptor->fields().push_back( StateValueDescriptor::Recursive(zone, id)); StateValueDescriptor* new_desc = &descriptor->fields().back(); - for (Edge edge : input->input_edges()) { + int const input_count = input->op()->ValueInputCount(); + ZoneVector const* types = MachineTypesOf(input->op()); + for (int i = 0; i < input_count; ++i) { entries += AddOperandToStateValueDescriptor( - new_desc, inputs, g, deduplicator, edge.to(), - MachineType::AnyTagged(), kind, zone); + new_desc, inputs, g, deduplicator, input->InputAt(i), + types->at(i), kind, zone); } return entries; } else { @@ -506,7 +513,6 @@ size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor, StateValueDescriptor::Duplicate(zone, id)); return 0; } - break; } default: { inputs->push_back(OperandForDeopt(g, input, kind, type.representation())); diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index 8c9a11aa96..967bfb9d01 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -57,6 +57,7 @@ V(StateValues) \ V(TypedStateValues) \ V(ObjectState) \ + V(TypedObjectState) \ V(Call) \ V(Parameter) \ V(OsrValue) \ diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index 3430db1b12..9555a3fe00 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -1012,6 +1012,36 @@ class RepresentationSelector { 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* types = + new (zone->New(sizeof(ZoneVector))) + ZoneVector(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) { return changer_->Int32OperatorFor(node->opcode()); } @@ -2456,6 +2486,8 @@ class RepresentationSelector { return; case IrOpcode::kStateValues: return VisitStateValues(node); + case IrOpcode::kObjectState: + return VisitObjectState(node); case IrOpcode::kTypeGuard: { // We just get rid of the sigma here. In principle, it should be // possible to refine the truncation and representation based on @@ -2497,7 +2529,6 @@ class RepresentationSelector { case IrOpcode::kThrow: case IrOpcode::kBeginRegion: case IrOpcode::kProjection: - case IrOpcode::kObjectState: case IrOpcode::kOsrValue: // All JavaScript operators except JSToNumber have uniform handling. #define OPCODE_CASE(name) case IrOpcode::k##name: diff --git a/src/compiler/state-values-utils.cc b/src/compiler/state-values-utils.cc index 77cc227038..e8310d7d56 100644 --- a/src/compiler/state-values-utils.cc +++ b/src/compiler/state-values-utils.cc @@ -274,8 +274,7 @@ MachineType StateValuesAccess::iterator::type() { return MachineType::AnyTagged(); } else { DCHECK_EQ(IrOpcode::kTypedStateValues, state->opcode()); - const ZoneVector* types = - OpParameter*>(state); + ZoneVector const* types = MachineTypesOf(state->op()); return (*types)[Top()->index]; } } diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 2f508d336e..7c2565cc42 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -820,12 +820,15 @@ Type* Typer::Visitor::TypeFrameState(Node* node) { Type* Typer::Visitor::TypeStateValues(Node* node) { return Type::Internal(); } -Type* Typer::Visitor::TypeObjectState(Node* node) { return Type::Internal(); } - Type* Typer::Visitor::TypeTypedStateValues(Node* node) { 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(); } diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index 31153c6ef2..6552654cf3 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -488,8 +488,9 @@ void Verifier::Visitor::Check(Node* node) { break; } case IrOpcode::kStateValues: - case IrOpcode::kObjectState: case IrOpcode::kTypedStateValues: + case IrOpcode::kObjectState: + case IrOpcode::kTypedObjectState: // TODO(jarin): what are the constraints on these? break; case IrOpcode::kCall: