[turbofan] Introduce explicit CreateClosureMode.
We use JSCreateClosure to also constructs closures for builtins, i.e. for the callbacks created by the Promise constructor. For these builtins we cannot set code to CompileLazy builtin, but need to use the code from the SharedFunctionInfo. The explicit mode tells the lowering what it should do (instead of relying on SharedFunctionInfo::native(), which is not the right bit). Bug: v8:2206, v8:7253, v8:7310 Change-Id: Ic956814e137c57b36ebb5d7b4d964dde5ee51a0d Reviewed-on: https://chromium-review.googlesource.com/930964 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Michael Stanton <mvstanton@chromium.org> Cr-Commit-Position: refs/heads/master@{#51547}
This commit is contained in:
parent
c41c7a0943
commit
2ece046c5b
@ -1444,8 +1444,9 @@ void BytecodeGraphBuilder::VisitCreateClosure() {
|
|||||||
bytecode_iterator().GetFlagOperand(2))
|
bytecode_iterator().GetFlagOperand(2))
|
||||||
? TENURED
|
? TENURED
|
||||||
: NOT_TENURED;
|
: NOT_TENURED;
|
||||||
const Operator* op = javascript()->CreateClosure(
|
const Operator* op =
|
||||||
shared_info, nexus.GetFeedbackCell(), tenured);
|
javascript()->CreateClosure(shared_info, nexus.GetFeedbackCell(),
|
||||||
|
CreateClosureMode::kRegular, tenured);
|
||||||
Node* closure = NewNode(op);
|
Node* closure = NewNode(op);
|
||||||
environment()->BindAccumulator(closure);
|
environment()->BindAccumulator(closure);
|
||||||
}
|
}
|
||||||
|
@ -4656,7 +4656,8 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
|
|||||||
isolate());
|
isolate());
|
||||||
Node* resolve = effect =
|
Node* resolve = effect =
|
||||||
graph()->NewNode(javascript()->CreateClosure(
|
graph()->NewNode(javascript()->CreateClosure(
|
||||||
resolve_shared, factory()->many_closures_cell()),
|
resolve_shared, factory()->many_closures_cell(),
|
||||||
|
CreateClosureMode::kBuiltin),
|
||||||
promise_context, effect, control);
|
promise_context, effect, control);
|
||||||
|
|
||||||
// Allocate the closure for the reject case.
|
// Allocate the closure for the reject case.
|
||||||
@ -4665,7 +4666,8 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
|
|||||||
isolate());
|
isolate());
|
||||||
Node* reject = effect =
|
Node* reject = effect =
|
||||||
graph()->NewNode(javascript()->CreateClosure(
|
graph()->NewNode(javascript()->CreateClosure(
|
||||||
reject_shared, factory()->many_closures_cell()),
|
reject_shared, factory()->many_closures_cell(),
|
||||||
|
CreateClosureMode::kBuiltin),
|
||||||
promise_context, effect, control);
|
promise_context, effect, control);
|
||||||
|
|
||||||
// Re-use the params from above, but actually set the promise parameter now.
|
// Re-use the params from above, but actually set the promise parameter now.
|
||||||
@ -4959,7 +4961,8 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
|
|||||||
native_context()->promise_catch_finally_shared_fun(), isolate());
|
native_context()->promise_catch_finally_shared_fun(), isolate());
|
||||||
catch_true = etrue =
|
catch_true = etrue =
|
||||||
graph()->NewNode(javascript()->CreateClosure(
|
graph()->NewNode(javascript()->CreateClosure(
|
||||||
catch_finally, factory()->many_closures_cell()),
|
catch_finally, factory()->many_closures_cell(),
|
||||||
|
CreateClosureMode::kBuiltin),
|
||||||
context, etrue, if_true);
|
context, etrue, if_true);
|
||||||
|
|
||||||
// Allocate the closure for the fulfill case.
|
// Allocate the closure for the fulfill case.
|
||||||
@ -4967,7 +4970,8 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
|
|||||||
native_context()->promise_then_finally_shared_fun(), isolate());
|
native_context()->promise_then_finally_shared_fun(), isolate());
|
||||||
then_true = etrue =
|
then_true = etrue =
|
||||||
graph()->NewNode(javascript()->CreateClosure(
|
graph()->NewNode(javascript()->CreateClosure(
|
||||||
then_finally, factory()->many_closures_cell()),
|
then_finally, factory()->many_closures_cell(),
|
||||||
|
CreateClosureMode::kBuiltin),
|
||||||
context, etrue, if_true);
|
context, etrue, if_true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,6 +901,7 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
|
|||||||
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
|
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
|
||||||
Handle<SharedFunctionInfo> shared = p.shared_info();
|
Handle<SharedFunctionInfo> shared = p.shared_info();
|
||||||
Handle<FeedbackCell> feedback_cell = p.feedback_cell();
|
Handle<FeedbackCell> feedback_cell = p.feedback_cell();
|
||||||
|
CreateClosureMode const mode = p.mode();
|
||||||
Node* effect = NodeProperties::GetEffectInput(node);
|
Node* effect = NodeProperties::GetEffectInput(node);
|
||||||
Node* control = NodeProperties::GetControlInput(node);
|
Node* control = NodeProperties::GetControlInput(node);
|
||||||
Node* context = NodeProperties::GetContextInput(node);
|
Node* context = NodeProperties::GetContextInput(node);
|
||||||
@ -914,8 +915,9 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
|
|||||||
|
|
||||||
Handle<Map> function_map(
|
Handle<Map> function_map(
|
||||||
Map::cast(native_context()->get(shared->function_map_index())));
|
Map::cast(native_context()->get(shared->function_map_index())));
|
||||||
Node* lazy_compile_builtin = jsgraph()->HeapConstant(handle(
|
Node* lazy_compile_builtin = jsgraph()->HeapConstant(
|
||||||
shared->native() ? shared->code()
|
handle(mode == CreateClosureMode::kBuiltin
|
||||||
|
? shared->code()
|
||||||
: isolate()->builtins()->builtin(Builtins::kCompileLazy),
|
: isolate()->builtins()->builtin(Builtins::kCompileLazy),
|
||||||
isolate()));
|
isolate()));
|
||||||
DCHECK(!function_map->IsInobjectSlackTrackingInProgress());
|
DCHECK(!function_map->IsInobjectSlackTrackingInProgress());
|
||||||
|
@ -376,6 +376,9 @@ void JSGenericLowering::LowerJSCreateClosure(Node* node) {
|
|||||||
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.feedback_cell()));
|
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.feedback_cell()));
|
||||||
node->RemoveInput(4); // control
|
node->RemoveInput(4); // control
|
||||||
|
|
||||||
|
// We cannot deal with closures for builtins here.
|
||||||
|
DCHECK_EQ(CreateClosureMode::kRegular, p.mode());
|
||||||
|
|
||||||
// Use the FastNewClosure builtin only for functions allocated in new space.
|
// Use the FastNewClosure builtin only for functions allocated in new space.
|
||||||
if (p.pretenure() == NOT_TENURED) {
|
if (p.pretenure() == NOT_TENURED) {
|
||||||
Callable callable =
|
Callable callable =
|
||||||
|
@ -445,6 +445,18 @@ const CreateBoundFunctionParameters& CreateBoundFunctionParametersOf(
|
|||||||
return OpParameter<CreateBoundFunctionParameters>(op);
|
return OpParameter<CreateBoundFunctionParameters>(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t hash_value(CreateClosureMode mode) { return static_cast<uint8_t>(mode); }
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, CreateClosureMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case CreateClosureMode::kBuiltin:
|
||||||
|
return os << "Builtin";
|
||||||
|
case CreateClosureMode::kRegular:
|
||||||
|
return os << "Regular";
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(CreateClosureParameters const& lhs,
|
bool operator==(CreateClosureParameters const& lhs,
|
||||||
CreateClosureParameters const& rhs) {
|
CreateClosureParameters const& rhs) {
|
||||||
return lhs.pretenure() == rhs.pretenure() &&
|
return lhs.pretenure() == rhs.pretenure() &&
|
||||||
@ -1062,8 +1074,9 @@ const Operator* JSOperatorBuilder::CreateBoundFunction(size_t arity,
|
|||||||
|
|
||||||
const Operator* JSOperatorBuilder::CreateClosure(
|
const Operator* JSOperatorBuilder::CreateClosure(
|
||||||
Handle<SharedFunctionInfo> shared_info, Handle<FeedbackCell> feedback_cell,
|
Handle<SharedFunctionInfo> shared_info, Handle<FeedbackCell> feedback_cell,
|
||||||
PretenureFlag pretenure) {
|
CreateClosureMode mode, PretenureFlag pretenure) {
|
||||||
CreateClosureParameters parameters(shared_info, feedback_cell, pretenure);
|
CreateClosureParameters parameters(shared_info, feedback_cell, mode,
|
||||||
|
pretenure);
|
||||||
return new (zone()) Operator1<CreateClosureParameters>( // --
|
return new (zone()) Operator1<CreateClosureParameters>( // --
|
||||||
IrOpcode::kJSCreateClosure, Operator::kEliminatable, // opcode
|
IrOpcode::kJSCreateClosure, Operator::kEliminatable, // opcode
|
||||||
"JSCreateClosure", // name
|
"JSCreateClosure", // name
|
||||||
|
@ -529,24 +529,37 @@ std::ostream& operator<<(std::ostream&, CreateBoundFunctionParameters const&);
|
|||||||
const CreateBoundFunctionParameters& CreateBoundFunctionParametersOf(
|
const CreateBoundFunctionParameters& CreateBoundFunctionParametersOf(
|
||||||
const Operator* op);
|
const Operator* op);
|
||||||
|
|
||||||
|
// The mode identifies the kind of closure to create.
|
||||||
|
enum class CreateClosureMode : uint8_t {
|
||||||
|
kBuiltin, // Closure for a builtin, use SharedFunctionInfo::code().
|
||||||
|
kRegular // Regular closure, use CompileLazy for code.
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t hash_value(CreateClosureMode);
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream&, CreateClosureMode);
|
||||||
|
|
||||||
// Defines shared information for the closure that should be created. This is
|
// Defines shared information for the closure that should be created. This is
|
||||||
// used as a parameter by JSCreateClosure operators.
|
// used as a parameter by JSCreateClosure operators.
|
||||||
class CreateClosureParameters final {
|
class CreateClosureParameters final {
|
||||||
public:
|
public:
|
||||||
CreateClosureParameters(Handle<SharedFunctionInfo> shared_info,
|
CreateClosureParameters(Handle<SharedFunctionInfo> shared_info,
|
||||||
Handle<FeedbackCell> feedback_cell,
|
Handle<FeedbackCell> feedback_cell,
|
||||||
PretenureFlag pretenure)
|
CreateClosureMode mode, PretenureFlag pretenure)
|
||||||
: shared_info_(shared_info),
|
: shared_info_(shared_info),
|
||||||
feedback_cell_(feedback_cell),
|
feedback_cell_(feedback_cell),
|
||||||
|
mode_(mode),
|
||||||
pretenure_(pretenure) {}
|
pretenure_(pretenure) {}
|
||||||
|
|
||||||
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
|
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
|
||||||
Handle<FeedbackCell> feedback_cell() const { return feedback_cell_; }
|
Handle<FeedbackCell> feedback_cell() const { return feedback_cell_; }
|
||||||
|
CreateClosureMode mode() const { return mode_; }
|
||||||
PretenureFlag pretenure() const { return pretenure_; }
|
PretenureFlag pretenure() const { return pretenure_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Handle<SharedFunctionInfo> const shared_info_;
|
Handle<SharedFunctionInfo> const shared_info_;
|
||||||
Handle<FeedbackCell> const feedback_cell_;
|
Handle<FeedbackCell> const feedback_cell_;
|
||||||
|
CreateClosureMode const mode_;
|
||||||
PretenureFlag const pretenure_;
|
PretenureFlag const pretenure_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -656,6 +669,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
|
|||||||
const Operator* CreateBoundFunction(size_t arity, Handle<Map> map);
|
const Operator* CreateBoundFunction(size_t arity, Handle<Map> map);
|
||||||
const Operator* CreateClosure(Handle<SharedFunctionInfo> shared_info,
|
const Operator* CreateClosure(Handle<SharedFunctionInfo> shared_info,
|
||||||
Handle<FeedbackCell> feedback_cell,
|
Handle<FeedbackCell> feedback_cell,
|
||||||
|
CreateClosureMode mode,
|
||||||
PretenureFlag pretenure = NOT_TENURED);
|
PretenureFlag pretenure = NOT_TENURED);
|
||||||
const Operator* CreateIterResultObject();
|
const Operator* CreateIterResultObject();
|
||||||
const Operator* CreateStringIterator();
|
const Operator* CreateStringIterator();
|
||||||
|
Loading…
Reference in New Issue
Block a user