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,
}
// static
FieldAccess AccessBuilder::ForJSFunctionPrototypeOrInitialMap() {
FieldAccess access = {kTaggedBase, JSFunction::kPrototypeOrInitialMapOffset,
MaybeHandle<Name>(), Type::Any(),
MachineType::AnyTagged()};
return access;
}
// static
FieldAccess AccessBuilder::ForJSFunctionContext() {
FieldAccess access = {kTaggedBase, JSFunction::kContextOffset,
......@@ -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
FieldAccess AccessBuilder::ForJSArrayLength(ElementsKind elements_kind) {
TypeCache const& type_cache = TypeCache::Get();
......
......@@ -34,12 +34,24 @@ class AccessBuilder final : public AllStatic {
// Provides access to JSObject inobject property fields.
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.
static FieldAccess ForJSFunctionContext();
// Provides access to JSFunction::shared() field.
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.
static FieldAccess ForJSArrayLength(ElementsKind elements_kind);
......
......@@ -201,6 +201,8 @@ Reduction JSCreateLowering::Reduce(Node* node) {
return ReduceJSCreateArguments(node);
case IrOpcode::kJSCreateArray:
return ReduceJSCreateArray(node);
case IrOpcode::kJSCreateClosure:
return ReduceJSCreateClosure(node);
case IrOpcode::kJSCreateIterResultObject:
return ReduceJSCreateIterResultObject(node);
case IrOpcode::kJSCreateLiteralArray:
......@@ -540,6 +542,51 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
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) {
DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
Node* value = NodeProperties::GetValueInput(node, 0);
......
......@@ -45,6 +45,7 @@ class JSCreateLowering final : public AdvancedReducer {
Reduction ReduceJSCreate(Node* node);
Reduction ReduceJSCreateArguments(Node* node);
Reduction ReduceJSCreateArray(Node* node);
Reduction ReduceJSCreateClosure(Node* node);
Reduction ReduceJSCreateIterResultObject(Node* node);
Reduction ReduceJSCreateLiteral(Node* node);
Reduction ReduceJSCreateFunctionContext(Node* node);
......
......@@ -171,6 +171,24 @@ TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedRestArray) {
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
......
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