From 14cb014726ec454199fc783b9f990b46bde054d6 Mon Sep 17 00:00:00 2001 From: Maya Lekova Date: Tue, 20 Aug 2019 17:29:02 +0200 Subject: [PATCH] [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 Reviewed-by: Georg Neis Cr-Commit-Position: refs/heads/master@{#63291} --- src/compiler/js-call-reducer.cc | 40 ++++++++++--------- src/compiler/js-heap-broker.cc | 32 +++++++++++++-- src/compiler/js-heap-broker.h | 5 +++ .../serializer-for-background-compilation.cc | 30 ++++++++++++++ 4 files changed, 84 insertions(+), 23 deletions(-) diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc index 3df47929dc..0b2113c6ae 100644 --- a/src/compiler/js-call-reducer.cc +++ b/src/compiler/js-call-reducer.cc @@ -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); \ - values.push_back(jsgraph()->HeapConstant( \ - factory()->InternalizeUtf8String(#Type "Array"))); \ + 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(); } } diff --git a/src/compiler/js-heap-broker.cc b/src/compiler/js-heap-broker.cc index 00bfbbb7d4..ddbfdef600 100644 --- a/src/compiler/js-heap-broker.cc +++ b/src/compiler/js-heap-broker.cc @@ -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::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,8 +3841,11 @@ void SharedFunctionInfoRef::SerializeFunctionTemplateInfo() { base::Optional SharedFunctionInfoRef::function_template_info() const { if (broker()->mode() == JSHeapBroker::kDisabled) { - return FunctionTemplateInfoRef( - broker(), handle(object()->function_data(), broker()->isolate())); + if (object()->IsApiFunction()) { + return FunctionTemplateInfoRef( + broker(), handle(object()->function_data(), broker()->isolate())); + } + return base::nullopt; } FunctionTemplateInfoData* function_template_info = data()->AsSharedFunctionInfo()->function_template_info(); diff --git a/src/compiler/js-heap-broker.h b/src/compiler/js-heap-broker.h index 2463a86a50..3a3e0212a8 100644 --- a/src/compiler/js-heap-broker.h +++ b/src/compiler/js-heap-broker.h @@ -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 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 }; diff --git a/src/compiler/serializer-for-background-compilation.cc b/src/compiler/serializer-for-background-compilation.cc index 4dd86f321e..aba750e9bb 100644 --- a/src/compiler/serializer-for-background-compilation.cc +++ b/src/compiler/serializer-for-background-compilation.cc @@ -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);