[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:
Benedikt Meurer 2019-05-15 09:36:26 +02:00 committed by Commit Bot
parent 099669ecf3
commit c7ca8dacd2
5 changed files with 21 additions and 83 deletions

View File

@ -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());

View File

@ -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) {

View File

@ -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,

View File

@ -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);

View File

@ -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