[turbofan] Introduce proper CreateLiteralParameters.

Put the constant parts of the CreateLiteralArray and CreateLiteralObject
operators into CreateLiteralParameters and properly use them everywhere.

R=mstarzinger@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#32207}
This commit is contained in:
bmeurer 2015-11-24 05:42:11 -08:00 committed by Commit bot
parent 085fed0fb5
commit 68ce906134
6 changed files with 135 additions and 47 deletions

View File

@ -1715,11 +1715,10 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
// Create node to deep-copy the literal boilerplate.
Node* literals_array =
BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
Node* literal_index = jsgraph()->Constant(expr->literal_index());
Node* constants = jsgraph()->Constant(expr->constant_properties());
const Operator* op =
javascript()->CreateLiteralObject(expr->ComputeFlags(true));
Node* literal = NewNode(op, literals_array, literal_index, constants);
const Operator* op = javascript()->CreateLiteralObject(
expr->constant_properties(), expr->ComputeFlags(true),
expr->literal_index());
Node* literal = NewNode(op, literals_array);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());
@ -1921,11 +1920,10 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
// Create node to deep-copy the literal boilerplate.
Node* literals_array =
BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
Node* literal_index = jsgraph()->Constant(expr->literal_index());
Node* constants = jsgraph()->Constant(expr->constant_elements());
const Operator* op =
javascript()->CreateLiteralArray(expr->ComputeFlags(true));
Node* literal = NewNode(op, literals_array, literal_index, constants);
const Operator* op = javascript()->CreateLiteralArray(
expr->constant_elements(), expr->ComputeFlags(true),
expr->literal_index());
Node* literal = NewNode(op, literals_array);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());

View File

@ -504,15 +504,19 @@ void JSGenericLowering::LowerJSCreateClosure(Node* node) {
void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
int literal_flags = OpParameter<int>(node->op());
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(literal_flags));
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constants()));
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
}
void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
int literal_flags = OpParameter<int>(node->op());
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(literal_flags));
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constants()));
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
}

View File

@ -410,6 +410,36 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) {
}
bool operator==(CreateLiteralParameters const& lhs,
CreateLiteralParameters const& rhs) {
return lhs.constants().location() == rhs.constants().location() &&
lhs.flags() == rhs.flags() && lhs.index() == rhs.index();
}
bool operator!=(CreateLiteralParameters const& lhs,
CreateLiteralParameters const& rhs) {
return !(lhs == rhs);
}
size_t hash_value(CreateLiteralParameters const& p) {
return base::hash_combine(p.constants().location(), p.flags(), p.index());
}
std::ostream& operator<<(std::ostream& os, CreateLiteralParameters const& p) {
return os << Brief(*p.constants()) << ", " << p.flags() << ", " << p.index();
}
const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kJSCreateLiteralArray ||
op->opcode() == IrOpcode::kJSCreateLiteralObject);
return OpParameter<CreateLiteralParameters>(op);
}
#define CACHED_OP_LIST(V) \
V(Equal, Operator::kNoProperties, 2, 1) \
V(NotEqual, Operator::kNoProperties, 2, 1) \
@ -723,21 +753,29 @@ const Operator* JSOperatorBuilder::CreateClosure(
}
const Operator* JSOperatorBuilder::CreateLiteralArray(int literal_flags) {
return new (zone()) Operator1<int>( // --
const Operator* JSOperatorBuilder::CreateLiteralArray(
Handle<FixedArray> constant_elements, int literal_flags,
int literal_index) {
CreateLiteralParameters parameters(constant_elements, literal_flags,
literal_index);
return new (zone()) Operator1<CreateLiteralParameters>( // --
IrOpcode::kJSCreateLiteralArray, Operator::kNoProperties, // opcode
"JSCreateLiteralArray", // name
3, 1, 1, 1, 1, 2, // counts
literal_flags); // parameter
1, 1, 1, 1, 1, 2, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::CreateLiteralObject(int literal_flags) {
return new (zone()) Operator1<int>( // --
const Operator* JSOperatorBuilder::CreateLiteralObject(
Handle<FixedArray> constant_properties, int literal_flags,
int literal_index) {
CreateLiteralParameters parameters(constant_properties, literal_flags,
literal_index);
return new (zone()) Operator1<CreateLiteralParameters>( // --
IrOpcode::kJSCreateLiteralObject, Operator::kNoProperties, // opcode
"JSCreateLiteralObject", // name
3, 1, 1, 1, 1, 2, // counts
literal_flags); // parameter
1, 1, 1, 1, 1, 2, // counts
parameters); // parameter
}

View File

@ -403,6 +403,34 @@ std::ostream& operator<<(std::ostream&, CreateClosureParameters const&);
const CreateClosureParameters& CreateClosureParametersOf(const Operator* op);
// Defines shared information for the literal that should be created. This is
// used as parameter by JSCreateLiteralArray and JSCreateLiteralObject
// operators.
class CreateLiteralParameters final {
public:
CreateLiteralParameters(Handle<FixedArray> constants, int flags, int index)
: constants_(constants), flags_(flags), index_(index) {}
Handle<FixedArray> constants() const { return constants_; }
int flags() const { return flags_; }
int index() const { return index_; }
private:
Handle<FixedArray> const constants_;
int const flags_;
int const index_;
};
bool operator==(CreateLiteralParameters const&, CreateLiteralParameters const&);
bool operator!=(CreateLiteralParameters const&, CreateLiteralParameters const&);
size_t hash_value(CreateLiteralParameters const&);
std::ostream& operator<<(std::ostream&, CreateLiteralParameters const&);
const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op);
// Interface for building JavaScript-level operators, e.g. directly from the
// AST. Most operators have no parameters, thus can be globally shared for all
// graphs.
@ -444,8 +472,10 @@ class JSOperatorBuilder final : public ZoneObject {
const Operator* CreateArray(size_t arity, Handle<AllocationSite> site);
const Operator* CreateClosure(Handle<SharedFunctionInfo> shared_info,
PretenureFlag pretenure);
const Operator* CreateLiteralArray(int literal_flags);
const Operator* CreateLiteralObject(int literal_flags);
const Operator* CreateLiteralArray(Handle<FixedArray> constant_elements,
int literal_flags, int literal_index);
const Operator* CreateLiteralObject(Handle<FixedArray> constant_properties,
int literal_flags, int literal_index);
const Operator* CallFunction(
size_t arity, LanguageMode language_mode,

View File

@ -1765,9 +1765,9 @@ Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) {
Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateLiteralArray, node->opcode());
HeapObjectMatcher mconst(NodeProperties::GetValueInput(node, 2));
int length = Handle<FixedArray>::cast(mconst.Value())->length();
int flags = OpParameter<int>(node->op());
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
int const length = p.constants()->length();
int const flags = p.flags();
// Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
// initial length limit for arrays with "fast" elements kind.
@ -1784,7 +1784,11 @@ Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) {
: CallDescriptor::kNoFlags);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
Node* literal_index = jsgraph()->SmiConstant(p.index());
Node* constant_elements = jsgraph()->HeapConstant(p.constants());
node->InsertInput(graph()->zone(), 0, stub_code);
node->InsertInput(graph()->zone(), 2, literal_index);
node->InsertInput(graph()->zone(), 3, constant_elements);
NodeProperties::ChangeOp(node, new_op);
return Changed(node);
}
@ -1795,10 +1799,10 @@ Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) {
Reduction JSTypedLowering::ReduceJSCreateLiteralObject(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateLiteralObject, node->opcode());
HeapObjectMatcher mconst(NodeProperties::GetValueInput(node, 2));
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
// Constants are pairs, see ObjectLiteral::properties_count().
int length = Handle<FixedArray>::cast(mconst.Value())->length() / 2;
int flags = OpParameter<int>(node->op());
int const length = p.constants()->length() / 2;
int const flags = p.flags();
// Use the FastCloneShallowObjectStub only for shallow boilerplates without
// elements up to the number of properties that the stubs can handle.
@ -1813,8 +1817,13 @@ Reduction JSTypedLowering::ReduceJSCreateLiteralObject(Node* node) {
: CallDescriptor::kNoFlags);
const Operator* new_op = common()->Call(desc);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(flags));
Node* literal_index = jsgraph()->SmiConstant(p.index());
Node* literal_flags = jsgraph()->SmiConstant(flags);
Node* constant_elements = jsgraph()->HeapConstant(p.constants());
node->InsertInput(graph()->zone(), 0, stub_code);
node->InsertInput(graph()->zone(), 2, literal_index);
node->InsertInput(graph()->zone(), 3, constant_elements);
node->InsertInput(graph()->zone(), 4, literal_flags);
NodeProperties::ChangeOp(node, new_op);
return Changed(node);
}

View File

@ -1091,22 +1091,26 @@ TEST_F(JSTypedLoweringTest, JSCreateClosure) {
TEST_F(JSTypedLoweringTest, JSCreateLiteralArray) {
Node* const input0 = Parameter(0);
Node* const input1 = Parameter(1);
Node* const input2 = HeapConstant(factory()->NewFixedArray(12));
Node* const context = UndefinedConstant();
Handle<FixedArray> const constant_elements = factory()->NewFixedArray(12);
int const literal_flags = ArrayLiteral::kShallowElements;
int const literal_index = 1;
Node* const input = Parameter(0);
Node* const context = Parameter(1);
Node* const frame_state = EmptyFrameState();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction const r = Reduce(graph()->NewNode(
javascript()->CreateLiteralArray(ArrayLiteral::kShallowElements), input0,
input1, input2, context, frame_state, effect, control));
Reduction const r = Reduce(
graph()->NewNode(javascript()->CreateLiteralArray(
constant_elements, literal_flags, literal_index),
input, context, frame_state, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsCall(_, IsHeapConstant(
CodeFactory::FastCloneShallowArray(isolate()).code()),
input0, input1, input2, context, frame_state, effect, control));
input, IsNumberConstant(literal_index),
IsHeapConstant(constant_elements), context, frame_state, effect,
control));
}
@ -1115,22 +1119,27 @@ TEST_F(JSTypedLoweringTest, JSCreateLiteralArray) {
TEST_F(JSTypedLoweringTest, JSCreateLiteralObject) {
Node* const input0 = Parameter(0);
Node* const input1 = Parameter(1);
Node* const input2 = HeapConstant(factory()->NewFixedArray(2 * 6));
Node* const context = UndefinedConstant();
Handle<FixedArray> const constant_properties =
factory()->NewFixedArray(6 * 2);
int const literal_flags = ObjectLiteral::kShallowProperties;
int const literal_index = 1;
Node* const input = Parameter(0);
Node* const context = Parameter(1);
Node* const frame_state = EmptyFrameState();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction const r = Reduce(graph()->NewNode(
javascript()->CreateLiteralObject(ObjectLiteral::kShallowProperties),
input0, input1, input2, context, frame_state, effect, control));
Reduction const r = Reduce(
graph()->NewNode(javascript()->CreateLiteralObject(
constant_properties, literal_flags, literal_index),
input, context, frame_state, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(
r.replacement(),
IsCall(_, IsHeapConstant(
CodeFactory::FastCloneShallowObject(isolate(), 6).code()),
input0, input1, input2, _, context, frame_state, effect, control));
input, IsNumberConstant(literal_index),
IsHeapConstant(constant_properties), _, context, frame_state,
effect, control));
}