Commit 2ece046c authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[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: 's avatarMichael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51547}
parent c41c7a09
......@@ -1444,8 +1444,9 @@ void BytecodeGraphBuilder::VisitCreateClosure() {
bytecode_iterator().GetFlagOperand(2))
? TENURED
: NOT_TENURED;
const Operator* op = javascript()->CreateClosure(
shared_info, nexus.GetFeedbackCell(), tenured);
const Operator* op =
javascript()->CreateClosure(shared_info, nexus.GetFeedbackCell(),
CreateClosureMode::kRegular, tenured);
Node* closure = NewNode(op);
environment()->BindAccumulator(closure);
}
......
......@@ -4656,7 +4656,8 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
isolate());
Node* resolve = effect =
graph()->NewNode(javascript()->CreateClosure(
resolve_shared, factory()->many_closures_cell()),
resolve_shared, factory()->many_closures_cell(),
CreateClosureMode::kBuiltin),
promise_context, effect, control);
// Allocate the closure for the reject case.
......@@ -4665,7 +4666,8 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
isolate());
Node* reject = effect =
graph()->NewNode(javascript()->CreateClosure(
reject_shared, factory()->many_closures_cell()),
reject_shared, factory()->many_closures_cell(),
CreateClosureMode::kBuiltin),
promise_context, effect, control);
// 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());
catch_true = etrue =
graph()->NewNode(javascript()->CreateClosure(
catch_finally, factory()->many_closures_cell()),
catch_finally, factory()->many_closures_cell(),
CreateClosureMode::kBuiltin),
context, etrue, if_true);
// Allocate the closure for the fulfill case.
......@@ -4967,7 +4970,8 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
native_context()->promise_then_finally_shared_fun(), isolate());
then_true = etrue =
graph()->NewNode(javascript()->CreateClosure(
then_finally, factory()->many_closures_cell()),
then_finally, factory()->many_closures_cell(),
CreateClosureMode::kBuiltin),
context, etrue, if_true);
}
......
......@@ -901,6 +901,7 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
Handle<SharedFunctionInfo> shared = p.shared_info();
Handle<FeedbackCell> feedback_cell = p.feedback_cell();
CreateClosureMode const mode = p.mode();
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* context = NodeProperties::GetContextInput(node);
......@@ -914,10 +915,11 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
Handle<Map> function_map(
Map::cast(native_context()->get(shared->function_map_index())));
Node* lazy_compile_builtin = jsgraph()->HeapConstant(handle(
shared->native() ? shared->code()
: isolate()->builtins()->builtin(Builtins::kCompileLazy),
isolate()));
Node* lazy_compile_builtin = jsgraph()->HeapConstant(
handle(mode == CreateClosureMode::kBuiltin
? shared->code()
: isolate()->builtins()->builtin(Builtins::kCompileLazy),
isolate()));
DCHECK(!function_map->IsInobjectSlackTrackingInProgress());
DCHECK(!function_map->is_dictionary_map());
......
......@@ -376,6 +376,9 @@ void JSGenericLowering::LowerJSCreateClosure(Node* node) {
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.feedback_cell()));
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.
if (p.pretenure() == NOT_TENURED) {
Callable callable =
......
......@@ -445,6 +445,18 @@ const CreateBoundFunctionParameters& CreateBoundFunctionParametersOf(
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,
CreateClosureParameters const& rhs) {
return lhs.pretenure() == rhs.pretenure() &&
......@@ -1062,8 +1074,9 @@ const Operator* JSOperatorBuilder::CreateBoundFunction(size_t arity,
const Operator* JSOperatorBuilder::CreateClosure(
Handle<SharedFunctionInfo> shared_info, Handle<FeedbackCell> feedback_cell,
PretenureFlag pretenure) {
CreateClosureParameters parameters(shared_info, feedback_cell, pretenure);
CreateClosureMode mode, PretenureFlag pretenure) {
CreateClosureParameters parameters(shared_info, feedback_cell, mode,
pretenure);
return new (zone()) Operator1<CreateClosureParameters>( // --
IrOpcode::kJSCreateClosure, Operator::kEliminatable, // opcode
"JSCreateClosure", // name
......
......@@ -529,24 +529,37 @@ std::ostream& operator<<(std::ostream&, CreateBoundFunctionParameters const&);
const CreateBoundFunctionParameters& CreateBoundFunctionParametersOf(
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
// used as a parameter by JSCreateClosure operators.
class CreateClosureParameters final {
public:
CreateClosureParameters(Handle<SharedFunctionInfo> shared_info,
Handle<FeedbackCell> feedback_cell,
PretenureFlag pretenure)
CreateClosureMode mode, PretenureFlag pretenure)
: shared_info_(shared_info),
feedback_cell_(feedback_cell),
mode_(mode),
pretenure_(pretenure) {}
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
Handle<FeedbackCell> feedback_cell() const { return feedback_cell_; }
CreateClosureMode mode() const { return mode_; }
PretenureFlag pretenure() const { return pretenure_; }
private:
Handle<SharedFunctionInfo> const shared_info_;
Handle<FeedbackCell> const feedback_cell_;
CreateClosureMode const mode_;
PretenureFlag const pretenure_;
};
......@@ -656,6 +669,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* CreateBoundFunction(size_t arity, Handle<Map> map);
const Operator* CreateClosure(Handle<SharedFunctionInfo> shared_info,
Handle<FeedbackCell> feedback_cell,
CreateClosureMode mode,
PretenureFlag pretenure = NOT_TENURED);
const Operator* CreateIterResultObject();
const Operator* CreateStringIterator();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment