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;
}
kNoFlags = 0,
kFastElements = 1,
kHasFunction = 1 << 1,
- kDisableMementos = 1 << 2
+ kShallowProperties = 1 << 2,
+ kDisableMementos = 1 << 3
};
struct Accessors: public ZoneObject {
}
+// 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);
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,
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());
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());
#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"
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:
}
+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();
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);
return false;
case Runtime::kInlineArguments:
case Runtime::kInlineCallFunction:
+ case Runtime::kInlineCreateArrayLiteral:
+ case Runtime::kInlineCreateObjectLiteral:
case Runtime::kInlineDateField:
case Runtime::kInlineDeoptimizeNow:
case Runtime::kInlineGetPrototype:
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;
}
// 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"
}
+// -----------------------------------------------------------------------------
+// %_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