Commit d1597b7d authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Use FastCloneShallow[Array|Object]Stub if possible.

This allows the JSIntrinsicLowering to optimize the cloning of literal
boilerplate objects using either the FastCloneShallowArrayStub or the
FastCloneShallowObjectStub when applicable.

R=mvstanton@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#27974}
parent d20660e0
......@@ -1507,6 +1507,9 @@ class ObjectLiteral final : public MaterializedLiteral {
int ComputeFlags(bool disable_mementos = false) const {
int flags = fast_elements() ? kFastElements : kNoFlags;
flags |= has_function() ? kHasFunction : kNoFlags;
if (depth() == 1 && !has_elements() && !may_store_doubles()) {
flags |= kShallowProperties;
}
if (disable_mementos) {
flags |= kDisableMementos;
}
......@@ -1517,7 +1520,8 @@ class ObjectLiteral final : public MaterializedLiteral {
kNoFlags = 0,
kFastElements = 1,
kHasFunction = 1 << 1,
kDisableMementos = 1 << 2
kShallowProperties = 1 << 2,
kDisableMementos = 1 << 3
};
struct Accessors: public ZoneObject {
......
......@@ -142,6 +142,21 @@ Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
}
// static
Callable CodeFactory::FastCloneShallowArray(Isolate* isolate) {
// TODO(mstarzinger): Thread through AllocationSiteMode at some point.
FastCloneShallowArrayStub stub(isolate, DONT_TRACK_ALLOCATION_SITE);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::FastCloneShallowObject(Isolate* isolate, int length) {
FastCloneShallowObjectStub stub(isolate, length);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::AllocateHeapNumber(Isolate* isolate) {
AllocateHeapNumberStub stub(isolate);
......
......@@ -65,6 +65,9 @@ class CodeFactory final {
static Callable StringAdd(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag);
static Callable FastCloneShallowArray(Isolate* isolate);
static Callable FastCloneShallowObject(Isolate* isolate, int length);
static Callable AllocateHeapNumber(Isolate* isolate);
static Callable CallFunction(Isolate* isolate, int argc,
......
......@@ -1630,7 +1630,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Node* constants = jsgraph()->Constant(expr->constant_properties());
Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
const Operator* op =
javascript()->CallRuntime(Runtime::kCreateObjectLiteral, 4);
javascript()->CallRuntime(Runtime::kInlineCreateObjectLiteral, 4);
Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());
......@@ -1822,7 +1822,7 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
Node* constants = jsgraph()->Constant(expr->constant_elements());
Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
const Operator* op =
javascript()->CallRuntime(Runtime::kCreateArrayLiteral, 4);
javascript()->CallRuntime(Runtime::kInlineCreateArrayLiteral, 4);
Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());
......
......@@ -7,8 +7,10 @@
#include <stack>
#include "src/code-factory.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties.h"
......@@ -28,6 +30,10 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
switch (f->function_id) {
case Runtime::kInlineConstructDouble:
return ReduceConstructDouble(node);
case Runtime::kInlineCreateArrayLiteral:
return ReduceCreateArrayLiteral(node);
case Runtime::kInlineCreateObjectLiteral:
return ReduceCreateObjectLiteral(node);
case Runtime::kInlineDeoptimizeNow:
return ReduceDeoptimizeNow(node);
case Runtime::kInlineDoubleHi:
......@@ -94,6 +100,62 @@ Reduction JSIntrinsicLowering::ReduceConstructDouble(Node* node) {
}
Reduction JSIntrinsicLowering::ReduceCreateArrayLiteral(Node* node) {
HeapObjectMatcher<FixedArray> mconst(NodeProperties::GetValueInput(node, 2));
NumberMatcher mflags(NodeProperties::GetValueInput(node, 3));
int length = mconst.Value().handle()->length();
int flags = FastD2I(mflags.Value());
// Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
// initial length limit for arrays with "fast" elements kind.
if ((flags & ArrayLiteral::kShallowElements) != 0 &&
length < JSObject::kInitialMaxFastElementArray) {
Isolate* isolate = jsgraph()->isolate();
Callable callable = CodeFactory::FastCloneShallowArray(isolate);
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate, graph()->zone(), callable.descriptor(), 0,
FLAG_turbo_deoptimization ? CallDescriptor::kNeedsFrameState
: CallDescriptor::kNoFlags);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->RemoveInput(3); // Remove flags input from node.
node->InsertInput(graph()->zone(), 0, stub_code);
node->set_op(new_op);
return Changed(node);
}
return NoChange();
}
Reduction JSIntrinsicLowering::ReduceCreateObjectLiteral(Node* node) {
HeapObjectMatcher<FixedArray> mconst(NodeProperties::GetValueInput(node, 2));
NumberMatcher mflags(NodeProperties::GetValueInput(node, 3));
// Constants are pairs, see ObjectLiteral::properties_count().
int length = mconst.Value().handle()->length() / 2;
int flags = FastD2I(mflags.Value());
// Use the FastCloneShallowObjectStub only for shallow boilerplates without
// elements up to the number of properties that the stubs can handle.
if ((flags & ObjectLiteral::kShallowProperties) != 0 &&
length <= FastCloneShallowObjectStub::kMaximumClonedProperties) {
Isolate* isolate = jsgraph()->isolate();
Callable callable = CodeFactory::FastCloneShallowObject(isolate, length);
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate, graph()->zone(), callable.descriptor(), 0,
FLAG_turbo_deoptimization ? CallDescriptor::kNeedsFrameState
: CallDescriptor::kNoFlags);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 0, stub_code);
node->set_op(new_op);
return Changed(node);
}
return NoChange();
}
Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) {
if (!FLAG_turbo_deoptimization) return NoChange();
......
......@@ -29,6 +29,8 @@ class JSIntrinsicLowering final : public Reducer {
private:
Reduction ReduceConstructDouble(Node* node);
Reduction ReduceCreateArrayLiteral(Node* node);
Reduction ReduceCreateObjectLiteral(Node* node);
Reduction ReduceDeoptimizeNow(Node* node);
Reduction ReduceDoubleHi(Node* node);
Reduction ReduceDoubleLo(Node* node);
......
......@@ -127,6 +127,8 @@ bool Linkage::NeedsFrameState(Runtime::FunctionId function) {
return false;
case Runtime::kInlineArguments:
case Runtime::kInlineCallFunction:
case Runtime::kInlineCreateArrayLiteral:
case Runtime::kInlineCreateObjectLiteral:
case Runtime::kInlineDateField:
case Runtime::kInlineDeoptimizeNow:
case Runtime::kInlineGetPrototype:
......
......@@ -420,13 +420,13 @@ void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime(
ObjectLiteral* expr) const {
int literal_flags = expr->ComputeFlags();
// FastCloneShallowObjectStub doesn't copy elements, and object literals don't
// support copy-on-write (COW) elements for now.
// TODO(mvstanton): make object literals support COW elements.
return expr->may_store_doubles() || expr->depth() > 1 ||
masm()->serializer_enabled() ||
expr->ComputeFlags() != ObjectLiteral::kFastElements ||
expr->has_elements() ||
return masm()->serializer_enabled() ||
literal_flags != ObjectLiteral::kShallowProperties ||
literal_flags != ObjectLiteral::kFastElements ||
expr->properties_count() >
FastCloneShallowObjectStub::kMaximumClonedProperties;
}
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/code-factory.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/diamond.h"
#include "src/compiler/js-graph.h"
......@@ -65,6 +66,56 @@ TEST_F(JSIntrinsicLoweringTest, InlineOptimizedConstructDouble) {
}
// -----------------------------------------------------------------------------
// %_CreateArrayLiteral
TEST_F(JSIntrinsicLoweringTest, InlineCreateArrayLiteral) {
i::FLAG_turbo_deoptimization = false;
Node* const input0 = Parameter(0);
Node* const input1 = Parameter(1);
Node* const input2 = HeapConstant(factory()->NewFixedArray(12));
Node* const input3 = NumberConstant(ArrayLiteral::kShallowElements);
Node* const context = Parameter(2);
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction const r = Reduce(graph()->NewNode(
javascript()->CallRuntime(Runtime::kInlineCreateArrayLiteral, 4), input0,
input1, input2, input3, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
CodeFactory::FastCloneShallowArray(isolate()).code())),
input0, input1, input2, effect, control));
}
// -----------------------------------------------------------------------------
// %_CreateObjectLiteral
TEST_F(JSIntrinsicLoweringTest, InlineCreateObjectLiteral) {
i::FLAG_turbo_deoptimization = false;
Node* const input0 = Parameter(0);
Node* const input1 = Parameter(1);
Node* const input2 = HeapConstant(factory()->NewFixedArray(2 * 6));
Node* const input3 = NumberConstant(ObjectLiteral::kShallowProperties);
Node* const context = Parameter(2);
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction const r = Reduce(graph()->NewNode(
javascript()->CallRuntime(Runtime::kInlineCreateObjectLiteral, 4), input0,
input1, input2, input3, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable(
CodeFactory::FastCloneShallowObject(isolate(), 6).code())),
input0, input1, input2, effect, control));
}
// -----------------------------------------------------------------------------
// %_DoubleLo
......
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