[turbofan] Use CheckHeapObject only for StoreField.
Previously we had to use CheckHeapObject in front of every CheckMaps, CompareMaps and TransitionElementsKind operation. Now these operators request HeapObject representation themselves (requiring for CompareMaps and TransitionElementsKind to remove the kNoDeopt property). This means we only do CheckHeapObject for StoreField to a field that has HeapObject representation. This not only leads to smaller graphs in the compiler, but also removes most uses of the CheckHeapObject operator, which doesn't express a real semantic property in the compiler frontend. Bug: v8:9183, v8:9250 Refs: nodejs/node#27667 Change-Id: Ie3d83de69583b1bed6c1c53444bfc97aaef624bb Cq-Include-Trybots: luci.chromium.try:linux-rel,win7-rel Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1612902 Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#61508}
This commit is contained in:
parent
099669ecf3
commit
c7ca8dacd2
@ -432,8 +432,6 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
|
||||
kStartAtPrototype);
|
||||
|
||||
// Monomorphic property access.
|
||||
constructor =
|
||||
access_builder.BuildCheckHeapObject(constructor, &effect, control);
|
||||
access_builder.BuildCheckMaps(constructor, &effect, control,
|
||||
access_info.receiver_maps());
|
||||
|
||||
@ -1124,8 +1122,6 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
effect =
|
||||
graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
|
||||
} else {
|
||||
receiver =
|
||||
access_builder.BuildCheckHeapObject(receiver, &effect, control);
|
||||
access_builder.BuildCheckMaps(receiver, &effect, control,
|
||||
access_info.receiver_maps());
|
||||
}
|
||||
@ -1154,7 +1150,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that {receiver} is a heap object.
|
||||
// Handle the case that {receiver} may be a number.
|
||||
Node* receiverissmi_control = nullptr;
|
||||
Node* receiverissmi_effect = effect;
|
||||
if (receiverissmi_possible) {
|
||||
@ -1163,9 +1159,6 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
control = graph()->NewNode(common()->IfFalse(), branch);
|
||||
receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
|
||||
receiverissmi_effect = effect;
|
||||
} else {
|
||||
receiver =
|
||||
access_builder.BuildCheckHeapObject(receiver, &effect, control);
|
||||
}
|
||||
|
||||
// Generate code for the various different property access patterns.
|
||||
@ -1547,10 +1540,6 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that {receiver} is a heap object.
|
||||
PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
|
||||
receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
|
||||
|
||||
// Check if we have the necessary data for building element accesses.
|
||||
for (ElementAccessInfo const& access_info : access_infos) {
|
||||
if (!IsFixedTypedArrayElementsKind(access_info.elements_kind())) continue;
|
||||
@ -1567,6 +1556,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
|
||||
}
|
||||
|
||||
// Check for the monomorphic case.
|
||||
PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
|
||||
if (access_infos.size() == 1) {
|
||||
ElementAccessInfo access_info = access_infos.front();
|
||||
|
||||
@ -1915,8 +1905,6 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
effect =
|
||||
graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
|
||||
} else {
|
||||
receiver =
|
||||
access_builder.BuildCheckHeapObject(receiver, &effect, control);
|
||||
access_builder.BuildCheckMaps(receiver, &effect, control,
|
||||
access_info.receiver_maps());
|
||||
}
|
||||
@ -1945,7 +1933,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that {receiver} is a heap object.
|
||||
// Handle the case that {receiver} may be a number.
|
||||
Node* receiverissmi_control = nullptr;
|
||||
Node* receiverissmi_effect = effect;
|
||||
if (receiverissmi_possible) {
|
||||
@ -1954,9 +1942,6 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
control = graph()->NewNode(common()->IfFalse(), branch);
|
||||
receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
|
||||
receiverissmi_effect = effect;
|
||||
} else {
|
||||
receiver =
|
||||
access_builder.BuildCheckHeapObject(receiver, &effect, control);
|
||||
}
|
||||
|
||||
// Generate code for the various different property access patterns.
|
||||
@ -2602,8 +2587,6 @@ JSNativeContextSpecialization::BuildPropertyStore(
|
||||
MachineRepresentation::kTaggedPointer ||
|
||||
field_representation ==
|
||||
MachineRepresentation::kCompressedPointer) {
|
||||
// Ensure that {value} is a HeapObject.
|
||||
value = access_builder.BuildCheckHeapObject(value, &effect, control);
|
||||
Handle<Map> field_map;
|
||||
if (access_info.field_map().ToHandle(&field_map)) {
|
||||
// Emit a map check for the value.
|
||||
@ -2611,6 +2594,10 @@ JSNativeContextSpecialization::BuildPropertyStore(
|
||||
simplified()->CheckMaps(CheckMapsFlag::kNone,
|
||||
ZoneHandleSet<Map>(field_map)),
|
||||
value, effect, control);
|
||||
} else {
|
||||
// Ensure that {value} is a HeapObject.
|
||||
value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
|
||||
value, effect, control);
|
||||
}
|
||||
field_access.write_barrier_kind = kPointerWriteBarrier;
|
||||
|
||||
@ -2721,7 +2708,6 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
|
||||
|
||||
// Monomorphic property access.
|
||||
PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
|
||||
receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
|
||||
access_builder.BuildCheckMaps(receiver, &effect, control,
|
||||
access_info.receiver_maps());
|
||||
|
||||
|
@ -81,60 +81,6 @@ bool PropertyAccessBuilder::TryBuildNumberCheck(
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool NeedsCheckHeapObject(Node* receiver) {
|
||||
switch (receiver->opcode()) {
|
||||
case IrOpcode::kConvertReceiver:
|
||||
case IrOpcode::kHeapConstant:
|
||||
case IrOpcode::kJSCloneObject:
|
||||
case IrOpcode::kJSConstruct:
|
||||
case IrOpcode::kJSConstructForwardVarargs:
|
||||
case IrOpcode::kJSConstructWithArrayLike:
|
||||
case IrOpcode::kJSConstructWithSpread:
|
||||
case IrOpcode::kJSCreate:
|
||||
case IrOpcode::kJSCreateArguments:
|
||||
case IrOpcode::kJSCreateArray:
|
||||
case IrOpcode::kJSCreateArrayFromIterable:
|
||||
case IrOpcode::kJSCreateArrayIterator:
|
||||
case IrOpcode::kJSCreateAsyncFunctionObject:
|
||||
case IrOpcode::kJSCreateBoundFunction:
|
||||
case IrOpcode::kJSCreateClosure:
|
||||
case IrOpcode::kJSCreateCollectionIterator:
|
||||
case IrOpcode::kJSCreateEmptyLiteralArray:
|
||||
case IrOpcode::kJSCreateEmptyLiteralObject:
|
||||
case IrOpcode::kJSCreateGeneratorObject:
|
||||
case IrOpcode::kJSCreateIterResultObject:
|
||||
case IrOpcode::kJSCreateKeyValueArray:
|
||||
case IrOpcode::kJSCreateLiteralArray:
|
||||
case IrOpcode::kJSCreateLiteralObject:
|
||||
case IrOpcode::kJSCreateLiteralRegExp:
|
||||
case IrOpcode::kJSCreateObject:
|
||||
case IrOpcode::kJSCreatePromise:
|
||||
case IrOpcode::kJSCreateStringIterator:
|
||||
case IrOpcode::kJSCreateTypedArray:
|
||||
case IrOpcode::kJSGetSuperConstructor:
|
||||
case IrOpcode::kJSToName:
|
||||
case IrOpcode::kJSToObject:
|
||||
case IrOpcode::kJSToString:
|
||||
case IrOpcode::kTypeOf:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Node* PropertyAccessBuilder::BuildCheckHeapObject(Node* receiver, Node** effect,
|
||||
Node* control) {
|
||||
if (NeedsCheckHeapObject(receiver)) {
|
||||
receiver = *effect = graph()->NewNode(simplified()->CheckHeapObject(),
|
||||
receiver, *effect, control);
|
||||
}
|
||||
return receiver;
|
||||
}
|
||||
|
||||
void PropertyAccessBuilder::BuildCheckMaps(
|
||||
Node* receiver, Node** effect, Node* control,
|
||||
ZoneVector<Handle<Map>> const& receiver_maps) {
|
||||
|
@ -41,7 +41,6 @@ class PropertyAccessBuilder {
|
||||
ZoneVector<Handle<Map>> const& maps, Node** receiver,
|
||||
Node** effect, Node* control);
|
||||
|
||||
Node* BuildCheckHeapObject(Node* receiver, Node** effect, Node* control);
|
||||
void BuildCheckMaps(Node* receiver, Node** effect, Node* control,
|
||||
ZoneVector<Handle<Map>> const& receiver_maps);
|
||||
Node* BuildCheckValue(Node* receiver, Node** effect, Node* control,
|
||||
|
@ -3281,14 +3281,21 @@ class RepresentationSelector {
|
||||
case IrOpcode::kMapGuard:
|
||||
// Eliminate MapGuard nodes here.
|
||||
return VisitUnused(node);
|
||||
case IrOpcode::kCheckMaps:
|
||||
case IrOpcode::kCheckMaps: {
|
||||
CheckMapsParameters const& p = CheckMapsParametersOf(node->op());
|
||||
return VisitUnop(
|
||||
node, UseInfo::CheckedHeapObjectAsTaggedPointer(p.feedback()),
|
||||
MachineRepresentation::kNone);
|
||||
}
|
||||
case IrOpcode::kTransitionElementsKind: {
|
||||
VisitInputs(node);
|
||||
return SetOutput(node, MachineRepresentation::kNone);
|
||||
return VisitUnop(
|
||||
node, UseInfo::CheckedHeapObjectAsTaggedPointer(VectorSlotPair()),
|
||||
MachineRepresentation::kNone);
|
||||
}
|
||||
case IrOpcode::kCompareMaps:
|
||||
return VisitUnop(node, UseInfo::AnyTagged(),
|
||||
MachineRepresentation::kBit);
|
||||
return VisitUnop(
|
||||
node, UseInfo::CheckedHeapObjectAsTaggedPointer(VectorSlotPair()),
|
||||
MachineRepresentation::kBit);
|
||||
case IrOpcode::kEnsureWritableFastElements:
|
||||
return VisitBinop(node, UseInfo::AnyTagged(),
|
||||
MachineRepresentation::kTaggedPointer);
|
||||
|
@ -1377,7 +1377,7 @@ const Operator* SimplifiedOperatorBuilder::CompareMaps(
|
||||
DCHECK_LT(0, maps.size());
|
||||
return new (zone()) Operator1<ZoneHandleSet<Map>>( // --
|
||||
IrOpcode::kCompareMaps, // opcode
|
||||
Operator::kEliminatable, // flags
|
||||
Operator::kNoThrow | Operator::kNoWrite, // flags
|
||||
"CompareMaps", // name
|
||||
1, 1, 1, 1, 1, 0, // counts
|
||||
maps); // parameter
|
||||
@ -1462,7 +1462,7 @@ const Operator* SimplifiedOperatorBuilder::TransitionElementsKind(
|
||||
ElementsTransition transition) {
|
||||
return new (zone()) Operator1<ElementsTransition>( // --
|
||||
IrOpcode::kTransitionElementsKind, // opcode
|
||||
Operator::kNoDeopt | Operator::kNoThrow, // flags
|
||||
Operator::kNoThrow, // flags
|
||||
"TransitionElementsKind", // name
|
||||
1, 1, 1, 0, 1, 0, // counts
|
||||
transition); // parameter
|
||||
|
Loading…
Reference in New Issue
Block a user