Commit 43c7c76f authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Use inline allocation for closures.

This changes closure creation to lower to inline allocations when
possible instead of going through the FastNewClosureStub. It allows us
to leverage all advantages of inline allocations on closures. Note that
it is only safe to embed the raw entry point of the compile lazy stub
into the code, because that stub is immortal and immovable.

R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/1573153002

Cr-Commit-Position: refs/heads/master@{#35499}
parent 290ee88f
...@@ -60,6 +60,14 @@ FieldAccess AccessBuilder::ForJSObjectInObjectProperty(Handle<Map> map, ...@@ -60,6 +60,14 @@ FieldAccess AccessBuilder::ForJSObjectInObjectProperty(Handle<Map> map,
} }
// static
FieldAccess AccessBuilder::ForJSFunctionPrototypeOrInitialMap() {
FieldAccess access = {kTaggedBase, JSFunction::kPrototypeOrInitialMapOffset,
MaybeHandle<Name>(), Type::Any(),
MachineType::AnyTagged()};
return access;
}
// static // static
FieldAccess AccessBuilder::ForJSFunctionContext() { FieldAccess AccessBuilder::ForJSFunctionContext() {
FieldAccess access = {kTaggedBase, JSFunction::kContextOffset, FieldAccess access = {kTaggedBase, JSFunction::kContextOffset,
...@@ -77,6 +85,29 @@ FieldAccess AccessBuilder::ForJSFunctionSharedFunctionInfo() { ...@@ -77,6 +85,29 @@ FieldAccess AccessBuilder::ForJSFunctionSharedFunctionInfo() {
} }
// static
FieldAccess AccessBuilder::ForJSFunctionLiterals() {
FieldAccess access = {kTaggedBase, JSFunction::kLiteralsOffset,
Handle<Name>(), Type::Internal(),
MachineType::AnyTagged()};
return access;
}
// static
FieldAccess AccessBuilder::ForJSFunctionCodeEntry() {
FieldAccess access = {kTaggedBase, JSFunction::kCodeEntryOffset,
Handle<Name>(), Type::UntaggedPointer(),
MachineType::Pointer()};
return access;
}
// static
FieldAccess AccessBuilder::ForJSFunctionNextFunctionLink() {
FieldAccess access = {kTaggedBase, JSFunction::kNextFunctionLinkOffset,
Handle<Name>(), Type::Any(), MachineType::AnyTagged()};
return access;
}
// static // static
FieldAccess AccessBuilder::ForJSArrayLength(ElementsKind elements_kind) { FieldAccess AccessBuilder::ForJSArrayLength(ElementsKind elements_kind) {
TypeCache const& type_cache = TypeCache::Get(); TypeCache const& type_cache = TypeCache::Get();
......
...@@ -34,12 +34,24 @@ class AccessBuilder final : public AllStatic { ...@@ -34,12 +34,24 @@ class AccessBuilder final : public AllStatic {
// Provides access to JSObject inobject property fields. // Provides access to JSObject inobject property fields.
static FieldAccess ForJSObjectInObjectProperty(Handle<Map> map, int index); static FieldAccess ForJSObjectInObjectProperty(Handle<Map> map, int index);
// Provides access to JSFunction::prototype_or_initial_map() field.
static FieldAccess ForJSFunctionPrototypeOrInitialMap();
// Provides access to JSFunction::context() field. // Provides access to JSFunction::context() field.
static FieldAccess ForJSFunctionContext(); static FieldAccess ForJSFunctionContext();
// Provides access to JSFunction::shared() field. // Provides access to JSFunction::shared() field.
static FieldAccess ForJSFunctionSharedFunctionInfo(); static FieldAccess ForJSFunctionSharedFunctionInfo();
// Provides access to JSFunction::literals() field.
static FieldAccess ForJSFunctionLiterals();
// Provides access to JSFunction::code() field.
static FieldAccess ForJSFunctionCodeEntry();
// Provides access to JSFunction::next_function_link() field.
static FieldAccess ForJSFunctionNextFunctionLink();
// Provides access to JSArray::length() field. // Provides access to JSArray::length() field.
static FieldAccess ForJSArrayLength(ElementsKind elements_kind); static FieldAccess ForJSArrayLength(ElementsKind elements_kind);
......
...@@ -201,6 +201,8 @@ Reduction JSCreateLowering::Reduce(Node* node) { ...@@ -201,6 +201,8 @@ Reduction JSCreateLowering::Reduce(Node* node) {
return ReduceJSCreateArguments(node); return ReduceJSCreateArguments(node);
case IrOpcode::kJSCreateArray: case IrOpcode::kJSCreateArray:
return ReduceJSCreateArray(node); return ReduceJSCreateArray(node);
case IrOpcode::kJSCreateClosure:
return ReduceJSCreateClosure(node);
case IrOpcode::kJSCreateIterResultObject: case IrOpcode::kJSCreateIterResultObject:
return ReduceJSCreateIterResultObject(node); return ReduceJSCreateIterResultObject(node);
case IrOpcode::kJSCreateLiteralArray: case IrOpcode::kJSCreateLiteralArray:
...@@ -540,6 +542,51 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) { ...@@ -540,6 +542,51 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
return NoChange(); return NoChange();
} }
Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
Handle<SharedFunctionInfo> shared = p.shared_info();
// Use inline allocation for functions that don't need literals cloning.
if (shared->num_literals() == 0) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* context = NodeProperties::GetContextInput(node);
Node* native_context = effect = graph()->NewNode(
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
context, context, effect);
int function_map_index =
Context::FunctionMapIndex(shared->language_mode(), shared->kind());
Node* function_map = effect =
graph()->NewNode(javascript()->LoadContext(0, function_map_index, true),
native_context, native_context, effect);
// Note that it is only safe to embed the raw entry point of the compile
// lazy stub into the code, because that stub is immortal and immovable.
Node* compile_entry = jsgraph()->IntPtrConstant(reinterpret_cast<intptr_t>(
jsgraph()->isolate()->builtins()->CompileLazy()->entry()));
Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
Node* the_hole = jsgraph()->TheHoleConstant();
Node* undefined = jsgraph()->UndefinedConstant();
AllocationBuilder a(jsgraph(), effect, control);
STATIC_ASSERT(JSFunction::kSize == 9 * kPointerSize);
a.Allocate(JSFunction::kSize, p.pretenure());
a.Store(AccessBuilder::ForMap(), function_map);
a.Store(AccessBuilder::ForJSObjectProperties(), empty_fixed_array);
a.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
a.Store(AccessBuilder::ForJSFunctionLiterals(), empty_fixed_array);
a.Store(AccessBuilder::ForJSFunctionPrototypeOrInitialMap(), the_hole);
a.Store(AccessBuilder::ForJSFunctionSharedFunctionInfo(), shared);
a.Store(AccessBuilder::ForJSFunctionContext(), context);
a.Store(AccessBuilder::ForJSFunctionCodeEntry(), compile_entry);
a.Store(AccessBuilder::ForJSFunctionNextFunctionLink(), undefined);
RelaxControls(node);
a.FinishAndChange(node);
return Changed(node);
}
return NoChange();
}
Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) { Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode()); DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
Node* value = NodeProperties::GetValueInput(node, 0); Node* value = NodeProperties::GetValueInput(node, 0);
......
...@@ -45,6 +45,7 @@ class JSCreateLowering final : public AdvancedReducer { ...@@ -45,6 +45,7 @@ class JSCreateLowering final : public AdvancedReducer {
Reduction ReduceJSCreate(Node* node); Reduction ReduceJSCreate(Node* node);
Reduction ReduceJSCreateArguments(Node* node); Reduction ReduceJSCreateArguments(Node* node);
Reduction ReduceJSCreateArray(Node* node); Reduction ReduceJSCreateArray(Node* node);
Reduction ReduceJSCreateClosure(Node* node);
Reduction ReduceJSCreateIterResultObject(Node* node); Reduction ReduceJSCreateIterResultObject(Node* node);
Reduction ReduceJSCreateLiteral(Node* node); Reduction ReduceJSCreateLiteral(Node* node);
Reduction ReduceJSCreateFunctionContext(Node* node); Reduction ReduceJSCreateFunctionContext(Node* node);
......
...@@ -171,6 +171,24 @@ TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedRestArray) { ...@@ -171,6 +171,24 @@ TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedRestArray) {
IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _)); IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _));
} }
// -----------------------------------------------------------------------------
// JSCreateClosure
TEST_F(JSCreateLoweringTest, JSCreateClosureViaInlinedAllocation) {
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
Reduction r =
Reduce(graph()->NewNode(javascript()->CreateClosure(shared, NOT_TENURED),
context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFinishRegion(IsAllocate(IsNumberConstant(JSFunction::kSize),
IsBeginRegion(_), control),
_));
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// JSCreateFunctionContext // JSCreateFunctionContext
......
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