Commit f5dca8a0 authored by Adam Klein's avatar Adam Klein Committed by Commit Bot

[ast] Slim down Block by one pointer, moving labels_ storage to subclass

The vast majority of blocks we create in the parser have no associated
labels, so it seems silly to waste a pointer on labels_ for all such
blocks.

This is accomplished by delegating responsibility for labels storage to
each subclass of BreakableStatement, and then further-specializing Block
by creating a new subclass, LabeledBlock.

Bug: v8:6092
Change-Id: I88c824639254e5890b25a86cc156bfc4310bf2b1
Reviewed-on: https://chromium-review.googlesource.com/639063Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47689}
parent ea9e9d4e
......@@ -1080,5 +1080,20 @@ const char* CallRuntime::debug_name() {
#endif // DEBUG
}
#define RETURN_LABELS(NodeType) \
case k##NodeType: \
return static_cast<const NodeType*>(this)->labels();
ZoneList<const AstRawString*>* BreakableStatement::labels() const {
switch (node_type()) {
BREAKABLE_NODE_LIST(RETURN_LABELS)
ITERATION_NODE_LIST(RETURN_LABELS)
default:
UNREACHABLE();
}
}
#undef RETURN_LABELS
} // namespace internal
} // namespace v8
......@@ -326,9 +326,7 @@ class BreakableStatement : public Statement {
TARGET_FOR_NAMED_ONLY
};
// The labels associated with this statement. May be NULL;
// if it is != NULL, guaranteed to contain at least one entry.
ZoneList<const AstRawString*>* labels() const { return labels_; }
ZoneList<const AstRawString*>* labels() const;
// Testers.
bool is_target_for_anonymous() const {
......@@ -336,35 +334,27 @@ class BreakableStatement : public Statement {
}
private:
BreakableType breakableType() const {
return BreakableTypeField::decode(bit_field_);
}
ZoneList<const AstRawString*>* labels_;
class BreakableTypeField
: public BitField<BreakableType, Statement::kNextBitFieldIndex, 1> {};
protected:
BreakableStatement(ZoneList<const AstRawString*>* labels,
BreakableType breakable_type, int position, NodeType type)
: Statement(position, type),
labels_(labels) {
DCHECK(labels == NULL || labels->length() > 0);
BreakableStatement(BreakableType breakable_type, int position, NodeType type)
: Statement(position, type) {
bit_field_ |= BreakableTypeField::encode(breakable_type);
}
static const uint8_t kNextBitFieldIndex = BreakableTypeField::kNext;
};
class Block final : public BreakableStatement {
class Block : public BreakableStatement {
public:
ZoneList<Statement*>* statements() { return &statements_; }
bool ignore_completion_value() const {
return IgnoreCompletionField::decode(bit_field_);
}
inline ZoneList<const AstRawString*>* labels() const;
bool IsJump() const {
return !statements_.is_empty() && statements_.last()->IsJump()
&& labels() == NULL; // Good enough as an approximation...
......@@ -376,21 +366,47 @@ class Block final : public BreakableStatement {
private:
friend class AstNodeFactory;
ZoneList<Statement*> statements_;
Scope* scope_;
class IgnoreCompletionField
: public BitField<bool, BreakableStatement::kNextBitFieldIndex, 1> {};
class IsLabeledField
: public BitField<bool, IgnoreCompletionField::kNext, 1> {};
protected:
Block(Zone* zone, ZoneList<const AstRawString*>* labels, int capacity,
bool ignore_completion_value, int pos)
: BreakableStatement(labels, TARGET_FOR_NAMED_ONLY, pos, kBlock),
: BreakableStatement(TARGET_FOR_NAMED_ONLY, pos, kBlock),
statements_(capacity, zone),
scope_(NULL) {
bit_field_ |= IgnoreCompletionField::encode(ignore_completion_value);
bit_field_ |= IgnoreCompletionField::encode(ignore_completion_value) |
IsLabeledField::encode(labels != nullptr);
}
};
ZoneList<Statement*> statements_;
Scope* scope_;
class LabeledBlock final : public Block {
private:
friend class AstNodeFactory;
friend class Block;
class IgnoreCompletionField
: public BitField<bool, BreakableStatement::kNextBitFieldIndex, 1> {};
LabeledBlock(Zone* zone, ZoneList<const AstRawString*>* labels, int capacity,
bool ignore_completion_value, int pos)
: Block(zone, labels, capacity, ignore_completion_value, pos),
labels_(labels) {
DCHECK_NOT_NULL(labels);
DCHECK_GT(labels->length(), 0);
}
ZoneList<const AstRawString*>* labels_;
};
inline ZoneList<const AstRawString*>* Block::labels() const {
if (IsLabeledField::decode(bit_field_)) {
return static_cast<const LabeledBlock*>(this)->labels_;
}
return nullptr;
}
class DoExpression final : public Expression {
public:
......@@ -495,6 +511,8 @@ class IterationStatement : public BreakableStatement {
Statement* body() const { return body_; }
void set_body(Statement* s) { body_ = s; }
ZoneList<const AstRawString*>* labels() const { return labels_; }
int suspend_count() const { return suspend_count_; }
int first_suspend_id() const { return first_suspend_id_; }
void set_suspend_count(int suspend_count) { suspend_count_ = suspend_count; }
......@@ -511,7 +529,8 @@ class IterationStatement : public BreakableStatement {
protected:
IterationStatement(ZoneList<const AstRawString*>* labels, int pos,
NodeType type)
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS, pos, type),
: BreakableStatement(TARGET_FOR_ANONYMOUS, pos, type),
labels_(labels),
osr_id_(BailoutId::None()),
body_(NULL),
suspend_count_(0),
......@@ -522,6 +541,7 @@ class IterationStatement : public BreakableStatement {
BreakableStatement::kNextBitFieldIndex;
private:
ZoneList<const AstRawString*>* labels_;
BailoutId osr_id_;
Statement* body_;
int suspend_count_;
......@@ -877,6 +897,7 @@ class SwitchStatement final : public BreakableStatement {
cases_ = cases;
}
ZoneList<const AstRawString*>* labels() const { return labels_; }
Expression* tag() const { return tag_; }
ZoneList<CaseClause*>* cases() const { return cases_; }
......@@ -886,10 +907,12 @@ class SwitchStatement final : public BreakableStatement {
friend class AstNodeFactory;
SwitchStatement(ZoneList<const AstRawString*>* labels, int pos)
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS, pos, kSwitchStatement),
: BreakableStatement(TARGET_FOR_ANONYMOUS, pos, kSwitchStatement),
labels_(labels),
tag_(NULL),
cases_(NULL) {}
ZoneList<const AstRawString*>* labels_;
Expression* tag_;
ZoneList<CaseClause*>* cases_;
};
......@@ -3148,8 +3171,11 @@ class AstNodeFactory final BASE_EMBEDDED {
Block* NewBlock(ZoneList<const AstRawString*>* labels, int capacity,
bool ignore_completion_value, int pos) {
return new (zone_)
Block(zone_, labels, capacity, ignore_completion_value, pos);
return labels != nullptr ? new (zone_)
LabeledBlock(zone_, labels, capacity,
ignore_completion_value, pos)
: new (zone_) Block(zone_, labels, capacity,
ignore_completion_value, pos);
}
#define STATEMENT_WITH_LABELS(NodeType) \
......
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