[turbofan] Be smarter when serializing function calls
Recursively serialize arguments to higher-order functions if appropriate. This should recover all or most of the Deltablue regression with --concurrent-inlining. It is also a prerequisite to allowing speculation in the call reducer for these situations. Bug: v8:7790, v8:9702 Change-Id: I1ac8ac8b8e4dc0f2e19c89aacfb45d18f2df190f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1835541 Commit-Queue: Georg Neis <neis@chromium.org> Reviewed-by: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Cr-Commit-Position: refs/heads/master@{#64108}
This commit is contained in:
parent
da8bc4a0a8
commit
1200f3c95b
@ -324,6 +324,8 @@ class Hints {
|
|||||||
|
|
||||||
using HintsVector = ZoneVector<Hints>;
|
using HintsVector = ZoneVector<Hints>;
|
||||||
|
|
||||||
|
// A FunctionBlueprint is a SharedFunctionInfo and a FeedbackVector, plus
|
||||||
|
// Hints about the context in which a closure will be created from them.
|
||||||
class FunctionBlueprint {
|
class FunctionBlueprint {
|
||||||
public:
|
public:
|
||||||
FunctionBlueprint(Handle<JSFunction> function, Isolate* isolate, Zone* zone);
|
FunctionBlueprint(Handle<JSFunction> function, Isolate* isolate, Zone* zone);
|
||||||
@ -350,6 +352,8 @@ class FunctionBlueprint {
|
|||||||
Hints context_hints_;
|
Hints context_hints_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A CompilationSubject is a FunctionBlueprint, optionally with a matching
|
||||||
|
// closure.
|
||||||
class CompilationSubject {
|
class CompilationSubject {
|
||||||
public:
|
public:
|
||||||
explicit CompilationSubject(FunctionBlueprint blueprint)
|
explicit CompilationSubject(FunctionBlueprint blueprint)
|
||||||
@ -367,6 +371,39 @@ class CompilationSubject {
|
|||||||
MaybeHandle<JSFunction> closure_;
|
MaybeHandle<JSFunction> closure_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A Callee is either a JSFunction (which may not have a feedback vector), or a
|
||||||
|
// FunctionBlueprint. Note that this is different from CompilationSubject, which
|
||||||
|
// always has a FunctionBlueprint.
|
||||||
|
class Callee {
|
||||||
|
public:
|
||||||
|
explicit Callee(Handle<JSFunction> jsfunction) : jsfunction_(jsfunction) {}
|
||||||
|
explicit Callee(FunctionBlueprint const& blueprint) : blueprint_(blueprint) {}
|
||||||
|
|
||||||
|
Handle<SharedFunctionInfo> shared(Isolate* isolate) const {
|
||||||
|
return blueprint_.has_value()
|
||||||
|
? blueprint_->shared()
|
||||||
|
: handle(jsfunction_.ToHandleChecked()->shared(), isolate);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasFeedbackVector() const {
|
||||||
|
Handle<JSFunction> function;
|
||||||
|
return blueprint_.has_value() ||
|
||||||
|
jsfunction_.ToHandleChecked()->has_feedback_vector();
|
||||||
|
}
|
||||||
|
|
||||||
|
CompilationSubject ToCompilationSubject(Isolate* isolate, Zone* zone) const {
|
||||||
|
CHECK(HasFeedbackVector());
|
||||||
|
return blueprint_.has_value()
|
||||||
|
? CompilationSubject(*blueprint_)
|
||||||
|
: CompilationSubject(jsfunction_.ToHandleChecked(), isolate,
|
||||||
|
zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MaybeHandle<JSFunction> const jsfunction_;
|
||||||
|
base::Optional<FunctionBlueprint> const blueprint_;
|
||||||
|
};
|
||||||
|
|
||||||
// The SerializerForBackgroundCompilation makes sure that the relevant function
|
// The SerializerForBackgroundCompilation makes sure that the relevant function
|
||||||
// data such as bytecode, SharedFunctionInfo and FeedbackVector, used by later
|
// data such as bytecode, SharedFunctionInfo and FeedbackVector, used by later
|
||||||
// optimizations in the compiler, is copied to the heap broker.
|
// optimizations in the compiler, is copied to the heap broker.
|
||||||
@ -396,15 +433,16 @@ class SerializerForBackgroundCompilation {
|
|||||||
SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
|
SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
|
||||||
#undef DECLARE_VISIT_BYTECODE
|
#undef DECLARE_VISIT_BYTECODE
|
||||||
|
|
||||||
// Returns whether the callee with the given SFI should be processed further,
|
void ProcessSFIForCallOrConstruct(Callee const& callee,
|
||||||
// i.e. whether it's inlineable.
|
base::Optional<Hints> new_target,
|
||||||
bool ProcessSFIForCallOrConstruct(Handle<SharedFunctionInfo> shared,
|
|
||||||
const HintsVector& arguments,
|
const HintsVector& arguments,
|
||||||
SpeculationMode speculation_mode);
|
SpeculationMode speculation_mode,
|
||||||
// Returns whether {function} should be serialized for compilation.
|
bool with_spread);
|
||||||
bool ProcessCalleeForCallOrConstruct(Handle<JSFunction> function,
|
void ProcessCalleeForCallOrConstruct(Handle<Object> callee,
|
||||||
|
base::Optional<Hints> new_target,
|
||||||
const HintsVector& arguments,
|
const HintsVector& arguments,
|
||||||
SpeculationMode speculation_mode);
|
SpeculationMode speculation_mode,
|
||||||
|
bool with_spread = false);
|
||||||
void ProcessCallOrConstruct(Hints callee, base::Optional<Hints> new_target,
|
void ProcessCallOrConstruct(Hints callee, base::Optional<Hints> new_target,
|
||||||
const HintsVector& arguments, FeedbackSlot slot,
|
const HintsVector& arguments, FeedbackSlot slot,
|
||||||
bool with_spread = false);
|
bool with_spread = false);
|
||||||
@ -417,15 +455,16 @@ class SerializerForBackgroundCompilation {
|
|||||||
void ProcessReceiverMapForApiCall(FunctionTemplateInfoRef target,
|
void ProcessReceiverMapForApiCall(FunctionTemplateInfoRef target,
|
||||||
Handle<Map> receiver);
|
Handle<Map> receiver);
|
||||||
void ProcessBuiltinCall(Handle<SharedFunctionInfo> target,
|
void ProcessBuiltinCall(Handle<SharedFunctionInfo> target,
|
||||||
|
base::Optional<Hints> new_target,
|
||||||
const HintsVector& arguments,
|
const HintsVector& arguments,
|
||||||
SpeculationMode speculation_mode);
|
SpeculationMode speculation_mode, bool with_spread);
|
||||||
|
|
||||||
void ProcessJump(interpreter::BytecodeArrayIterator* iterator);
|
void ProcessJump(interpreter::BytecodeArrayIterator* iterator);
|
||||||
|
|
||||||
void ProcessKeyedPropertyAccess(Hints const& receiver, Hints const& key,
|
void ProcessKeyedPropertyAccess(Hints const& receiver, Hints const& key,
|
||||||
FeedbackSlot slot, AccessMode access_mode,
|
FeedbackSlot slot, AccessMode access_mode,
|
||||||
bool honor_bailout_on_uninitialized);
|
bool honor_bailout_on_uninitialized);
|
||||||
void ProcessNamedPropertyAccess(Hints receiver, NameRef const& name,
|
void ProcessNamedPropertyAccess(Hints const& receiver, NameRef const& name,
|
||||||
FeedbackSlot slot, AccessMode access_mode);
|
FeedbackSlot slot, AccessMode access_mode);
|
||||||
void ProcessNamedAccess(Hints receiver, NamedAccessFeedback const& feedback,
|
void ProcessNamedAccess(Hints receiver, NamedAccessFeedback const& feedback,
|
||||||
AccessMode access_mode, Hints* new_accumulator_hints);
|
AccessMode access_mode, Hints* new_accumulator_hints);
|
||||||
@ -442,7 +481,6 @@ class SerializerForBackgroundCompilation {
|
|||||||
void ProcessHintsForHasInPrototypeChain(Hints const& instance_hints);
|
void ProcessHintsForHasInPrototypeChain(Hints const& instance_hints);
|
||||||
void ProcessHintsForRegExpTest(Hints const& regexp_hints);
|
void ProcessHintsForRegExpTest(Hints const& regexp_hints);
|
||||||
PropertyAccessInfo ProcessMapForRegExpTest(MapRef map);
|
PropertyAccessInfo ProcessMapForRegExpTest(MapRef map);
|
||||||
void ProcessHintsForFunctionCall(Hints const& target_hints);
|
|
||||||
void ProcessHintsForFunctionBind(Hints const& receiver_hints);
|
void ProcessHintsForFunctionBind(Hints const& receiver_hints);
|
||||||
void ProcessHintsForObjectGetPrototype(Hints const& object_hints);
|
void ProcessHintsForObjectGetPrototype(Hints const& object_hints);
|
||||||
void ProcessConstantForOrdinaryHasInstance(HeapObjectRef const& constructor,
|
void ProcessConstantForOrdinaryHasInstance(HeapObjectRef const& constructor,
|
||||||
@ -544,11 +582,11 @@ FunctionBlueprint::FunctionBlueprint(Handle<SharedFunctionInfo> shared,
|
|||||||
FunctionBlueprint::FunctionBlueprint(Handle<JSFunction> function,
|
FunctionBlueprint::FunctionBlueprint(Handle<JSFunction> function,
|
||||||
Isolate* isolate, Zone* zone)
|
Isolate* isolate, Zone* zone)
|
||||||
: shared_(handle(function->shared(), isolate)),
|
: shared_(handle(function->shared(), isolate)),
|
||||||
feedback_vector_(handle(function->feedback_vector(), isolate)),
|
feedback_vector_(function->feedback_vector(), isolate),
|
||||||
context_hints_() {
|
context_hints_() {
|
||||||
|
context_hints_.AddConstant(handle(function->context(), isolate), zone);
|
||||||
// The checked invariant rules out recursion and thus avoids complexity.
|
// The checked invariant rules out recursion and thus avoids complexity.
|
||||||
CHECK(context_hints_.function_blueprints().IsEmpty());
|
CHECK(context_hints_.function_blueprints().IsEmpty());
|
||||||
context_hints_.AddConstant(handle(function->context(), isolate), zone);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CompilationSubject::CompilationSubject(Handle<JSFunction> closure,
|
CompilationSubject::CompilationSubject(Handle<JSFunction> closure,
|
||||||
@ -1777,37 +1815,34 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer(
|
|||||||
return hints;
|
return hints;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SerializerForBackgroundCompilation::ProcessSFIForCallOrConstruct(
|
void SerializerForBackgroundCompilation::ProcessSFIForCallOrConstruct(
|
||||||
Handle<SharedFunctionInfo> shared, const HintsVector& arguments,
|
Callee const& callee, base::Optional<Hints> new_target,
|
||||||
SpeculationMode speculation_mode) {
|
const HintsVector& arguments, SpeculationMode speculation_mode,
|
||||||
|
bool with_spread) {
|
||||||
|
Handle<SharedFunctionInfo> shared = callee.shared(broker()->isolate());
|
||||||
if (shared->IsApiFunction()) {
|
if (shared->IsApiFunction()) {
|
||||||
ProcessApiCall(shared, arguments);
|
ProcessApiCall(shared, arguments);
|
||||||
DCHECK(!shared->IsInlineable());
|
DCHECK(!shared->IsInlineable());
|
||||||
} else if (shared->HasBuiltinId()) {
|
} else if (shared->HasBuiltinId()) {
|
||||||
ProcessBuiltinCall(shared, arguments, speculation_mode);
|
ProcessBuiltinCall(shared, new_target, arguments, speculation_mode,
|
||||||
|
with_spread);
|
||||||
DCHECK(!shared->IsInlineable());
|
DCHECK(!shared->IsInlineable());
|
||||||
|
} else if (shared->IsInlineable() && callee.HasFeedbackVector()) {
|
||||||
|
CompilationSubject subject =
|
||||||
|
callee.ToCompilationSubject(broker()->isolate(), zone());
|
||||||
|
environment()->accumulator_hints().Add(
|
||||||
|
RunChildSerializer(subject, new_target, arguments, with_spread),
|
||||||
|
zone());
|
||||||
}
|
}
|
||||||
return shared->IsInlineable();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
|
|
||||||
Handle<JSFunction> function, const HintsVector& arguments,
|
|
||||||
SpeculationMode speculation_mode) {
|
|
||||||
JSFunctionRef(broker(), function).Serialize();
|
|
||||||
|
|
||||||
Handle<SharedFunctionInfo> shared(function->shared(), broker()->isolate());
|
|
||||||
|
|
||||||
return ProcessSFIForCallOrConstruct(shared, arguments, speculation_mode) &&
|
|
||||||
function->has_feedback_vector();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Returns the innermost bound target, if it's a JSFunction and inserts
|
// Returns the innermost bound target and inserts all bound arguments and
|
||||||
// all bound arguments and {original_arguments} into {expanded_arguments}
|
// {original_arguments} into {expanded_arguments} in the appropriate order.
|
||||||
// in the appropriate order.
|
JSReceiverRef UnrollBoundFunction(JSBoundFunctionRef const& bound_function,
|
||||||
MaybeHandle<JSFunction> UnrollBoundFunction(
|
JSHeapBroker* broker,
|
||||||
JSBoundFunctionRef const& bound_function, JSHeapBroker* broker,
|
const HintsVector& original_arguments,
|
||||||
const HintsVector& original_arguments, HintsVector* expanded_arguments) {
|
HintsVector* expanded_arguments) {
|
||||||
DCHECK(expanded_arguments->empty());
|
DCHECK(expanded_arguments->empty());
|
||||||
|
|
||||||
JSReceiverRef target = bound_function.AsJSReceiver();
|
JSReceiverRef target = bound_function.AsJSReceiver();
|
||||||
@ -1826,8 +1861,6 @@ MaybeHandle<JSFunction> UnrollBoundFunction(
|
|||||||
reversed_bound_arguments.push_back(arg);
|
reversed_bound_arguments.push_back(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target.IsJSFunction()) return MaybeHandle<JSFunction>();
|
|
||||||
|
|
||||||
expanded_arguments->insert(expanded_arguments->end(),
|
expanded_arguments->insert(expanded_arguments->end(),
|
||||||
reversed_bound_arguments.rbegin(),
|
reversed_bound_arguments.rbegin(),
|
||||||
reversed_bound_arguments.rend());
|
reversed_bound_arguments.rend());
|
||||||
@ -1835,10 +1868,34 @@ MaybeHandle<JSFunction> UnrollBoundFunction(
|
|||||||
original_arguments.begin(),
|
original_arguments.begin(),
|
||||||
original_arguments.end());
|
original_arguments.end());
|
||||||
|
|
||||||
return target.AsJSFunction().object();
|
return target;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
|
||||||
|
Handle<Object> callee, base::Optional<Hints> new_target,
|
||||||
|
const HintsVector& arguments, SpeculationMode speculation_mode,
|
||||||
|
bool with_spread) {
|
||||||
|
const HintsVector* actual_arguments = &arguments;
|
||||||
|
HintsVector expanded_arguments(zone());
|
||||||
|
if (callee->IsJSBoundFunction()) {
|
||||||
|
JSBoundFunctionRef bound_function(broker(),
|
||||||
|
Handle<JSBoundFunction>::cast(callee));
|
||||||
|
bound_function.Serialize();
|
||||||
|
callee = UnrollBoundFunction(bound_function, broker(), arguments,
|
||||||
|
&expanded_arguments)
|
||||||
|
.object();
|
||||||
|
actual_arguments = &expanded_arguments;
|
||||||
|
}
|
||||||
|
if (!callee->IsJSFunction()) return;
|
||||||
|
|
||||||
|
JSFunctionRef function(broker(), Handle<JSFunction>::cast(callee));
|
||||||
|
function.Serialize();
|
||||||
|
Callee new_callee(function.object());
|
||||||
|
ProcessSFIForCallOrConstruct(new_callee, new_target, *actual_arguments,
|
||||||
|
speculation_mode, with_spread);
|
||||||
|
}
|
||||||
|
|
||||||
void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
|
void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
|
||||||
Hints callee, base::Optional<Hints> new_target,
|
Hints callee, base::Optional<Hints> new_target,
|
||||||
const HintsVector& arguments, FeedbackSlot slot, bool with_spread) {
|
const HintsVector& arguments, FeedbackSlot slot, bool with_spread) {
|
||||||
@ -1871,47 +1928,15 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
|
|||||||
environment()->accumulator_hints().Clear();
|
environment()->accumulator_hints().Clear();
|
||||||
|
|
||||||
// For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
|
// For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
|
||||||
for (auto hint : callee.constants()) {
|
for (auto constant : callee.constants()) {
|
||||||
const HintsVector* actual_arguments = &arguments;
|
ProcessCalleeForCallOrConstruct(constant, new_target, arguments,
|
||||||
Handle<JSFunction> function;
|
speculation_mode, with_spread);
|
||||||
HintsVector expanded_arguments(zone());
|
|
||||||
if (hint->IsJSBoundFunction()) {
|
|
||||||
JSBoundFunctionRef bound_function(broker(),
|
|
||||||
Handle<JSBoundFunction>::cast(hint));
|
|
||||||
bound_function.Serialize();
|
|
||||||
|
|
||||||
MaybeHandle<JSFunction> maybe_function = UnrollBoundFunction(
|
|
||||||
bound_function, broker(), arguments, &expanded_arguments);
|
|
||||||
if (maybe_function.is_null()) continue;
|
|
||||||
function = maybe_function.ToHandleChecked();
|
|
||||||
actual_arguments = &expanded_arguments;
|
|
||||||
} else if (hint->IsJSFunction()) {
|
|
||||||
function = Handle<JSFunction>::cast(hint);
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ProcessCalleeForCallOrConstruct(function, *actual_arguments,
|
|
||||||
speculation_mode)) {
|
|
||||||
environment()->accumulator_hints().Add(
|
|
||||||
RunChildSerializer(
|
|
||||||
CompilationSubject(function, broker()->isolate(), zone()),
|
|
||||||
new_target, *actual_arguments, with_spread),
|
|
||||||
zone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
|
// For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
|
||||||
for (auto hint : callee.function_blueprints()) {
|
for (auto hint : callee.function_blueprints()) {
|
||||||
Handle<SharedFunctionInfo> shared = hint.shared();
|
ProcessSFIForCallOrConstruct(Callee(hint), new_target, arguments,
|
||||||
if (!ProcessSFIForCallOrConstruct(shared, arguments, speculation_mode)) {
|
speculation_mode, with_spread);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
environment()->accumulator_hints().Add(
|
|
||||||
RunChildSerializer(CompilationSubject(hint), new_target, arguments,
|
|
||||||
with_spread),
|
|
||||||
zone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2000,8 +2025,9 @@ void SerializerForBackgroundCompilation::ProcessHintsForObjectCreate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
||||||
Handle<SharedFunctionInfo> target, const HintsVector& arguments,
|
Handle<SharedFunctionInfo> target, base::Optional<Hints> new_target,
|
||||||
SpeculationMode speculation_mode) {
|
const HintsVector& arguments, SpeculationMode speculation_mode,
|
||||||
|
bool with_spread) {
|
||||||
DCHECK(target->HasBuiltinId());
|
DCHECK(target->HasBuiltinId());
|
||||||
const int builtin_id = target->builtin_id();
|
const int builtin_id = target->builtin_id();
|
||||||
const char* name = Builtins::name(builtin_id);
|
const char* name = Builtins::name(builtin_id);
|
||||||
@ -2043,7 +2069,6 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
|||||||
case Builtins::kPromiseResolveTrampoline:
|
case Builtins::kPromiseResolveTrampoline:
|
||||||
// For JSCallReducer::ReducePromiseInternalResolve and
|
// For JSCallReducer::ReducePromiseInternalResolve and
|
||||||
// JSNativeContextSpecialization::ReduceJSResolvePromise.
|
// JSNativeContextSpecialization::ReduceJSResolvePromise.
|
||||||
// TODO(mslekova): Check if this condition is redundant.
|
|
||||||
if (arguments.size() >= 1) {
|
if (arguments.size() >= 1) {
|
||||||
Hints const& resolution_hints =
|
Hints const& resolution_hints =
|
||||||
arguments.size() >= 2
|
arguments.size() >= 2
|
||||||
@ -2087,30 +2112,45 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
|
|||||||
case Builtins::kArraySome:
|
case Builtins::kArraySome:
|
||||||
if (arguments.size() >= 2 &&
|
if (arguments.size() >= 2 &&
|
||||||
speculation_mode != SpeculationMode::kDisallowSpeculation) {
|
speculation_mode != SpeculationMode::kDisallowSpeculation) {
|
||||||
Hints const& callback_hints = arguments[1];
|
Hints const& callback = arguments[1];
|
||||||
ProcessHintsForFunctionCall(callback_hints);
|
for (auto constant : callback.constants()) {
|
||||||
|
ProcessCalleeForCallOrConstruct(
|
||||||
|
constant, base::nullopt, HintsVector(zone()),
|
||||||
|
SpeculationMode::kDisallowSpeculation, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// TODO(neis): At least for Array* we should look at blueprints too.
|
||||||
|
// TODO(neis): Might need something like a FunctionBlueprint but for
|
||||||
|
// creating bound functions rather than creating closures.
|
||||||
case Builtins::kFunctionPrototypeApply:
|
case Builtins::kFunctionPrototypeApply:
|
||||||
case Builtins::kFunctionPrototypeCall:
|
|
||||||
case Builtins::kPromiseConstructor:
|
case Builtins::kPromiseConstructor:
|
||||||
// TODO(mslekova): Since the reducer for all these introduce a
|
|
||||||
// JSCall/JSConstruct that will again get optimized by the JSCallReducer,
|
|
||||||
// we basically might have to do all the serialization that we do for that
|
|
||||||
// here as well. The only difference is that the new JSCall/JSConstruct
|
|
||||||
// has speculation disabled, causing the JSCallReducer to do much less
|
|
||||||
// work. To account for that, ProcessCallOrConstruct should have a way of
|
|
||||||
// taking the speculation mode as an argument rather than getting that
|
|
||||||
// from the feedback. (Also applies to Reflect.apply and
|
|
||||||
// Reflect.construct.)
|
|
||||||
if (arguments.size() >= 1) {
|
if (arguments.size() >= 1) {
|
||||||
ProcessHintsForFunctionCall(arguments[0]);
|
for (auto constant : arguments[0].constants()) {
|
||||||
|
ProcessCalleeForCallOrConstruct(
|
||||||
|
constant, base::nullopt, HintsVector(zone()),
|
||||||
|
SpeculationMode::kDisallowSpeculation, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Builtins::kFunctionPrototypeCall:
|
||||||
|
if (arguments.size() >= 1) {
|
||||||
|
HintsVector new_arguments(arguments.begin() + 1, arguments.end(),
|
||||||
|
zone());
|
||||||
|
for (auto constant : arguments[0].constants()) {
|
||||||
|
ProcessCalleeForCallOrConstruct(
|
||||||
|
constant, base::nullopt, new_arguments,
|
||||||
|
SpeculationMode::kDisallowSpeculation, with_spread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Builtins::kReflectApply:
|
case Builtins::kReflectApply:
|
||||||
case Builtins::kReflectConstruct:
|
case Builtins::kReflectConstruct:
|
||||||
if (arguments.size() >= 2) {
|
if (arguments.size() >= 2) {
|
||||||
ProcessHintsForFunctionCall(arguments[1]);
|
for (auto constant : arguments[1].constants()) {
|
||||||
|
if (constant->IsJSFunction())
|
||||||
|
JSFunctionRef(broker(), constant).Serialize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Builtins::kObjectPrototypeIsPrototypeOf:
|
case Builtins::kObjectPrototypeIsPrototypeOf:
|
||||||
@ -2273,13 +2313,6 @@ void SerializerForBackgroundCompilation::ProcessHintsForRegExpTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerializerForBackgroundCompilation::ProcessHintsForFunctionCall(
|
|
||||||
Hints const& target_hints) {
|
|
||||||
for (auto constant : target_hints.constants()) {
|
|
||||||
if (constant->IsJSFunction()) JSFunctionRef(broker(), constant).Serialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void ProcessMapForFunctionBind(MapRef map) {
|
void ProcessMapForFunctionBind(MapRef map) {
|
||||||
map.SerializePrototype();
|
map.SerializePrototype();
|
||||||
@ -2692,7 +2725,7 @@ void SerializerForBackgroundCompilation::ProcessKeyedPropertyAccess(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
|
void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
|
||||||
Hints receiver, NameRef const& name, FeedbackSlot slot,
|
Hints const& receiver, NameRef const& name, FeedbackSlot slot,
|
||||||
AccessMode access_mode) {
|
AccessMode access_mode) {
|
||||||
if (slot.IsInvalid() || feedback_vector().is_null()) return;
|
if (slot.IsInvalid() || feedback_vector().is_null()) return;
|
||||||
FeedbackSource source(feedback_vector(), slot);
|
FeedbackSource source(feedback_vector(), slot);
|
||||||
@ -2706,6 +2739,7 @@ void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
|
|||||||
DCHECK(name.equals(feedback.AsNamedAccess().name()));
|
DCHECK(name.equals(feedback.AsNamedAccess().name()));
|
||||||
ProcessNamedAccess(receiver, feedback.AsNamedAccess(), access_mode,
|
ProcessNamedAccess(receiver, feedback.AsNamedAccess(), access_mode,
|
||||||
&new_accumulator_hints);
|
&new_accumulator_hints);
|
||||||
|
// TODO(neis): Propagate feedback maps to receiver hints.
|
||||||
break;
|
break;
|
||||||
case ProcessedFeedback::kInsufficient:
|
case ProcessedFeedback::kInsufficient:
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user