[turbofan] Fully brokerize JSCallReducer
ReduceTypedArrayPrototypeToStringTag, ReduceObjectGetPrototype and ReduceObjectGetPrototype are now heap-access free. Bug: v8:7790 Change-Id: If7f7ae4c7712326240aa50e02189fee94a57afa9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1762022 Commit-Queue: Maya Lekova <mslekova@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#63291}
This commit is contained in:
parent
ed50ab6529
commit
14cb014726
@ -180,6 +180,8 @@ Reduction JSCallReducer::ReduceMathMinMax(Node* node, const Operator* op,
|
||||
}
|
||||
|
||||
Reduction JSCallReducer::Reduce(Node* node) {
|
||||
DisallowHeapAccessIf disallow_heap_access(FLAG_concurrent_inlining);
|
||||
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kJSConstruct:
|
||||
return ReduceJSConstruct(node);
|
||||
@ -616,13 +618,19 @@ Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) {
|
||||
MapHandles const& object_maps = inference.GetMaps();
|
||||
|
||||
MapRef candidate_map(broker(), object_maps[0]);
|
||||
candidate_map.SerializePrototype();
|
||||
if (FLAG_concurrent_inlining && !candidate_map.serialized_prototype()) {
|
||||
TRACE_BROKER_MISSING(broker(), "prototype for map " << candidate_map);
|
||||
return inference.NoChange();
|
||||
}
|
||||
ObjectRef candidate_prototype = candidate_map.prototype();
|
||||
|
||||
// Check if we can constant-fold the {candidate_prototype}.
|
||||
for (size_t i = 0; i < object_maps.size(); ++i) {
|
||||
MapRef object_map(broker(), object_maps[i]);
|
||||
object_map.SerializePrototype();
|
||||
if (FLAG_concurrent_inlining && !object_map.serialized_prototype()) {
|
||||
TRACE_BROKER_MISSING(broker(), "prototype for map " << object_map);
|
||||
return inference.NoChange();
|
||||
}
|
||||
if (IsSpecialReceiverInstanceType(object_map.instance_type()) ||
|
||||
!object_map.prototype().equals(candidate_prototype)) {
|
||||
// We exclude special receivers, like JSProxy or API objects that
|
||||
@ -3228,10 +3236,6 @@ bool ShouldUseCallICFeedback(Node* node) {
|
||||
} // namespace
|
||||
|
||||
Reduction JSCallReducer::ReduceJSCall(Node* node) {
|
||||
// TODO(mslekova): Remove once ReduceJSCall is brokerized.
|
||||
AllowHandleDereference allow_handle_dereference;
|
||||
AllowHandleAllocation allow_handle_allocation;
|
||||
|
||||
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
|
||||
CallParameters const& p = CallParametersOf(node->op());
|
||||
Node* target = NodeProperties::GetValueInput(node, 0);
|
||||
@ -3725,17 +3729,13 @@ Reduction JSCallReducer::ReduceJSCall(Node* node,
|
||||
break;
|
||||
}
|
||||
|
||||
if (shared.object()->IsApiFunction()) {
|
||||
if (shared.function_template_info().has_value()) {
|
||||
return ReduceCallApiFunction(node, shared);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction JSCallReducer::ReduceJSCallWithArrayLike(Node* node) {
|
||||
// TODO(mslekova): Remove once ReduceJSCallWithArrayLike is brokerized.
|
||||
AllowHandleDereference allow_handle_dereference;
|
||||
AllowHandleAllocation allow_handle_allocation;
|
||||
|
||||
DCHECK_EQ(IrOpcode::kJSCallWithArrayLike, node->opcode());
|
||||
CallFrequency frequency = CallFrequencyOf(node->op());
|
||||
VectorSlotPair feedback;
|
||||
@ -3755,10 +3755,6 @@ Reduction JSCallReducer::ReduceJSCallWithSpread(Node* node) {
|
||||
}
|
||||
|
||||
Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
|
||||
// TODO(mslekova): Remove once ReduceJSConstruct is brokerized.
|
||||
AllowHandleDereference allow_handle_dereference;
|
||||
AllowHandleAllocation allow_handle_allocation;
|
||||
|
||||
DCHECK_EQ(IrOpcode::kJSConstruct, node->opcode());
|
||||
ConstructParameters const& p = ConstructParametersOf(node->op());
|
||||
DCHECK_LE(2u, p.arity());
|
||||
@ -6260,8 +6256,13 @@ Reduction JSCallReducer::ReduceTypedArrayPrototypeToStringTag(Node* node) {
|
||||
jsgraph()->Constant(TYPE##_ELEMENTS - \
|
||||
FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)); \
|
||||
control = graph()->NewNode(common()->Branch(), check, control); \
|
||||
if (FLAG_concurrent_inlining) { \
|
||||
values.push_back(jsgraph()->Constant( \
|
||||
broker()->GetTypedArrayStringTag(TYPE##_ELEMENTS))); \
|
||||
} else { \
|
||||
values.push_back(jsgraph()->HeapConstant( \
|
||||
factory()->InternalizeUtf8String(#Type "Array"))); \
|
||||
} \
|
||||
effects.push_back(effect); \
|
||||
controls.push_back(graph()->NewNode(common()->IfTrue(), control)); \
|
||||
control = graph()->NewNode(common()->IfFalse(), control); \
|
||||
@ -6503,9 +6504,10 @@ Reduction JSCallReducer::ReduceCollectionIteratorPrototypeNext(
|
||||
MapInference inference(broker(), receiver, effect);
|
||||
if (!inference.HaveMaps()) return NoChange();
|
||||
MapHandles const& receiver_maps = inference.GetMaps();
|
||||
receiver_instance_type = receiver_maps[0]->instance_type();
|
||||
receiver_instance_type = MapRef(broker(), receiver_maps[0]).instance_type();
|
||||
for (size_t i = 1; i < receiver_maps.size(); ++i) {
|
||||
if (receiver_maps[i]->instance_type() != receiver_instance_type) {
|
||||
if (MapRef(broker(), receiver_maps[i]).instance_type() !=
|
||||
receiver_instance_type) {
|
||||
return inference.NoChange();
|
||||
}
|
||||
}
|
||||
|
@ -2218,7 +2218,8 @@ JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone,
|
||||
ais_for_loading_exec_(zone()),
|
||||
ais_for_loading_has_instance_(zone()),
|
||||
ais_for_loading_then_(zone()),
|
||||
property_access_infos_(zone()) {
|
||||
property_access_infos_(zone()),
|
||||
typed_array_string_tags_(zone()) {
|
||||
// Note that this initialization of the refs_ pointer with the minimal
|
||||
// initial capacity is redundant in the normal use case (concurrent
|
||||
// compilation enabled, standard objects to be serialized), as the map
|
||||
@ -2348,6 +2349,25 @@ void JSHeapBroker::CollectArrayAndObjectPrototypes() {
|
||||
CHECK(!array_and_object_prototypes_.empty());
|
||||
}
|
||||
|
||||
void JSHeapBroker::SerializeTypedArrayStringTags() {
|
||||
#define TYPED_ARRAY_STRING_TAG(Type, type, TYPE, ctype) \
|
||||
do { \
|
||||
ObjectData* data = GetOrCreateData( \
|
||||
isolate()->factory()->InternalizeUtf8String(#Type "Array")); \
|
||||
typed_array_string_tags_.push_back(data); \
|
||||
} while (false);
|
||||
|
||||
TYPED_ARRAYS(TYPED_ARRAY_STRING_TAG)
|
||||
#undef TYPED_ARRAY_STRING_TAG
|
||||
}
|
||||
|
||||
StringRef JSHeapBroker::GetTypedArrayStringTag(ElementsKind kind) {
|
||||
DCHECK(IsTypedArrayElementsKind(kind));
|
||||
size_t idx = kind - FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
|
||||
CHECK_LT(idx, typed_array_string_tags_.size());
|
||||
return StringRef(this, typed_array_string_tags_[idx]);
|
||||
}
|
||||
|
||||
bool JSHeapBroker::IsArrayOrObjectPrototype(const JSObjectRef& object) const {
|
||||
if (mode() == kDisabled) {
|
||||
return isolate()->IsInAnyContext(*object.object(),
|
||||
@ -2369,6 +2389,7 @@ void JSHeapBroker::SerializeStandardObjects() {
|
||||
TraceScope tracer(this, "JSHeapBroker::SerializeStandardObjects");
|
||||
|
||||
CollectArrayAndObjectPrototypes();
|
||||
SerializeTypedArrayStringTags();
|
||||
|
||||
SetNativeContextRef();
|
||||
native_context().Serialize();
|
||||
@ -3269,7 +3290,7 @@ base::Optional<MapRef> MapRef::FindRootMap() const {
|
||||
if (map_data) {
|
||||
return MapRef(broker(), map_data);
|
||||
}
|
||||
TRACE_BROKER_MISSING(broker(), "root map for object " << object());
|
||||
TRACE_BROKER_MISSING(broker(), "root map for object " << *this);
|
||||
return base::nullopt;
|
||||
}
|
||||
|
||||
@ -3820,9 +3841,12 @@ void SharedFunctionInfoRef::SerializeFunctionTemplateInfo() {
|
||||
base::Optional<FunctionTemplateInfoRef>
|
||||
SharedFunctionInfoRef::function_template_info() const {
|
||||
if (broker()->mode() == JSHeapBroker::kDisabled) {
|
||||
if (object()->IsApiFunction()) {
|
||||
return FunctionTemplateInfoRef(
|
||||
broker(), handle(object()->function_data(), broker()->isolate()));
|
||||
}
|
||||
return base::nullopt;
|
||||
}
|
||||
FunctionTemplateInfoData* function_template_info =
|
||||
data()->AsSharedFunctionInfo()->function_template_info();
|
||||
if (!function_template_info) return base::nullopt;
|
||||
|
@ -185,6 +185,8 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
|
||||
CompilationDependencies* dependencies,
|
||||
SerializationPolicy policy = SerializationPolicy::kAssumeSerialized);
|
||||
|
||||
StringRef GetTypedArrayStringTag(ElementsKind kind);
|
||||
|
||||
std::ostream& Trace();
|
||||
void IncrementTracingIndentation();
|
||||
void DecrementTracingIndentation();
|
||||
@ -213,6 +215,7 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
|
||||
|
||||
void SerializeShareableObjects();
|
||||
void CollectArrayAndObjectPrototypes();
|
||||
void SerializeTypedArrayStringTags();
|
||||
|
||||
Isolate* const isolate_;
|
||||
Zone* const broker_zone_;
|
||||
@ -244,6 +247,8 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
|
||||
PropertyAccessTarget::Hash, PropertyAccessTarget::Equal>
|
||||
property_access_infos_;
|
||||
|
||||
ZoneVector<ObjectData*> typed_array_string_tags_;
|
||||
|
||||
static const size_t kMinimalRefsBucketCount = 8; // must be power of 2
|
||||
static const size_t kInitialRefsBucketCount = 1024; // must be power of 2
|
||||
};
|
||||
|
@ -409,6 +409,7 @@ class SerializerForBackgroundCompilation {
|
||||
PropertyAccessInfo ProcessMapForRegExpTest(MapRef map);
|
||||
void ProcessHintsForFunctionCall(Hints const& target_hints);
|
||||
void ProcessHintsForFunctionBind(Hints const& receiver_hints);
|
||||
void ProcessHintsForObjectGetPrototype(Hints const& object_hints);
|
||||
void ProcessConstantForOrdinaryHasInstance(HeapObjectRef const& constructor,
|
||||
bool* walk_prototypes);
|
||||
void ProcessConstantForInstanceOf(ObjectRef const& constant,
|
||||
@ -1853,6 +1854,21 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
||||
ProcessHintsForFunctionBind(arguments[0]);
|
||||
}
|
||||
break;
|
||||
case Builtins::kObjectGetPrototypeOf:
|
||||
case Builtins::kReflectGetPrototypeOf:
|
||||
if (arguments.size() >= 2) {
|
||||
ProcessHintsForObjectGetPrototype(arguments[1]);
|
||||
} else {
|
||||
Hints undefined_hint = Hints::SingleConstant(
|
||||
broker()->isolate()->factory()->undefined_value(), zone());
|
||||
ProcessHintsForObjectGetPrototype(undefined_hint);
|
||||
}
|
||||
break;
|
||||
case Builtins::kObjectPrototypeGetProto:
|
||||
if (arguments.size() >= 1) {
|
||||
ProcessHintsForObjectGetPrototype(arguments[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2002,6 +2018,20 @@ void SerializerForBackgroundCompilation::ProcessHintsForFunctionBind(
|
||||
}
|
||||
}
|
||||
|
||||
void SerializerForBackgroundCompilation::ProcessHintsForObjectGetPrototype(
|
||||
Hints const& object_hints) {
|
||||
for (auto constant : object_hints.constants()) {
|
||||
if (!constant->IsHeapObject()) continue;
|
||||
HeapObjectRef object(broker(), constant);
|
||||
object.map().SerializePrototype();
|
||||
}
|
||||
|
||||
for (auto map : object_hints.maps()) {
|
||||
MapRef map_ref(broker(), map);
|
||||
map_ref.SerializePrototype();
|
||||
}
|
||||
}
|
||||
|
||||
void SerializerForBackgroundCompilation::ContributeToJumpTargetEnvironment(
|
||||
int target_offset) {
|
||||
auto it = jump_target_environments_.find(target_offset);
|
||||
|
Loading…
Reference in New Issue
Block a user