[ast] Create CompoundAssignment subclass of Assignment
This saves one pointer in Assignment for non-compound assignment expressions. Change-Id: I7ec32c1d378917c81ab55c42733b6af450ce65db Reviewed-on: https://chromium-review.googlesource.com/612673 Commit-Queue: Adam Klein <adamk@chromium.org> Reviewed-by: Marja Hölttä <marja@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#47380}
This commit is contained in:
parent
8f1bc55817
commit
8024d38a64
@ -265,6 +265,10 @@ void AstExpressionRewriter::VisitAssignment(Assignment* node) {
|
|||||||
AST_REWRITE_PROPERTY(Expression, node, value);
|
AST_REWRITE_PROPERTY(Expression, node, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AstExpressionRewriter::VisitCompoundAssignment(CompoundAssignment* node) {
|
||||||
|
VisitAssignment(node);
|
||||||
|
}
|
||||||
|
|
||||||
void AstExpressionRewriter::VisitYield(Yield* node) {
|
void AstExpressionRewriter::VisitYield(Yield* node) {
|
||||||
REWRITE_THIS(node);
|
REWRITE_THIS(node);
|
||||||
AST_REWRITE_PROPERTY(Expression, node, expression);
|
AST_REWRITE_PROPERTY(Expression, node, expression);
|
||||||
|
@ -313,12 +313,15 @@ void AstNumberingVisitor::VisitProperty(Property* node) {
|
|||||||
|
|
||||||
|
|
||||||
void AstNumberingVisitor::VisitAssignment(Assignment* node) {
|
void AstNumberingVisitor::VisitAssignment(Assignment* node) {
|
||||||
if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
|
|
||||||
VisitReference(node->target());
|
VisitReference(node->target());
|
||||||
Visit(node->value());
|
Visit(node->value());
|
||||||
ReserveFeedbackSlots(node);
|
ReserveFeedbackSlots(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AstNumberingVisitor::VisitCompoundAssignment(CompoundAssignment* node) {
|
||||||
|
VisitBinaryOperation(node->binary_operation());
|
||||||
|
VisitAssignment(node);
|
||||||
|
}
|
||||||
|
|
||||||
void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
|
void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
|
||||||
Visit(node->left());
|
Visit(node->left());
|
||||||
|
@ -359,6 +359,12 @@ void AstTraversalVisitor<Subclass>::VisitAssignment(Assignment* expr) {
|
|||||||
RECURSE_EXPRESSION(Visit(expr->value()));
|
RECURSE_EXPRESSION(Visit(expr->value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Subclass>
|
||||||
|
void AstTraversalVisitor<Subclass>::VisitCompoundAssignment(
|
||||||
|
CompoundAssignment* expr) {
|
||||||
|
VisitAssignment(expr);
|
||||||
|
}
|
||||||
|
|
||||||
template <class Subclass>
|
template <class Subclass>
|
||||||
void AstTraversalVisitor<Subclass>::VisitYield(Yield* expr) {
|
void AstTraversalVisitor<Subclass>::VisitYield(Yield* expr) {
|
||||||
PROCESS_EXPRESSION(expr);
|
PROCESS_EXPRESSION(expr);
|
||||||
|
@ -251,12 +251,9 @@ void ForInStatement::AssignFeedbackSlots(FeedbackVectorSpec* spec,
|
|||||||
for_in_feedback_slot_ = spec->AddGeneralSlot();
|
for_in_feedback_slot_ = spec->AddGeneralSlot();
|
||||||
}
|
}
|
||||||
|
|
||||||
Assignment::Assignment(Token::Value op, Expression* target, Expression* value,
|
Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
|
||||||
int pos)
|
Expression* value, int pos)
|
||||||
: Expression(pos, kAssignment),
|
: Expression(pos, node_type), target_(target), value_(value) {
|
||||||
target_(target),
|
|
||||||
value_(value),
|
|
||||||
binary_operation_(NULL) {
|
|
||||||
bit_field_ |= IsUninitializedField::encode(false) |
|
bit_field_ |= IsUninitializedField::encode(false) |
|
||||||
KeyTypeField::encode(ELEMENT) |
|
KeyTypeField::encode(ELEMENT) |
|
||||||
StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op);
|
StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op);
|
||||||
@ -278,24 +275,6 @@ void CountOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Token::Value Assignment::binary_op() const {
|
|
||||||
switch (op()) {
|
|
||||||
case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
|
|
||||||
case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
|
|
||||||
case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
|
|
||||||
case Token::ASSIGN_SHL: return Token::SHL;
|
|
||||||
case Token::ASSIGN_SAR: return Token::SAR;
|
|
||||||
case Token::ASSIGN_SHR: return Token::SHR;
|
|
||||||
case Token::ASSIGN_ADD: return Token::ADD;
|
|
||||||
case Token::ASSIGN_SUB: return Token::SUB;
|
|
||||||
case Token::ASSIGN_MUL: return Token::MUL;
|
|
||||||
case Token::ASSIGN_DIV: return Token::DIV;
|
|
||||||
case Token::ASSIGN_MOD: return Token::MOD;
|
|
||||||
default: UNREACHABLE();
|
|
||||||
}
|
|
||||||
return Token::ILLEGAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FunctionLiteral::ShouldEagerCompile() const {
|
bool FunctionLiteral::ShouldEagerCompile() const {
|
||||||
return scope()->ShouldEagerCompile();
|
return scope()->ShouldEagerCompile();
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,7 @@ namespace internal {
|
|||||||
|
|
||||||
#define PROPERTY_NODE_LIST(V) \
|
#define PROPERTY_NODE_LIST(V) \
|
||||||
V(Assignment) \
|
V(Assignment) \
|
||||||
|
V(CompoundAssignment) \
|
||||||
V(CountOperation) \
|
V(CountOperation) \
|
||||||
V(Property)
|
V(Property)
|
||||||
|
|
||||||
@ -2099,13 +2100,8 @@ class Conditional final : public Expression {
|
|||||||
Expression* else_expression_;
|
Expression* else_expression_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Assignment : public Expression {
|
||||||
class Assignment final : public Expression {
|
|
||||||
public:
|
public:
|
||||||
Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }
|
|
||||||
|
|
||||||
Token::Value binary_op() const;
|
|
||||||
|
|
||||||
Token::Value op() const { return TokenField::decode(bit_field_); }
|
Token::Value op() const { return TokenField::decode(bit_field_); }
|
||||||
Expression* target() const { return target_; }
|
Expression* target() const { return target_; }
|
||||||
Expression* value() const { return value_; }
|
Expression* value() const { return value_; }
|
||||||
@ -2113,11 +2109,6 @@ class Assignment final : public Expression {
|
|||||||
void set_target(Expression* e) { target_ = e; }
|
void set_target(Expression* e) { target_ = e; }
|
||||||
void set_value(Expression* e) { value_ = e; }
|
void set_value(Expression* e) { value_ = e; }
|
||||||
|
|
||||||
BinaryOperation* binary_operation() const { return binary_operation_; }
|
|
||||||
|
|
||||||
// This check relies on the definition order of token in token.h.
|
|
||||||
bool is_compound() const { return op() > Token::ASSIGN; }
|
|
||||||
|
|
||||||
// Type feedback information.
|
// Type feedback information.
|
||||||
bool IsUninitialized() const {
|
bool IsUninitialized() const {
|
||||||
return IsUninitializedField::decode(bit_field_);
|
return IsUninitializedField::decode(bit_field_);
|
||||||
@ -2157,11 +2148,13 @@ class Assignment final : public Expression {
|
|||||||
FeedbackSlotCache* cache);
|
FeedbackSlotCache* cache);
|
||||||
FeedbackSlot AssignmentSlot() const { return slot_; }
|
FeedbackSlot AssignmentSlot() const { return slot_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Assignment(NodeType type, Token::Value op, Expression* target,
|
||||||
|
Expression* value, int pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class AstNodeFactory;
|
friend class AstNodeFactory;
|
||||||
|
|
||||||
Assignment(Token::Value op, Expression* target, Expression* value, int pos);
|
|
||||||
|
|
||||||
class IsUninitializedField
|
class IsUninitializedField
|
||||||
: public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
|
: public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
|
||||||
class KeyTypeField
|
class KeyTypeField
|
||||||
@ -2175,10 +2168,23 @@ class Assignment final : public Expression {
|
|||||||
FeedbackSlot slot_;
|
FeedbackSlot slot_;
|
||||||
Expression* target_;
|
Expression* target_;
|
||||||
Expression* value_;
|
Expression* value_;
|
||||||
BinaryOperation* binary_operation_;
|
|
||||||
SmallMapList receiver_types_;
|
SmallMapList receiver_types_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CompoundAssignment final : public Assignment {
|
||||||
|
public:
|
||||||
|
BinaryOperation* binary_operation() const { return binary_operation_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class AstNodeFactory;
|
||||||
|
|
||||||
|
CompoundAssignment(Token::Value op, Expression* target, Expression* value,
|
||||||
|
int pos, BinaryOperation* binary_operation)
|
||||||
|
: Assignment(kCompoundAssignment, op, target, value, pos),
|
||||||
|
binary_operation_(binary_operation) {}
|
||||||
|
|
||||||
|
BinaryOperation* binary_operation_;
|
||||||
|
};
|
||||||
|
|
||||||
// The RewritableExpression class is a wrapper for AST nodes that wait
|
// The RewritableExpression class is a wrapper for AST nodes that wait
|
||||||
// for some potential rewriting. However, even if such nodes are indeed
|
// for some potential rewriting. However, even if such nodes are indeed
|
||||||
@ -3360,12 +3366,15 @@ class AstNodeFactory final BASE_EMBEDDED {
|
|||||||
target->AsVariableProxy()->set_is_assigned();
|
target->AsVariableProxy()->set_is_assigned();
|
||||||
}
|
}
|
||||||
|
|
||||||
Assignment* assign = new (zone_) Assignment(op, target, value, pos);
|
if (op == Token::ASSIGN || op == Token::INIT) {
|
||||||
if (assign->is_compound()) {
|
return new (zone_)
|
||||||
assign->binary_operation_ =
|
Assignment(AstNode::kAssignment, op, target, value, pos);
|
||||||
NewBinaryOperation(assign->binary_op(), target, value, pos + 1);
|
} else {
|
||||||
|
return new (zone_) CompoundAssignment(
|
||||||
|
op, target, value, pos,
|
||||||
|
NewBinaryOperation(Token::BinaryOpForAssignment(op), target, value,
|
||||||
|
pos + 1));
|
||||||
}
|
}
|
||||||
return assign;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Suspend* NewYield(Expression* expression, int pos,
|
Suspend* NewYield(Expression* expression, int pos,
|
||||||
|
@ -269,6 +269,10 @@ void CallPrinter::VisitAssignment(Assignment* node) {
|
|||||||
Find(node->value());
|
Find(node->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
|
||||||
|
VisitAssignment(node);
|
||||||
|
}
|
||||||
|
|
||||||
void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
|
void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
|
||||||
|
|
||||||
void CallPrinter::VisitYieldStar(YieldStar* node) { Find(node->expression()); }
|
void CallPrinter::VisitYieldStar(YieldStar* node) { Find(node->expression()); }
|
||||||
@ -1141,6 +1145,10 @@ void AstPrinter::VisitAssignment(Assignment* node) {
|
|||||||
Visit(node->value());
|
Visit(node->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AstPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
|
||||||
|
VisitAssignment(node);
|
||||||
|
}
|
||||||
|
|
||||||
void AstPrinter::VisitYield(Yield* node) {
|
void AstPrinter::VisitYield(Yield* node) {
|
||||||
EmbeddedVector<char, 128> buf;
|
EmbeddedVector<char, 128> buf;
|
||||||
SNPrintF(buf, "YIELD id %d", node->suspend_id());
|
SNPrintF(buf, "YIELD id %d", node->suspend_id());
|
||||||
|
@ -2488,7 +2488,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
|||||||
|
|
||||||
// Evaluate the value and potentially handle compound assignments by loading
|
// Evaluate the value and potentially handle compound assignments by loading
|
||||||
// the left-hand side value and performing a binary operation.
|
// the left-hand side value and performing a binary operation.
|
||||||
if (expr->is_compound()) {
|
if (expr->IsCompoundAssignment()) {
|
||||||
switch (assign_type) {
|
switch (assign_type) {
|
||||||
case VARIABLE: {
|
case VARIABLE: {
|
||||||
VariableProxy* proxy = expr->target()->AsVariableProxy();
|
VariableProxy* proxy = expr->target()->AsVariableProxy();
|
||||||
@ -2519,17 +2519,17 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FeedbackSlot slot = expr->binary_operation()->BinaryOperationFeedbackSlot();
|
BinaryOperation* binop = expr->AsCompoundAssignment()->binary_operation();
|
||||||
|
FeedbackSlot slot = binop->BinaryOperationFeedbackSlot();
|
||||||
if (expr->value()->IsSmiLiteral()) {
|
if (expr->value()->IsSmiLiteral()) {
|
||||||
builder()->BinaryOperationSmiLiteral(
|
builder()->BinaryOperationSmiLiteral(
|
||||||
expr->binary_op(), expr->value()->AsLiteral()->AsSmiLiteral(),
|
binop->op(), expr->value()->AsLiteral()->AsSmiLiteral(),
|
||||||
feedback_index(slot));
|
feedback_index(slot));
|
||||||
} else {
|
} else {
|
||||||
Register old_value = register_allocator()->NewRegister();
|
Register old_value = register_allocator()->NewRegister();
|
||||||
builder()->StoreAccumulatorInRegister(old_value);
|
builder()->StoreAccumulatorInRegister(old_value);
|
||||||
VisitForAccumulatorValue(expr->value());
|
VisitForAccumulatorValue(expr->value());
|
||||||
builder()->BinaryOperation(expr->binary_op(), old_value,
|
builder()->BinaryOperation(binop->op(), old_value, feedback_index(slot));
|
||||||
feedback_index(slot));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VisitForAccumulatorValue(expr->value());
|
VisitForAccumulatorValue(expr->value());
|
||||||
@ -2571,6 +2571,10 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BytecodeGenerator::VisitCompoundAssignment(CompoundAssignment* expr) {
|
||||||
|
VisitAssignment(expr);
|
||||||
|
}
|
||||||
|
|
||||||
// Suspends the generator to resume at |suspend_id|, with output stored in the
|
// Suspends the generator to resume at |suspend_id|, with output stored in the
|
||||||
// accumulator. When the generator is resumed, the sent value is loaded in the
|
// accumulator. When the generator is resumed, the sent value is loaded in the
|
||||||
// accumulator.
|
// accumulator.
|
||||||
|
@ -2458,7 +2458,7 @@ void Parser::AddArrowFunctionFormalParameters(
|
|||||||
Expression* initializer = nullptr;
|
Expression* initializer = nullptr;
|
||||||
if (expr->IsAssignment()) {
|
if (expr->IsAssignment()) {
|
||||||
Assignment* assignment = expr->AsAssignment();
|
Assignment* assignment = expr->AsAssignment();
|
||||||
DCHECK(!assignment->is_compound());
|
DCHECK(!assignment->IsCompoundAssignment());
|
||||||
initializer = assignment->value();
|
initializer = assignment->value();
|
||||||
expr = assignment->target();
|
expr = assignment->target();
|
||||||
}
|
}
|
||||||
|
@ -782,6 +782,7 @@ NOT_A_PATTERN(CallRuntime)
|
|||||||
NOT_A_PATTERN(CaseClause)
|
NOT_A_PATTERN(CaseClause)
|
||||||
NOT_A_PATTERN(ClassLiteral)
|
NOT_A_PATTERN(ClassLiteral)
|
||||||
NOT_A_PATTERN(CompareOperation)
|
NOT_A_PATTERN(CompareOperation)
|
||||||
|
NOT_A_PATTERN(CompoundAssignment)
|
||||||
NOT_A_PATTERN(Conditional)
|
NOT_A_PATTERN(Conditional)
|
||||||
NOT_A_PATTERN(ContinueStatement)
|
NOT_A_PATTERN(ContinueStatement)
|
||||||
NOT_A_PATTERN(CountOperation)
|
NOT_A_PATTERN(CountOperation)
|
||||||
|
@ -53,9 +53,8 @@ namespace internal {
|
|||||||
T(ARROW, "=>", 0) \
|
T(ARROW, "=>", 0) \
|
||||||
\
|
\
|
||||||
/* Assignment operators. */ \
|
/* Assignment operators. */ \
|
||||||
/* IsAssignmentOp() and Assignment::is_compound() relies on */ \
|
/* IsAssignmentOp() relies on this block of enum values being */ \
|
||||||
/* this block of enum values being contiguous and sorted in the */ \
|
/* contiguous and sorted in the same order! */ \
|
||||||
/* same order! */ \
|
|
||||||
T(INIT, "=init", 2) /* AST-use only. */ \
|
T(INIT, "=init", 2) /* AST-use only. */ \
|
||||||
T(ASSIGN, "=", 2) \
|
T(ASSIGN, "=", 2) \
|
||||||
T(ASSIGN_BIT_OR, "|=", 2) \
|
T(ASSIGN_BIT_OR, "|=", 2) \
|
||||||
@ -318,6 +317,36 @@ class Token {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value BinaryOpForAssignment(Value op) {
|
||||||
|
DCHECK(IsAssignmentOp(op));
|
||||||
|
switch (op) {
|
||||||
|
case Token::ASSIGN_BIT_OR:
|
||||||
|
return Token::BIT_OR;
|
||||||
|
case Token::ASSIGN_BIT_XOR:
|
||||||
|
return Token::BIT_XOR;
|
||||||
|
case Token::ASSIGN_BIT_AND:
|
||||||
|
return Token::BIT_AND;
|
||||||
|
case Token::ASSIGN_SHL:
|
||||||
|
return Token::SHL;
|
||||||
|
case Token::ASSIGN_SAR:
|
||||||
|
return Token::SAR;
|
||||||
|
case Token::ASSIGN_SHR:
|
||||||
|
return Token::SHR;
|
||||||
|
case Token::ASSIGN_ADD:
|
||||||
|
return Token::ADD;
|
||||||
|
case Token::ASSIGN_SUB:
|
||||||
|
return Token::SUB;
|
||||||
|
case Token::ASSIGN_MUL:
|
||||||
|
return Token::MUL;
|
||||||
|
case Token::ASSIGN_DIV:
|
||||||
|
return Token::DIV;
|
||||||
|
case Token::ASSIGN_MOD:
|
||||||
|
return Token::MOD;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsBitOp(Value op) {
|
static bool IsBitOp(Value op) {
|
||||||
return (BIT_OR <= op && op <= SHR) || op == BIT_NOT;
|
return (BIT_OR <= op && op <= SHR) || op == BIT_NOT;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user