[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:
Maya Lekova 2019-08-20 17:29:02 +02:00 committed by Commit Bot
parent ed50ab6529
commit 14cb014726
4 changed files with 84 additions and 23 deletions

View File

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

View File

@ -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,8 +3841,11 @@ void SharedFunctionInfoRef::SerializeFunctionTemplateInfo() {
base::Optional<FunctionTemplateInfoRef>
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();

View File

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

View File

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