[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:
Benedikt Meurer 2018-02-22 13:39:34 +01:00 committed by Commit Bot
parent c41c7a0943
commit 2ece046c5b
6 changed files with 50 additions and 13 deletions

View File

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

View File

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

View File

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

View File

@ -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 =

View File

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

View File

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