[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}
This commit is contained in:
parent
e4bae13309
commit
a5d251defe
@ -235,6 +235,12 @@ OsrGuardType OsrGuardTypeOf(Operator const* 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) \
|
||||
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<int>( // --
|
||||
IrOpcode::kObjectState, Operator::kPure, // opcode
|
||||
"ObjectState", // name
|
||||
pointer_slots, 0, 0, 1, 0, 0, id); // 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, types); // counts
|
||||
static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts
|
||||
types); // parameter
|
||||
}
|
||||
|
||||
const Operator* CommonOperatorBuilder::ObjectState(int pointer_slots) {
|
||||
return new (zone()) Operator1<int>( // --
|
||||
IrOpcode::kObjectState, Operator::kPure, // opcode
|
||||
"ObjectState", // name
|
||||
pointer_slots, 0, 0, 1, 0, 0, // counts
|
||||
pointer_slots); // parameter
|
||||
}
|
||||
|
||||
const Operator* CommonOperatorBuilder::TypedObjectState(
|
||||
const ZoneVector<MachineType>* types) {
|
||||
return new (zone()) Operator1<const ZoneVector<MachineType>*>( // --
|
||||
IrOpcode::kTypedObjectState, Operator::kPure, // opcode
|
||||
"TypedObjectState", // name
|
||||
static_cast<int>(types->size()), 0, 0, 1, 0, 0, // counts
|
||||
types); // parameter
|
||||
}
|
||||
|
||||
const Operator* CommonOperatorBuilder::FrameState(
|
||||
BailoutId bailout_id, OutputFrameStateCombine state_combine,
|
||||
|
@ -181,6 +181,9 @@ size_t hash_value(OsrGuardType type);
|
||||
std::ostream& operator<<(std::ostream&, OsrGuardType);
|
||||
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,
|
||||
// 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<MachineType>* types);
|
||||
const Operator* ObjectState(int pointer_slots);
|
||||
const Operator* TypedObjectState(const ZoneVector<MachineType>* types);
|
||||
const Operator* FrameState(BailoutId bailout_id,
|
||||
OutputFrameStateCombine state_combine,
|
||||
const FrameStateFunctionInfo* function_info);
|
||||
|
@ -1578,8 +1578,8 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
|
||||
}
|
||||
int input_count = static_cast<int>(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 "
|
||||
|
@ -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<MachineType> 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()));
|
||||
|
@ -57,6 +57,7 @@
|
||||
V(StateValues) \
|
||||
V(TypedStateValues) \
|
||||
V(ObjectState) \
|
||||
V(TypedObjectState) \
|
||||
V(Call) \
|
||||
V(Parameter) \
|
||||
V(OsrValue) \
|
||||
|
@ -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<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) {
|
||||
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:
|
||||
|
@ -274,8 +274,7 @@ MachineType StateValuesAccess::iterator::type() {
|
||||
return MachineType::AnyTagged();
|
||||
} else {
|
||||
DCHECK_EQ(IrOpcode::kTypedStateValues, state->opcode());
|
||||
const ZoneVector<MachineType>* types =
|
||||
OpParameter<const ZoneVector<MachineType>*>(state);
|
||||
ZoneVector<MachineType> const* types = MachineTypesOf(state->op());
|
||||
return (*types)[Top()->index];
|
||||
}
|
||||
}
|
||||
|
@ -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(); }
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user