[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);
|
||||
}
|
||||
|
||||
void AstExpressionRewriter::VisitCompoundAssignment(CompoundAssignment* node) {
|
||||
VisitAssignment(node);
|
||||
}
|
||||
|
||||
void AstExpressionRewriter::VisitYield(Yield* node) {
|
||||
REWRITE_THIS(node);
|
||||
AST_REWRITE_PROPERTY(Expression, node, expression);
|
||||
|
@ -313,12 +313,15 @@ void AstNumberingVisitor::VisitProperty(Property* node) {
|
||||
|
||||
|
||||
void AstNumberingVisitor::VisitAssignment(Assignment* node) {
|
||||
if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
|
||||
VisitReference(node->target());
|
||||
Visit(node->value());
|
||||
ReserveFeedbackSlots(node);
|
||||
}
|
||||
|
||||
void AstNumberingVisitor::VisitCompoundAssignment(CompoundAssignment* node) {
|
||||
VisitBinaryOperation(node->binary_operation());
|
||||
VisitAssignment(node);
|
||||
}
|
||||
|
||||
void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
|
||||
Visit(node->left());
|
||||
|
@ -359,6 +359,12 @@ void AstTraversalVisitor<Subclass>::VisitAssignment(Assignment* expr) {
|
||||
RECURSE_EXPRESSION(Visit(expr->value()));
|
||||
}
|
||||
|
||||
template <class Subclass>
|
||||
void AstTraversalVisitor<Subclass>::VisitCompoundAssignment(
|
||||
CompoundAssignment* expr) {
|
||||
VisitAssignment(expr);
|
||||
}
|
||||
|
||||
template <class Subclass>
|
||||
void AstTraversalVisitor<Subclass>::VisitYield(Yield* expr) {
|
||||
PROCESS_EXPRESSION(expr);
|
||||
|
@ -251,12 +251,9 @@ void ForInStatement::AssignFeedbackSlots(FeedbackVectorSpec* spec,
|
||||
for_in_feedback_slot_ = spec->AddGeneralSlot();
|
||||
}
|
||||
|
||||
Assignment::Assignment(Token::Value op, Expression* target, Expression* value,
|
||||
int pos)
|
||||
: Expression(pos, kAssignment),
|
||||
target_(target),
|
||||
value_(value),
|
||||
binary_operation_(NULL) {
|
||||
Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
|
||||
Expression* value, int pos)
|
||||
: Expression(pos, node_type), target_(target), value_(value) {
|
||||
bit_field_ |= IsUninitializedField::encode(false) |
|
||||
KeyTypeField::encode(ELEMENT) |
|
||||
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 {
|
||||
return scope()->ShouldEagerCompile();
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ namespace internal {
|
||||
|
||||
#define PROPERTY_NODE_LIST(V) \
|
||||
V(Assignment) \
|
||||
V(CompoundAssignment) \
|
||||
V(CountOperation) \
|
||||
V(Property)
|
||||
|
||||
@ -2099,13 +2100,8 @@ class Conditional final : public Expression {
|
||||
Expression* else_expression_;
|
||||
};
|
||||
|
||||
|
||||
class Assignment final : public Expression {
|
||||
class Assignment : public Expression {
|
||||
public:
|
||||
Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }
|
||||
|
||||
Token::Value binary_op() const;
|
||||
|
||||
Token::Value op() const { return TokenField::decode(bit_field_); }
|
||||
Expression* target() const { return target_; }
|
||||
Expression* value() const { return value_; }
|
||||
@ -2113,11 +2109,6 @@ class Assignment final : public Expression {
|
||||
void set_target(Expression* e) { target_ = 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.
|
||||
bool IsUninitialized() const {
|
||||
return IsUninitializedField::decode(bit_field_);
|
||||
@ -2157,11 +2148,13 @@ class Assignment final : public Expression {
|
||||
FeedbackSlotCache* cache);
|
||||
FeedbackSlot AssignmentSlot() const { return slot_; }
|
||||
|
||||
protected:
|
||||
Assignment(NodeType type, Token::Value op, Expression* target,
|
||||
Expression* value, int pos);
|
||||
|
||||
private:
|
||||
friend class AstNodeFactory;
|
||||
|
||||
Assignment(Token::Value op, Expression* target, Expression* value, int pos);
|
||||
|
||||
class IsUninitializedField
|
||||
: public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
|
||||
class KeyTypeField
|
||||
@ -2175,10 +2168,23 @@ class Assignment final : public Expression {
|
||||
FeedbackSlot slot_;
|
||||
Expression* target_;
|
||||
Expression* value_;
|
||||
BinaryOperation* binary_operation_;
|
||||
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
|
||||
// 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();
|
||||
}
|
||||
|
||||
Assignment* assign = new (zone_) Assignment(op, target, value, pos);
|
||||
if (assign->is_compound()) {
|
||||
assign->binary_operation_ =
|
||||
NewBinaryOperation(assign->binary_op(), target, value, pos + 1);
|
||||
if (op == Token::ASSIGN || op == Token::INIT) {
|
||||
return new (zone_)
|
||||
Assignment(AstNode::kAssignment, op, target, value, pos);
|
||||
} 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,
|
||||
|
@ -269,6 +269,10 @@ void CallPrinter::VisitAssignment(Assignment* node) {
|
||||
Find(node->value());
|
||||
}
|
||||
|
||||
void CallPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
|
||||
VisitAssignment(node);
|
||||
}
|
||||
|
||||
void CallPrinter::VisitYield(Yield* node) { Find(node->expression()); }
|
||||
|
||||
void CallPrinter::VisitYieldStar(YieldStar* node) { Find(node->expression()); }
|
||||
@ -1141,6 +1145,10 @@ void AstPrinter::VisitAssignment(Assignment* node) {
|
||||
Visit(node->value());
|
||||
}
|
||||
|
||||
void AstPrinter::VisitCompoundAssignment(CompoundAssignment* node) {
|
||||
VisitAssignment(node);
|
||||
}
|
||||
|
||||
void AstPrinter::VisitYield(Yield* node) {
|
||||
EmbeddedVector<char, 128> buf;
|
||||
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
|
||||
// the left-hand side value and performing a binary operation.
|
||||
if (expr->is_compound()) {
|
||||
if (expr->IsCompoundAssignment()) {
|
||||
switch (assign_type) {
|
||||
case VARIABLE: {
|
||||
VariableProxy* proxy = expr->target()->AsVariableProxy();
|
||||
@ -2519,17 +2519,17 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
FeedbackSlot slot = expr->binary_operation()->BinaryOperationFeedbackSlot();
|
||||
BinaryOperation* binop = expr->AsCompoundAssignment()->binary_operation();
|
||||
FeedbackSlot slot = binop->BinaryOperationFeedbackSlot();
|
||||
if (expr->value()->IsSmiLiteral()) {
|
||||
builder()->BinaryOperationSmiLiteral(
|
||||
expr->binary_op(), expr->value()->AsLiteral()->AsSmiLiteral(),
|
||||
binop->op(), expr->value()->AsLiteral()->AsSmiLiteral(),
|
||||
feedback_index(slot));
|
||||
} else {
|
||||
Register old_value = register_allocator()->NewRegister();
|
||||
builder()->StoreAccumulatorInRegister(old_value);
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
builder()->BinaryOperation(expr->binary_op(), old_value,
|
||||
feedback_index(slot));
|
||||
builder()->BinaryOperation(binop->op(), old_value, feedback_index(slot));
|
||||
}
|
||||
} else {
|
||||
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
|
||||
// accumulator. When the generator is resumed, the sent value is loaded in the
|
||||
// accumulator.
|
||||
|
@ -2458,7 +2458,7 @@ void Parser::AddArrowFunctionFormalParameters(
|
||||
Expression* initializer = nullptr;
|
||||
if (expr->IsAssignment()) {
|
||||
Assignment* assignment = expr->AsAssignment();
|
||||
DCHECK(!assignment->is_compound());
|
||||
DCHECK(!assignment->IsCompoundAssignment());
|
||||
initializer = assignment->value();
|
||||
expr = assignment->target();
|
||||
}
|
||||
|
@ -782,6 +782,7 @@ NOT_A_PATTERN(CallRuntime)
|
||||
NOT_A_PATTERN(CaseClause)
|
||||
NOT_A_PATTERN(ClassLiteral)
|
||||
NOT_A_PATTERN(CompareOperation)
|
||||
NOT_A_PATTERN(CompoundAssignment)
|
||||
NOT_A_PATTERN(Conditional)
|
||||
NOT_A_PATTERN(ContinueStatement)
|
||||
NOT_A_PATTERN(CountOperation)
|
||||
|
@ -53,9 +53,8 @@ namespace internal {
|
||||
T(ARROW, "=>", 0) \
|
||||
\
|
||||
/* Assignment operators. */ \
|
||||
/* IsAssignmentOp() and Assignment::is_compound() relies on */ \
|
||||
/* this block of enum values being contiguous and sorted in the */ \
|
||||
/* same order! */ \
|
||||
/* IsAssignmentOp() relies on this block of enum values being */ \
|
||||
/* contiguous and sorted in the same order! */ \
|
||||
T(INIT, "=init", 2) /* AST-use only. */ \
|
||||
T(ASSIGN, "=", 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) {
|
||||
return (BIT_OR <= op && op <= SHR) || op == BIT_NOT;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user