1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_AST_AST_H_
6 #define V8_AST_AST_H_
7
8 #include "src/ast/ast-types.h"
9 #include "src/ast/ast-value-factory.h"
10 #include "src/ast/modules.h"
11 #include "src/ast/variables.h"
12 #include "src/bailout-reason.h"
13 #include "src/base/flags.h"
14 #include "src/factory.h"
15 #include "src/globals.h"
16 #include "src/isolate.h"
17 #include "src/label.h"
18 #include "src/list.h"
19 #include "src/objects/literal-objects.h"
20 #include "src/parsing/token.h"
21 #include "src/runtime/runtime.h"
22 #include "src/small-pointer-list.h"
23
24 namespace v8 {
25 namespace internal {
26
27 // The abstract syntax tree is an intermediate, light-weight
28 // representation of the parsed JavaScript code suitable for
29 // compilation to native code.
30
31 // Nodes are allocated in a separate zone, which allows faster
32 // allocation and constant-time deallocation of the entire syntax
33 // tree.
34
35
36 // ----------------------------------------------------------------------------
37 // Nodes of the abstract syntax tree. Only concrete classes are
38 // enumerated here.
39
40 #define DECLARATION_NODE_LIST(V) \
41 V(VariableDeclaration) \
42 V(FunctionDeclaration)
43
44 #define ITERATION_NODE_LIST(V) \
45 V(DoWhileStatement) \
46 V(WhileStatement) \
47 V(ForStatement) \
48 V(ForInStatement) \
49 V(ForOfStatement)
50
51 #define BREAKABLE_NODE_LIST(V) \
52 V(Block) \
53 V(SwitchStatement)
54
55 #define STATEMENT_NODE_LIST(V) \
56 ITERATION_NODE_LIST(V) \
57 BREAKABLE_NODE_LIST(V) \
58 V(ExpressionStatement) \
59 V(EmptyStatement) \
60 V(SloppyBlockFunctionStatement) \
61 V(IfStatement) \
62 V(ContinueStatement) \
63 V(BreakStatement) \
64 V(ReturnStatement) \
65 V(WithStatement) \
66 V(TryCatchStatement) \
67 V(TryFinallyStatement) \
68 V(DebuggerStatement)
69
70 #define LITERAL_NODE_LIST(V) \
71 V(RegExpLiteral) \
72 V(ObjectLiteral) \
73 V(ArrayLiteral)
74
75 #define PROPERTY_NODE_LIST(V) \
76 V(Assignment) \
77 V(CountOperation) \
78 V(Property)
79
80 #define CALL_NODE_LIST(V) \
81 V(Call) \
82 V(CallNew)
83
84 #define EXPRESSION_NODE_LIST(V) \
85 LITERAL_NODE_LIST(V) \
86 PROPERTY_NODE_LIST(V) \
87 CALL_NODE_LIST(V) \
88 V(FunctionLiteral) \
89 V(ClassLiteral) \
90 V(NativeFunctionLiteral) \
91 V(Conditional) \
92 V(VariableProxy) \
93 V(Literal) \
94 V(Yield) \
95 V(Throw) \
96 V(CallRuntime) \
97 V(UnaryOperation) \
98 V(BinaryOperation) \
99 V(CompareOperation) \
100 V(Spread) \
101 V(ThisFunction) \
102 V(SuperPropertyReference) \
103 V(SuperCallReference) \
104 V(CaseClause) \
105 V(EmptyParentheses) \
106 V(GetIterator) \
107 V(DoExpression) \
108 V(RewritableExpression)
109
110 #define AST_NODE_LIST(V) \
111 DECLARATION_NODE_LIST(V) \
112 STATEMENT_NODE_LIST(V) \
113 EXPRESSION_NODE_LIST(V)
114
115 // Forward declarations
116 class AstNodeFactory;
117 class Declaration;
118 class Module;
119 class BreakableStatement;
120 class Expression;
121 class IterationStatement;
122 class MaterializedLiteral;
123 class Statement;
124 class TypeFeedbackOracle;
125
126 #define DEF_FORWARD_DECLARATION(type) class type;
AST_NODE_LIST(DEF_FORWARD_DECLARATION)127 AST_NODE_LIST(DEF_FORWARD_DECLARATION)
128 #undef DEF_FORWARD_DECLARATION
129
130 class FeedbackSlotCache {
131 public:
132 typedef std::pair<TypeofMode, Variable*> Key;
133
134 explicit FeedbackSlotCache(Zone* zone) : map_(zone) {}
135
136 void Put(TypeofMode typeof_mode, Variable* variable, FeedbackSlot slot) {
137 Key key = std::make_pair(typeof_mode, variable);
138 auto entry = std::make_pair(key, slot);
139 map_.insert(entry);
140 }
141
142 FeedbackSlot Get(TypeofMode typeof_mode, Variable* variable) const {
143 Key key = std::make_pair(typeof_mode, variable);
144 auto iter = map_.find(key);
145 if (iter != map_.end()) {
146 return iter->second;
147 }
148 return FeedbackSlot();
149 }
150
151 private:
152 ZoneMap<Key, FeedbackSlot> map_;
153 };
154
155
156 class AstProperties final BASE_EMBEDDED {
157 public:
158 enum Flag {
159 kNoFlags = 0,
160 kDontSelfOptimize = 1 << 0,
161 kMustUseIgnitionTurbo = 1 << 1
162 };
163
164 typedef base::Flags<Flag> Flags;
165
AstProperties(Zone * zone)166 explicit AstProperties(Zone* zone) : node_count_(0), spec_(zone) {}
167
flags()168 Flags& flags() { return flags_; }
flags()169 Flags flags() const { return flags_; }
node_count()170 int node_count() { return node_count_; }
add_node_count(int count)171 void add_node_count(int count) { node_count_ += count; }
172
get_spec()173 const FeedbackVectorSpec* get_spec() const { return &spec_; }
get_spec()174 FeedbackVectorSpec* get_spec() { return &spec_; }
175
176 private:
177 Flags flags_;
178 int node_count_;
179 FeedbackVectorSpec spec_;
180 };
181
DEFINE_OPERATORS_FOR_FLAGS(AstProperties::Flags)182 DEFINE_OPERATORS_FOR_FLAGS(AstProperties::Flags)
183
184
185 class AstNode: public ZoneObject {
186 public:
187 #define DECLARE_TYPE_ENUM(type) k##type,
188 enum NodeType : uint8_t { AST_NODE_LIST(DECLARE_TYPE_ENUM) };
189 #undef DECLARE_TYPE_ENUM
190
191 void* operator new(size_t size, Zone* zone) { return zone->New(size); }
192
193 NodeType node_type() const { return NodeTypeField::decode(bit_field_); }
194 int position() const { return position_; }
195
196 #ifdef DEBUG
197 void Print();
198 void Print(Isolate* isolate);
199 #endif // DEBUG
200
201 // Type testing & conversion functions overridden by concrete subclasses.
202 #define DECLARE_NODE_FUNCTIONS(type) \
203 V8_INLINE bool Is##type() const; \
204 V8_INLINE type* As##type(); \
205 V8_INLINE const type* As##type() const;
206 AST_NODE_LIST(DECLARE_NODE_FUNCTIONS)
207 #undef DECLARE_NODE_FUNCTIONS
208
209 BreakableStatement* AsBreakableStatement();
210 IterationStatement* AsIterationStatement();
211 MaterializedLiteral* AsMaterializedLiteral();
212
213 private:
214 // Hidden to prevent accidental usage. It would have to load the
215 // current zone from the TLS.
216 void* operator new(size_t size);
217
218 int position_;
219 class NodeTypeField : public BitField<NodeType, 0, 6> {};
220
221 protected:
222 uint32_t bit_field_;
223 static const uint8_t kNextBitFieldIndex = NodeTypeField::kNext;
224
225 AstNode(int position, NodeType type)
226 : position_(position), bit_field_(NodeTypeField::encode(type)) {}
227 };
228
229
230 class Statement : public AstNode {
231 public:
IsEmpty()232 bool IsEmpty() { return AsEmptyStatement() != NULL; }
233 bool IsJump() const;
234
235 protected:
Statement(int position,NodeType type)236 Statement(int position, NodeType type) : AstNode(position, type) {}
237
238 static const uint8_t kNextBitFieldIndex = AstNode::kNextBitFieldIndex;
239 };
240
241
242 class SmallMapList final {
243 public:
SmallMapList()244 SmallMapList() {}
SmallMapList(int capacity,Zone * zone)245 SmallMapList(int capacity, Zone* zone) : list_(capacity, zone) {}
246
Reserve(int capacity,Zone * zone)247 void Reserve(int capacity, Zone* zone) { list_.Reserve(capacity, zone); }
Clear()248 void Clear() { list_.Clear(); }
Sort()249 void Sort() { list_.Sort(); }
250
is_empty()251 bool is_empty() const { return list_.is_empty(); }
length()252 int length() const { return list_.length(); }
253
AddMapIfMissing(Handle<Map> map,Zone * zone)254 void AddMapIfMissing(Handle<Map> map, Zone* zone) {
255 if (!Map::TryUpdate(map).ToHandle(&map)) return;
256 for (int i = 0; i < length(); ++i) {
257 if (at(i).is_identical_to(map)) return;
258 }
259 Add(map, zone);
260 }
261
FilterForPossibleTransitions(Map * root_map)262 void FilterForPossibleTransitions(Map* root_map) {
263 for (int i = list_.length() - 1; i >= 0; i--) {
264 if (at(i)->FindRootMap() != root_map) {
265 list_.RemoveElement(list_.at(i));
266 }
267 }
268 }
269
Add(Handle<Map> handle,Zone * zone)270 void Add(Handle<Map> handle, Zone* zone) {
271 list_.Add(handle.location(), zone);
272 }
273
at(int i)274 Handle<Map> at(int i) const {
275 return Handle<Map>(list_.at(i));
276 }
277
first()278 Handle<Map> first() const { return at(0); }
last()279 Handle<Map> last() const { return at(length() - 1); }
280
281 private:
282 // The list stores pointers to Map*, that is Map**, so it's GC safe.
283 SmallPointerList<Map*> list_;
284
285 DISALLOW_COPY_AND_ASSIGN(SmallMapList);
286 };
287
288
289 class Expression : public AstNode {
290 public:
291 enum Context {
292 // Not assigned a context yet, or else will not be visited during
293 // code generation.
294 kUninitialized,
295 // Evaluated for its side effects.
296 kEffect,
297 // Evaluated for its value (and side effects).
298 kValue,
299 // Evaluated for control flow (and side effects).
300 kTest
301 };
302
303 // Mark this expression as being in tail position.
304 void MarkTail();
305
306 // True iff the expression is a valid reference expression.
307 bool IsValidReferenceExpression() const;
308
309 // Helpers for ToBoolean conversion.
310 bool ToBooleanIsTrue() const;
311 bool ToBooleanIsFalse() const;
312
313 // Symbols that cannot be parsed as array indices are considered property
314 // names. We do not treat symbols that can be array indexes as property
315 // names because [] for string objects is handled only by keyed ICs.
316 bool IsPropertyName() const;
317
318 // True iff the expression is a class or function expression without
319 // a syntactic name.
320 bool IsAnonymousFunctionDefinition() const;
321
322 // True iff the expression is a literal represented as a smi.
323 bool IsSmiLiteral() const;
324
325 // True iff the expression is a literal represented as a number.
326 bool IsNumberLiteral() const;
327
328 // True iff the expression is a string literal.
329 bool IsStringLiteral() const;
330
331 // True iff the expression is the null literal.
332 bool IsNullLiteral() const;
333
334 // True if we can prove that the expression is the undefined literal. Note
335 // that this also checks for loads of the global "undefined" variable.
336 bool IsUndefinedLiteral() const;
337
338 // True iff the expression is a valid target for an assignment.
339 bool IsValidReferenceExpressionOrThis() const;
340
341 // TODO(rossberg): this should move to its own AST node eventually.
342 void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
to_boolean_types()343 uint16_t to_boolean_types() const {
344 return ToBooleanTypesField::decode(bit_field_);
345 }
346
347 SmallMapList* GetReceiverTypes();
348 KeyedAccessStoreMode GetStoreMode() const;
349 IcCheckType GetKeyType() const;
350 bool IsMonomorphic() const;
351
set_base_id(int id)352 void set_base_id(int id) { base_id_ = id; }
num_ids()353 static int num_ids() { return parent_num_ids() + 2; }
id()354 BailoutId id() const { return BailoutId(local_id(0)); }
test_id()355 TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); }
356
357 private:
local_id(int n)358 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
359
360 int base_id_;
361 class ToBooleanTypesField
362 : public BitField<uint16_t, AstNode::kNextBitFieldIndex, 9> {};
363
364 protected:
Expression(int pos,NodeType type)365 Expression(int pos, NodeType type)
366 : AstNode(pos, type), base_id_(BailoutId::None().ToInt()) {
367 bit_field_ = ToBooleanTypesField::update(bit_field_, 0);
368 }
369
parent_num_ids()370 static int parent_num_ids() { return 0; }
set_to_boolean_types(uint16_t types)371 void set_to_boolean_types(uint16_t types) {
372 bit_field_ = ToBooleanTypesField::update(bit_field_, types);
373 }
base_id()374 int base_id() const {
375 DCHECK(!BailoutId(base_id_).IsNone());
376 return base_id_;
377 }
378
379 static const uint8_t kNextBitFieldIndex = ToBooleanTypesField::kNext;
380 };
381
382
383 class BreakableStatement : public Statement {
384 public:
385 enum BreakableType {
386 TARGET_FOR_ANONYMOUS,
387 TARGET_FOR_NAMED_ONLY
388 };
389
390 // The labels associated with this statement. May be NULL;
391 // if it is != NULL, guaranteed to contain at least one entry.
labels()392 ZoneList<const AstRawString*>* labels() const { return labels_; }
393
394 // Code generation
break_target()395 Label* break_target() { return &break_target_; }
396
397 // Testers.
is_target_for_anonymous()398 bool is_target_for_anonymous() const {
399 return BreakableTypeField::decode(bit_field_) == TARGET_FOR_ANONYMOUS;
400 }
401
set_base_id(int id)402 void set_base_id(int id) { base_id_ = id; }
num_ids()403 static int num_ids() { return parent_num_ids() + 2; }
EntryId()404 BailoutId EntryId() const { return BailoutId(local_id(0)); }
ExitId()405 BailoutId ExitId() const { return BailoutId(local_id(1)); }
406
407 private:
local_id(int n)408 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
409
breakableType()410 BreakableType breakableType() const {
411 return BreakableTypeField::decode(bit_field_);
412 }
413
414 int base_id_;
415 Label break_target_;
416 ZoneList<const AstRawString*>* labels_;
417
418 class BreakableTypeField
419 : public BitField<BreakableType, Statement::kNextBitFieldIndex, 1> {};
420
421 protected:
BreakableStatement(ZoneList<const AstRawString * > * labels,BreakableType breakable_type,int position,NodeType type)422 BreakableStatement(ZoneList<const AstRawString*>* labels,
423 BreakableType breakable_type, int position, NodeType type)
424 : Statement(position, type),
425 base_id_(BailoutId::None().ToInt()),
426 labels_(labels) {
427 DCHECK(labels == NULL || labels->length() > 0);
428 bit_field_ |= BreakableTypeField::encode(breakable_type);
429 }
parent_num_ids()430 static int parent_num_ids() { return 0; }
431
base_id()432 int base_id() const {
433 DCHECK(!BailoutId(base_id_).IsNone());
434 return base_id_;
435 }
436
437 static const uint8_t kNextBitFieldIndex = BreakableTypeField::kNext;
438 };
439
440
441 class Block final : public BreakableStatement {
442 public:
statements()443 ZoneList<Statement*>* statements() { return &statements_; }
ignore_completion_value()444 bool ignore_completion_value() const {
445 return IgnoreCompletionField::decode(bit_field_);
446 }
447
num_ids()448 static int num_ids() { return parent_num_ids() + 1; }
DeclsId()449 BailoutId DeclsId() const { return BailoutId(local_id(0)); }
450
IsJump()451 bool IsJump() const {
452 return !statements_.is_empty() && statements_.last()->IsJump()
453 && labels() == NULL; // Good enough as an approximation...
454 }
455
scope()456 Scope* scope() const { return scope_; }
set_scope(Scope * scope)457 void set_scope(Scope* scope) { scope_ = scope; }
458
459 private:
460 friend class AstNodeFactory;
461
Block(Zone * zone,ZoneList<const AstRawString * > * labels,int capacity,bool ignore_completion_value,int pos)462 Block(Zone* zone, ZoneList<const AstRawString*>* labels, int capacity,
463 bool ignore_completion_value, int pos)
464 : BreakableStatement(labels, TARGET_FOR_NAMED_ONLY, pos, kBlock),
465 statements_(capacity, zone),
466 scope_(NULL) {
467 bit_field_ |= IgnoreCompletionField::encode(ignore_completion_value);
468 }
parent_num_ids()469 static int parent_num_ids() { return BreakableStatement::num_ids(); }
local_id(int n)470 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
471
472 ZoneList<Statement*> statements_;
473 Scope* scope_;
474
475 class IgnoreCompletionField
476 : public BitField<bool, BreakableStatement::kNextBitFieldIndex, 1> {};
477 };
478
479
480 class DoExpression final : public Expression {
481 public:
block()482 Block* block() { return block_; }
set_block(Block * b)483 void set_block(Block* b) { block_ = b; }
result()484 VariableProxy* result() { return result_; }
set_result(VariableProxy * v)485 void set_result(VariableProxy* v) { result_ = v; }
represented_function()486 FunctionLiteral* represented_function() { return represented_function_; }
set_represented_function(FunctionLiteral * f)487 void set_represented_function(FunctionLiteral* f) {
488 represented_function_ = f;
489 }
490 bool IsAnonymousFunctionDefinition() const;
491
492 private:
493 friend class AstNodeFactory;
494
DoExpression(Block * block,VariableProxy * result,int pos)495 DoExpression(Block* block, VariableProxy* result, int pos)
496 : Expression(pos, kDoExpression),
497 block_(block),
498 result_(result),
499 represented_function_(nullptr) {
500 DCHECK_NOT_NULL(block_);
501 DCHECK_NOT_NULL(result_);
502 }
parent_num_ids()503 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)504 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
505
506 Block* block_;
507 VariableProxy* result_;
508 FunctionLiteral* represented_function_;
509 };
510
511
512 class Declaration : public AstNode {
513 public:
514 typedef ThreadedList<Declaration> List;
515
proxy()516 VariableProxy* proxy() const { return proxy_; }
scope()517 Scope* scope() const { return scope_; }
518
519 protected:
Declaration(VariableProxy * proxy,Scope * scope,int pos,NodeType type)520 Declaration(VariableProxy* proxy, Scope* scope, int pos, NodeType type)
521 : AstNode(pos, type), proxy_(proxy), scope_(scope), next_(nullptr) {}
522
523 private:
524 VariableProxy* proxy_;
525 // Nested scope from which the declaration originated.
526 Scope* scope_;
527 // Declarations list threaded through the declarations.
next()528 Declaration** next() { return &next_; }
529 Declaration* next_;
530 friend List;
531 };
532
533
534 class VariableDeclaration final : public Declaration {
535 private:
536 friend class AstNodeFactory;
537
VariableDeclaration(VariableProxy * proxy,Scope * scope,int pos)538 VariableDeclaration(VariableProxy* proxy, Scope* scope, int pos)
539 : Declaration(proxy, scope, pos, kVariableDeclaration) {}
540 };
541
542
543 class FunctionDeclaration final : public Declaration {
544 public:
fun()545 FunctionLiteral* fun() const { return fun_; }
set_fun(FunctionLiteral * f)546 void set_fun(FunctionLiteral* f) { fun_ = f; }
547
548 private:
549 friend class AstNodeFactory;
550
FunctionDeclaration(VariableProxy * proxy,FunctionLiteral * fun,Scope * scope,int pos)551 FunctionDeclaration(VariableProxy* proxy, FunctionLiteral* fun, Scope* scope,
552 int pos)
553 : Declaration(proxy, scope, pos, kFunctionDeclaration), fun_(fun) {
554 DCHECK(fun != NULL);
555 }
556
557 FunctionLiteral* fun_;
558 };
559
560
561 class IterationStatement : public BreakableStatement {
562 public:
body()563 Statement* body() const { return body_; }
set_body(Statement * s)564 void set_body(Statement* s) { body_ = s; }
565
yield_count()566 int yield_count() const { return yield_count_; }
first_yield_id()567 int first_yield_id() const { return first_yield_id_; }
set_yield_count(int yield_count)568 void set_yield_count(int yield_count) { yield_count_ = yield_count; }
set_first_yield_id(int first_yield_id)569 void set_first_yield_id(int first_yield_id) {
570 first_yield_id_ = first_yield_id;
571 }
572
num_ids()573 static int num_ids() { return parent_num_ids() + 1; }
OsrEntryId()574 BailoutId OsrEntryId() const { return BailoutId(local_id(0)); }
575
576 // Code generation
continue_target()577 Label* continue_target() { return &continue_target_; }
578
579 protected:
IterationStatement(ZoneList<const AstRawString * > * labels,int pos,NodeType type)580 IterationStatement(ZoneList<const AstRawString*>* labels, int pos,
581 NodeType type)
582 : BreakableStatement(labels, TARGET_FOR_ANONYMOUS, pos, type),
583 body_(NULL),
584 yield_count_(0),
585 first_yield_id_(0) {}
parent_num_ids()586 static int parent_num_ids() { return BreakableStatement::num_ids(); }
Initialize(Statement * body)587 void Initialize(Statement* body) { body_ = body; }
588
589 static const uint8_t kNextBitFieldIndex =
590 BreakableStatement::kNextBitFieldIndex;
591
592 private:
local_id(int n)593 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
594
595 Statement* body_;
596 Label continue_target_;
597 int yield_count_;
598 int first_yield_id_;
599 };
600
601
602 class DoWhileStatement final : public IterationStatement {
603 public:
Initialize(Expression * cond,Statement * body)604 void Initialize(Expression* cond, Statement* body) {
605 IterationStatement::Initialize(body);
606 cond_ = cond;
607 }
608
cond()609 Expression* cond() const { return cond_; }
set_cond(Expression * e)610 void set_cond(Expression* e) { cond_ = e; }
611
num_ids()612 static int num_ids() { return parent_num_ids() + 2; }
ContinueId()613 BailoutId ContinueId() const { return BailoutId(local_id(0)); }
StackCheckId()614 BailoutId StackCheckId() const { return BackEdgeId(); }
BackEdgeId()615 BailoutId BackEdgeId() const { return BailoutId(local_id(1)); }
616
617 private:
618 friend class AstNodeFactory;
619
DoWhileStatement(ZoneList<const AstRawString * > * labels,int pos)620 DoWhileStatement(ZoneList<const AstRawString*>* labels, int pos)
621 : IterationStatement(labels, pos, kDoWhileStatement), cond_(NULL) {}
parent_num_ids()622 static int parent_num_ids() { return IterationStatement::num_ids(); }
local_id(int n)623 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
624
625 Expression* cond_;
626 };
627
628
629 class WhileStatement final : public IterationStatement {
630 public:
Initialize(Expression * cond,Statement * body)631 void Initialize(Expression* cond, Statement* body) {
632 IterationStatement::Initialize(body);
633 cond_ = cond;
634 }
635
cond()636 Expression* cond() const { return cond_; }
set_cond(Expression * e)637 void set_cond(Expression* e) { cond_ = e; }
638
num_ids()639 static int num_ids() { return parent_num_ids() + 1; }
ContinueId()640 BailoutId ContinueId() const { return EntryId(); }
StackCheckId()641 BailoutId StackCheckId() const { return BodyId(); }
BodyId()642 BailoutId BodyId() const { return BailoutId(local_id(0)); }
643
644 private:
645 friend class AstNodeFactory;
646
WhileStatement(ZoneList<const AstRawString * > * labels,int pos)647 WhileStatement(ZoneList<const AstRawString*>* labels, int pos)
648 : IterationStatement(labels, pos, kWhileStatement), cond_(NULL) {}
parent_num_ids()649 static int parent_num_ids() { return IterationStatement::num_ids(); }
local_id(int n)650 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
651
652 Expression* cond_;
653 };
654
655
656 class ForStatement final : public IterationStatement {
657 public:
Initialize(Statement * init,Expression * cond,Statement * next,Statement * body)658 void Initialize(Statement* init,
659 Expression* cond,
660 Statement* next,
661 Statement* body) {
662 IterationStatement::Initialize(body);
663 init_ = init;
664 cond_ = cond;
665 next_ = next;
666 }
667
init()668 Statement* init() const { return init_; }
cond()669 Expression* cond() const { return cond_; }
next()670 Statement* next() const { return next_; }
671
set_init(Statement * s)672 void set_init(Statement* s) { init_ = s; }
set_cond(Expression * e)673 void set_cond(Expression* e) { cond_ = e; }
set_next(Statement * s)674 void set_next(Statement* s) { next_ = s; }
675
num_ids()676 static int num_ids() { return parent_num_ids() + 2; }
ContinueId()677 BailoutId ContinueId() const { return BailoutId(local_id(0)); }
StackCheckId()678 BailoutId StackCheckId() const { return BodyId(); }
BodyId()679 BailoutId BodyId() const { return BailoutId(local_id(1)); }
680
681 private:
682 friend class AstNodeFactory;
683
ForStatement(ZoneList<const AstRawString * > * labels,int pos)684 ForStatement(ZoneList<const AstRawString*>* labels, int pos)
685 : IterationStatement(labels, pos, kForStatement),
686 init_(NULL),
687 cond_(NULL),
688 next_(NULL) {}
parent_num_ids()689 static int parent_num_ids() { return IterationStatement::num_ids(); }
local_id(int n)690 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
691
692 Statement* init_;
693 Expression* cond_;
694 Statement* next_;
695 };
696
697
698 class ForEachStatement : public IterationStatement {
699 public:
700 enum VisitMode {
701 ENUMERATE, // for (each in subject) body;
702 ITERATE // for (each of subject) body;
703 };
704
705 using IterationStatement::Initialize;
706
VisitModeString(VisitMode mode)707 static const char* VisitModeString(VisitMode mode) {
708 return mode == ITERATE ? "for-of" : "for-in";
709 }
710
711 protected:
ForEachStatement(ZoneList<const AstRawString * > * labels,int pos,NodeType type)712 ForEachStatement(ZoneList<const AstRawString*>* labels, int pos,
713 NodeType type)
714 : IterationStatement(labels, pos, type) {}
715 };
716
717
718 class ForInStatement final : public ForEachStatement {
719 public:
Initialize(Expression * each,Expression * subject,Statement * body)720 void Initialize(Expression* each, Expression* subject, Statement* body) {
721 ForEachStatement::Initialize(body);
722 each_ = each;
723 subject_ = subject;
724 }
725
enumerable()726 Expression* enumerable() const {
727 return subject();
728 }
729
each()730 Expression* each() const { return each_; }
subject()731 Expression* subject() const { return subject_; }
732
set_each(Expression * e)733 void set_each(Expression* e) { each_ = e; }
set_subject(Expression * e)734 void set_subject(Expression* e) { subject_ = e; }
735
736 // Type feedback information.
737 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
738 FeedbackSlotCache* cache);
EachFeedbackSlot()739 FeedbackSlot EachFeedbackSlot() const { return each_slot_; }
ForInFeedbackSlot()740 FeedbackSlot ForInFeedbackSlot() {
741 DCHECK(!for_in_feedback_slot_.IsInvalid());
742 return for_in_feedback_slot_;
743 }
744
745 enum ForInType { FAST_FOR_IN, SLOW_FOR_IN };
for_in_type()746 ForInType for_in_type() const { return ForInTypeField::decode(bit_field_); }
set_for_in_type(ForInType type)747 void set_for_in_type(ForInType type) {
748 bit_field_ = ForInTypeField::update(bit_field_, type);
749 }
750
num_ids()751 static int num_ids() { return parent_num_ids() + 7; }
BodyId()752 BailoutId BodyId() const { return BailoutId(local_id(0)); }
EnumId()753 BailoutId EnumId() const { return BailoutId(local_id(1)); }
ToObjectId()754 BailoutId ToObjectId() const { return BailoutId(local_id(2)); }
PrepareId()755 BailoutId PrepareId() const { return BailoutId(local_id(3)); }
FilterId()756 BailoutId FilterId() const { return BailoutId(local_id(4)); }
AssignmentId()757 BailoutId AssignmentId() const { return BailoutId(local_id(5)); }
IncrementId()758 BailoutId IncrementId() const { return BailoutId(local_id(6)); }
StackCheckId()759 BailoutId StackCheckId() const { return BodyId(); }
760
761 private:
762 friend class AstNodeFactory;
763
ForInStatement(ZoneList<const AstRawString * > * labels,int pos)764 ForInStatement(ZoneList<const AstRawString*>* labels, int pos)
765 : ForEachStatement(labels, pos, kForInStatement),
766 each_(nullptr),
767 subject_(nullptr) {
768 bit_field_ = ForInTypeField::update(bit_field_, SLOW_FOR_IN);
769 }
770
parent_num_ids()771 static int parent_num_ids() { return ForEachStatement::num_ids(); }
local_id(int n)772 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
773
774 Expression* each_;
775 Expression* subject_;
776 FeedbackSlot each_slot_;
777 FeedbackSlot for_in_feedback_slot_;
778
779 class ForInTypeField
780 : public BitField<ForInType, ForEachStatement::kNextBitFieldIndex, 1> {};
781 };
782
783
784 class ForOfStatement final : public ForEachStatement {
785 public:
Initialize(Statement * body,Variable * iterator,Expression * assign_iterator,Expression * next_result,Expression * result_done,Expression * assign_each)786 void Initialize(Statement* body, Variable* iterator,
787 Expression* assign_iterator, Expression* next_result,
788 Expression* result_done, Expression* assign_each) {
789 ForEachStatement::Initialize(body);
790 iterator_ = iterator;
791 assign_iterator_ = assign_iterator;
792 next_result_ = next_result;
793 result_done_ = result_done;
794 assign_each_ = assign_each;
795 }
796
iterator()797 Variable* iterator() const {
798 return iterator_;
799 }
800
801 // iterator = subject[Symbol.iterator]()
assign_iterator()802 Expression* assign_iterator() const {
803 return assign_iterator_;
804 }
805
806 // result = iterator.next() // with type check
next_result()807 Expression* next_result() const {
808 return next_result_;
809 }
810
811 // result.done
result_done()812 Expression* result_done() const {
813 return result_done_;
814 }
815
816 // each = result.value
assign_each()817 Expression* assign_each() const {
818 return assign_each_;
819 }
820
set_assign_iterator(Expression * e)821 void set_assign_iterator(Expression* e) { assign_iterator_ = e; }
set_next_result(Expression * e)822 void set_next_result(Expression* e) { next_result_ = e; }
set_result_done(Expression * e)823 void set_result_done(Expression* e) { result_done_ = e; }
set_assign_each(Expression * e)824 void set_assign_each(Expression* e) { assign_each_ = e; }
825
826 private:
827 friend class AstNodeFactory;
828
ForOfStatement(ZoneList<const AstRawString * > * labels,int pos)829 ForOfStatement(ZoneList<const AstRawString*>* labels, int pos)
830 : ForEachStatement(labels, pos, kForOfStatement),
831 iterator_(NULL),
832 assign_iterator_(NULL),
833 next_result_(NULL),
834 result_done_(NULL),
835 assign_each_(NULL) {}
836
837 Variable* iterator_;
838 Expression* assign_iterator_;
839 Expression* next_result_;
840 Expression* result_done_;
841 Expression* assign_each_;
842 };
843
844
845 class ExpressionStatement final : public Statement {
846 public:
set_expression(Expression * e)847 void set_expression(Expression* e) { expression_ = e; }
expression()848 Expression* expression() const { return expression_; }
IsJump()849 bool IsJump() const { return expression_->IsThrow(); }
850
851 private:
852 friend class AstNodeFactory;
853
ExpressionStatement(Expression * expression,int pos)854 ExpressionStatement(Expression* expression, int pos)
855 : Statement(pos, kExpressionStatement), expression_(expression) {}
856
857 Expression* expression_;
858 };
859
860
861 class JumpStatement : public Statement {
862 public:
IsJump()863 bool IsJump() const { return true; }
864
865 protected:
JumpStatement(int pos,NodeType type)866 JumpStatement(int pos, NodeType type) : Statement(pos, type) {}
867 };
868
869
870 class ContinueStatement final : public JumpStatement {
871 public:
target()872 IterationStatement* target() const { return target_; }
873
874 private:
875 friend class AstNodeFactory;
876
ContinueStatement(IterationStatement * target,int pos)877 ContinueStatement(IterationStatement* target, int pos)
878 : JumpStatement(pos, kContinueStatement), target_(target) {}
879
880 IterationStatement* target_;
881 };
882
883
884 class BreakStatement final : public JumpStatement {
885 public:
target()886 BreakableStatement* target() const { return target_; }
887
888 private:
889 friend class AstNodeFactory;
890
BreakStatement(BreakableStatement * target,int pos)891 BreakStatement(BreakableStatement* target, int pos)
892 : JumpStatement(pos, kBreakStatement), target_(target) {}
893
894 BreakableStatement* target_;
895 };
896
897
898 class ReturnStatement final : public JumpStatement {
899 public:
900 enum Type { kNormal, kAsyncReturn };
expression()901 Expression* expression() const { return expression_; }
902
set_expression(Expression * e)903 void set_expression(Expression* e) { expression_ = e; }
type()904 Type type() const { return TypeField::decode(bit_field_); }
is_async_return()905 bool is_async_return() const { return type() == kAsyncReturn; }
906
907 private:
908 friend class AstNodeFactory;
909
ReturnStatement(Expression * expression,Type type,int pos)910 ReturnStatement(Expression* expression, Type type, int pos)
911 : JumpStatement(pos, kReturnStatement), expression_(expression) {
912 bit_field_ |= TypeField::encode(type);
913 }
914
915 Expression* expression_;
916
917 class TypeField
918 : public BitField<Type, JumpStatement::kNextBitFieldIndex, 1> {};
919 };
920
921
922 class WithStatement final : public Statement {
923 public:
scope()924 Scope* scope() { return scope_; }
expression()925 Expression* expression() const { return expression_; }
set_expression(Expression * e)926 void set_expression(Expression* e) { expression_ = e; }
statement()927 Statement* statement() const { return statement_; }
set_statement(Statement * s)928 void set_statement(Statement* s) { statement_ = s; }
929
930 private:
931 friend class AstNodeFactory;
932
WithStatement(Scope * scope,Expression * expression,Statement * statement,int pos)933 WithStatement(Scope* scope, Expression* expression, Statement* statement,
934 int pos)
935 : Statement(pos, kWithStatement),
936 scope_(scope),
937 expression_(expression),
938 statement_(statement) {}
939
940 Scope* scope_;
941 Expression* expression_;
942 Statement* statement_;
943 };
944
945
946 class CaseClause final : public Expression {
947 public:
is_default()948 bool is_default() const { return label_ == NULL; }
label()949 Expression* label() const {
950 CHECK(!is_default());
951 return label_;
952 }
set_label(Expression * e)953 void set_label(Expression* e) { label_ = e; }
body_target()954 Label* body_target() { return &body_target_; }
statements()955 ZoneList<Statement*>* statements() const { return statements_; }
956
num_ids()957 static int num_ids() { return parent_num_ids() + 2; }
EntryId()958 BailoutId EntryId() const { return BailoutId(local_id(0)); }
CompareId()959 TypeFeedbackId CompareId() { return TypeFeedbackId(local_id(1)); }
960
compare_type()961 AstType* compare_type() { return compare_type_; }
set_compare_type(AstType * type)962 void set_compare_type(AstType* type) { compare_type_ = type; }
963
964 // CaseClause will have both a slot in the feedback vector and the
965 // TypeFeedbackId to record the type information. TypeFeedbackId is used by
966 // full codegen and the feedback vector slot is used by interpreter.
967 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
968 FeedbackSlotCache* cache);
969
CompareOperationFeedbackSlot()970 FeedbackSlot CompareOperationFeedbackSlot() { return feedback_slot_; }
971
972 private:
973 friend class AstNodeFactory;
974
parent_num_ids()975 static int parent_num_ids() { return Expression::num_ids(); }
976 CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos);
local_id(int n)977 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
978
979 Expression* label_;
980 Label body_target_;
981 ZoneList<Statement*>* statements_;
982 AstType* compare_type_;
983 FeedbackSlot feedback_slot_;
984 };
985
986
987 class SwitchStatement final : public BreakableStatement {
988 public:
Initialize(Expression * tag,ZoneList<CaseClause * > * cases)989 void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
990 tag_ = tag;
991 cases_ = cases;
992 }
993
tag()994 Expression* tag() const { return tag_; }
cases()995 ZoneList<CaseClause*>* cases() const { return cases_; }
996
set_tag(Expression * t)997 void set_tag(Expression* t) { tag_ = t; }
998
999 private:
1000 friend class AstNodeFactory;
1001
SwitchStatement(ZoneList<const AstRawString * > * labels,int pos)1002 SwitchStatement(ZoneList<const AstRawString*>* labels, int pos)
1003 : BreakableStatement(labels, TARGET_FOR_ANONYMOUS, pos, kSwitchStatement),
1004 tag_(NULL),
1005 cases_(NULL) {}
1006
1007 Expression* tag_;
1008 ZoneList<CaseClause*>* cases_;
1009 };
1010
1011
1012 // If-statements always have non-null references to their then- and
1013 // else-parts. When parsing if-statements with no explicit else-part,
1014 // the parser implicitly creates an empty statement. Use the
1015 // HasThenStatement() and HasElseStatement() functions to check if a
1016 // given if-statement has a then- or an else-part containing code.
1017 class IfStatement final : public Statement {
1018 public:
HasThenStatement()1019 bool HasThenStatement() const { return !then_statement()->IsEmpty(); }
HasElseStatement()1020 bool HasElseStatement() const { return !else_statement()->IsEmpty(); }
1021
condition()1022 Expression* condition() const { return condition_; }
then_statement()1023 Statement* then_statement() const { return then_statement_; }
else_statement()1024 Statement* else_statement() const { return else_statement_; }
1025
set_condition(Expression * e)1026 void set_condition(Expression* e) { condition_ = e; }
set_then_statement(Statement * s)1027 void set_then_statement(Statement* s) { then_statement_ = s; }
set_else_statement(Statement * s)1028 void set_else_statement(Statement* s) { else_statement_ = s; }
1029
IsJump()1030 bool IsJump() const {
1031 return HasThenStatement() && then_statement()->IsJump()
1032 && HasElseStatement() && else_statement()->IsJump();
1033 }
1034
set_base_id(int id)1035 void set_base_id(int id) { base_id_ = id; }
num_ids()1036 static int num_ids() { return parent_num_ids() + 3; }
IfId()1037 BailoutId IfId() const { return BailoutId(local_id(0)); }
ThenId()1038 BailoutId ThenId() const { return BailoutId(local_id(1)); }
ElseId()1039 BailoutId ElseId() const { return BailoutId(local_id(2)); }
1040
1041 private:
1042 friend class AstNodeFactory;
1043
IfStatement(Expression * condition,Statement * then_statement,Statement * else_statement,int pos)1044 IfStatement(Expression* condition, Statement* then_statement,
1045 Statement* else_statement, int pos)
1046 : Statement(pos, kIfStatement),
1047 base_id_(BailoutId::None().ToInt()),
1048 condition_(condition),
1049 then_statement_(then_statement),
1050 else_statement_(else_statement) {}
1051
parent_num_ids()1052 static int parent_num_ids() { return 0; }
base_id()1053 int base_id() const {
1054 DCHECK(!BailoutId(base_id_).IsNone());
1055 return base_id_;
1056 }
local_id(int n)1057 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
1058
1059 int base_id_;
1060 Expression* condition_;
1061 Statement* then_statement_;
1062 Statement* else_statement_;
1063 };
1064
1065
1066 class TryStatement : public Statement {
1067 public:
try_block()1068 Block* try_block() const { return try_block_; }
set_try_block(Block * b)1069 void set_try_block(Block* b) { try_block_ = b; }
1070
1071 // Prediction of whether exceptions thrown into the handler for this try block
1072 // will be caught.
1073 //
1074 // This is set in ast-numbering and later compiled into the code's handler
1075 // table. The runtime uses this information to implement a feature that
1076 // notifies the debugger when an uncaught exception is thrown, _before_ the
1077 // exception propagates to the top.
1078 //
1079 // Since it's generally undecidable whether an exception will be caught, our
1080 // prediction is only an approximation.
catch_prediction()1081 HandlerTable::CatchPrediction catch_prediction() const {
1082 return catch_prediction_;
1083 }
set_catch_prediction(HandlerTable::CatchPrediction prediction)1084 void set_catch_prediction(HandlerTable::CatchPrediction prediction) {
1085 catch_prediction_ = prediction;
1086 }
1087
1088 protected:
TryStatement(Block * try_block,int pos,NodeType type)1089 TryStatement(Block* try_block, int pos, NodeType type)
1090 : Statement(pos, type),
1091 catch_prediction_(HandlerTable::UNCAUGHT),
1092 try_block_(try_block) {}
1093
1094 HandlerTable::CatchPrediction catch_prediction_;
1095
1096 private:
1097 Block* try_block_;
1098 };
1099
1100
1101 class TryCatchStatement final : public TryStatement {
1102 public:
scope()1103 Scope* scope() { return scope_; }
variable()1104 Variable* variable() { return variable_; }
catch_block()1105 Block* catch_block() const { return catch_block_; }
set_catch_block(Block * b)1106 void set_catch_block(Block* b) { catch_block_ = b; }
1107
1108 // The clear_pending_message flag indicates whether or not to clear the
1109 // isolate's pending exception message before executing the catch_block. In
1110 // the normal use case, this flag is always on because the message object
1111 // is not needed anymore when entering the catch block and should not be kept
1112 // alive.
1113 // The use case where the flag is off is when the catch block is guaranteed to
1114 // rethrow the caught exception (using %ReThrow), which reuses the pending
1115 // message instead of generating a new one.
1116 // (When the catch block doesn't rethrow but is guaranteed to perform an
1117 // ordinary throw, not clearing the old message is safe but not very useful.)
clear_pending_message()1118 bool clear_pending_message() const {
1119 return catch_prediction_ != HandlerTable::UNCAUGHT;
1120 }
1121
1122 private:
1123 friend class AstNodeFactory;
1124
TryCatchStatement(Block * try_block,Scope * scope,Variable * variable,Block * catch_block,HandlerTable::CatchPrediction catch_prediction,int pos)1125 TryCatchStatement(Block* try_block, Scope* scope, Variable* variable,
1126 Block* catch_block,
1127 HandlerTable::CatchPrediction catch_prediction, int pos)
1128 : TryStatement(try_block, pos, kTryCatchStatement),
1129 scope_(scope),
1130 variable_(variable),
1131 catch_block_(catch_block) {
1132 catch_prediction_ = catch_prediction;
1133 }
1134
1135 Scope* scope_;
1136 Variable* variable_;
1137 Block* catch_block_;
1138 };
1139
1140
1141 class TryFinallyStatement final : public TryStatement {
1142 public:
finally_block()1143 Block* finally_block() const { return finally_block_; }
set_finally_block(Block * b)1144 void set_finally_block(Block* b) { finally_block_ = b; }
1145
1146 private:
1147 friend class AstNodeFactory;
1148
TryFinallyStatement(Block * try_block,Block * finally_block,int pos)1149 TryFinallyStatement(Block* try_block, Block* finally_block, int pos)
1150 : TryStatement(try_block, pos, kTryFinallyStatement),
1151 finally_block_(finally_block) {}
1152
1153 Block* finally_block_;
1154 };
1155
1156
1157 class DebuggerStatement final : public Statement {
1158 private:
1159 friend class AstNodeFactory;
1160
DebuggerStatement(int pos)1161 explicit DebuggerStatement(int pos) : Statement(pos, kDebuggerStatement) {}
1162 };
1163
1164
1165 class EmptyStatement final : public Statement {
1166 private:
1167 friend class AstNodeFactory;
EmptyStatement(int pos)1168 explicit EmptyStatement(int pos) : Statement(pos, kEmptyStatement) {}
1169 };
1170
1171
1172 // Delegates to another statement, which may be overwritten.
1173 // This was introduced to implement ES2015 Annex B3.3 for conditionally making
1174 // sloppy-mode block-scoped functions have a var binding, which is changed
1175 // from one statement to another during parsing.
1176 class SloppyBlockFunctionStatement final : public Statement {
1177 public:
statement()1178 Statement* statement() const { return statement_; }
set_statement(Statement * statement)1179 void set_statement(Statement* statement) { statement_ = statement; }
1180
1181 private:
1182 friend class AstNodeFactory;
1183
SloppyBlockFunctionStatement(Statement * statement)1184 explicit SloppyBlockFunctionStatement(Statement* statement)
1185 : Statement(kNoSourcePosition, kSloppyBlockFunctionStatement),
1186 statement_(statement) {}
1187
1188 Statement* statement_;
1189 };
1190
1191
1192 class Literal final : public Expression {
1193 public:
1194 // Returns true if literal represents a property name (i.e. cannot be parsed
1195 // as array indices).
IsPropertyName()1196 bool IsPropertyName() const { return value_->IsPropertyName(); }
1197
AsPropertyName()1198 Handle<String> AsPropertyName() {
1199 DCHECK(IsPropertyName());
1200 return Handle<String>::cast(value());
1201 }
1202
AsRawPropertyName()1203 const AstRawString* AsRawPropertyName() {
1204 DCHECK(IsPropertyName());
1205 return value_->AsString();
1206 }
1207
ToBooleanIsTrue()1208 bool ToBooleanIsTrue() const { return raw_value()->BooleanValue(); }
ToBooleanIsFalse()1209 bool ToBooleanIsFalse() const { return !raw_value()->BooleanValue(); }
1210
value()1211 Handle<Object> value() const { return value_->value(); }
raw_value()1212 const AstValue* raw_value() const { return value_; }
1213
1214 // Support for using Literal as a HashMap key. NOTE: Currently, this works
1215 // only for string and number literals!
1216 uint32_t Hash();
1217 static bool Match(void* literal1, void* literal2);
1218
num_ids()1219 static int num_ids() { return parent_num_ids() + 1; }
LiteralFeedbackId()1220 TypeFeedbackId LiteralFeedbackId() const {
1221 return TypeFeedbackId(local_id(0));
1222 }
1223
1224 private:
1225 friend class AstNodeFactory;
1226
Literal(const AstValue * value,int position)1227 Literal(const AstValue* value, int position)
1228 : Expression(position, kLiteral), value_(value) {}
1229
parent_num_ids()1230 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)1231 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
1232
1233 const AstValue* value_;
1234 };
1235
1236 // Base class for literals that need space in the type feedback vector.
1237 class MaterializedLiteral : public Expression {
1238 public:
depth()1239 int depth() const {
1240 // only callable after initialization.
1241 DCHECK(depth_ >= 1);
1242 return depth_;
1243 }
1244
AssignFeedbackSlots(FeedbackVectorSpec * spec,LanguageMode language_mode,FeedbackSlotCache * cache)1245 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
1246 FeedbackSlotCache* cache) {
1247 literal_slot_ = spec->AddLiteralSlot();
1248 }
1249
literal_slot()1250 FeedbackSlot literal_slot() const { return literal_slot_; }
1251
1252 private:
1253 int depth_ : 31;
1254 FeedbackSlot literal_slot_;
1255
1256 class IsSimpleField
1257 : public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
1258
1259 protected:
MaterializedLiteral(int pos,NodeType type)1260 MaterializedLiteral(int pos, NodeType type)
1261 : Expression(pos, type), depth_(0) {
1262 bit_field_ |= IsSimpleField::encode(false);
1263 }
1264
1265 // A materialized literal is simple if the values consist of only
1266 // constants and simple object and array literals.
is_simple()1267 bool is_simple() const { return IsSimpleField::decode(bit_field_); }
set_is_simple(bool is_simple)1268 void set_is_simple(bool is_simple) {
1269 bit_field_ = IsSimpleField::update(bit_field_, is_simple);
1270 }
1271 friend class CompileTimeValue;
1272
set_depth(int depth)1273 void set_depth(int depth) {
1274 DCHECK_LE(1, depth);
1275 depth_ = depth;
1276 }
1277
1278 // Populate the depth field and any flags the literal has.
1279 void InitDepthAndFlags();
1280
1281 // Populate the constant properties/elements fixed array.
1282 void BuildConstants(Isolate* isolate);
1283 friend class ArrayLiteral;
1284 friend class ObjectLiteral;
1285
1286 // If the expression is a literal, return the literal value;
1287 // if the expression is a materialized literal and is simple return a
1288 // compile time value as encoded by CompileTimeValue::GetValue().
1289 // Otherwise, return undefined literal as the placeholder
1290 // in the object literal boilerplate.
1291 Handle<Object> GetBoilerplateValue(Expression* expression, Isolate* isolate);
1292
1293 static const uint8_t kNextBitFieldIndex = IsSimpleField::kNext;
1294 };
1295
1296 // Common supertype for ObjectLiteralProperty and ClassLiteralProperty
1297 class LiteralProperty : public ZoneObject {
1298 public:
key()1299 Expression* key() const { return key_; }
value()1300 Expression* value() const { return value_; }
set_key(Expression * e)1301 void set_key(Expression* e) { key_ = e; }
set_value(Expression * e)1302 void set_value(Expression* e) { value_ = e; }
1303
is_computed_name()1304 bool is_computed_name() const { return is_computed_name_; }
1305
1306 FeedbackSlot GetSlot(int offset = 0) const {
1307 DCHECK_LT(offset, static_cast<int>(arraysize(slots_)));
1308 return slots_[offset];
1309 }
1310
1311 FeedbackSlot GetStoreDataPropertySlot() const;
1312
1313 void SetSlot(FeedbackSlot slot, int offset = 0) {
1314 DCHECK_LT(offset, static_cast<int>(arraysize(slots_)));
1315 slots_[offset] = slot;
1316 }
1317
1318 void SetStoreDataPropertySlot(FeedbackSlot slot);
1319
1320 bool NeedsSetFunctionName() const;
1321
1322 protected:
LiteralProperty(Expression * key,Expression * value,bool is_computed_name)1323 LiteralProperty(Expression* key, Expression* value, bool is_computed_name)
1324 : key_(key), value_(value), is_computed_name_(is_computed_name) {}
1325
1326 Expression* key_;
1327 Expression* value_;
1328 FeedbackSlot slots_[2];
1329 bool is_computed_name_;
1330 };
1331
1332 // Property is used for passing information
1333 // about an object literal's properties from the parser
1334 // to the code generator.
1335 class ObjectLiteralProperty final : public LiteralProperty {
1336 public:
1337 enum Kind : uint8_t {
1338 CONSTANT, // Property with constant value (compile time).
1339 COMPUTED, // Property with computed value (execution time).
1340 MATERIALIZED_LITERAL, // Property value is a materialized literal.
1341 GETTER,
1342 SETTER, // Property is an accessor function.
1343 PROTOTYPE, // Property is __proto__.
1344 SPREAD
1345 };
1346
kind()1347 Kind kind() const { return kind_; }
1348
1349 // Type feedback information.
IsMonomorphic()1350 bool IsMonomorphic() const { return !receiver_type_.is_null(); }
GetReceiverType()1351 Handle<Map> GetReceiverType() const { return receiver_type_; }
1352
1353 bool IsCompileTimeValue() const;
1354
1355 void set_emit_store(bool emit_store);
1356 bool emit_store() const;
1357
set_receiver_type(Handle<Map> map)1358 void set_receiver_type(Handle<Map> map) { receiver_type_ = map; }
1359
1360 private:
1361 friend class AstNodeFactory;
1362
1363 ObjectLiteralProperty(Expression* key, Expression* value, Kind kind,
1364 bool is_computed_name);
1365 ObjectLiteralProperty(AstValueFactory* ast_value_factory, Expression* key,
1366 Expression* value, bool is_computed_name);
1367
1368 Kind kind_;
1369 bool emit_store_;
1370 Handle<Map> receiver_type_;
1371 };
1372
1373
1374 // An object literal has a boilerplate object that is used
1375 // for minimizing the work when constructing it at runtime.
1376 class ObjectLiteral final : public MaterializedLiteral {
1377 public:
1378 typedef ObjectLiteralProperty Property;
1379
constant_properties()1380 Handle<BoilerplateDescription> constant_properties() const {
1381 DCHECK(!constant_properties_.is_null());
1382 return constant_properties_;
1383 }
properties_count()1384 int properties_count() const { return boilerplate_properties_; }
properties()1385 ZoneList<Property*>* properties() const { return properties_; }
fast_elements()1386 bool fast_elements() const { return FastElementsField::decode(bit_field_); }
may_store_doubles()1387 bool may_store_doubles() const {
1388 return MayStoreDoublesField::decode(bit_field_);
1389 }
has_elements()1390 bool has_elements() const { return HasElementsField::decode(bit_field_); }
has_shallow_properties()1391 bool has_shallow_properties() const {
1392 return depth() == 1 && !has_elements() && !may_store_doubles();
1393 }
has_rest_property()1394 bool has_rest_property() const {
1395 return HasRestPropertyField::decode(bit_field_);
1396 }
1397
1398 // Decide if a property should be in the object boilerplate.
1399 static bool IsBoilerplateProperty(Property* property);
1400
1401 // Populate the depth field and flags.
1402 void InitDepthAndFlags();
1403
1404 // Get the constant properties fixed array, populating it if necessary.
GetOrBuildConstantProperties(Isolate * isolate)1405 Handle<BoilerplateDescription> GetOrBuildConstantProperties(
1406 Isolate* isolate) {
1407 if (constant_properties_.is_null()) {
1408 BuildConstantProperties(isolate);
1409 }
1410 return constant_properties();
1411 }
1412
1413 // Populate the constant properties fixed array.
1414 void BuildConstantProperties(Isolate* isolate);
1415
1416 // Mark all computed expressions that are bound to a key that
1417 // is shadowed by a later occurrence of the same key. For the
1418 // marked expressions, no store code is emitted.
1419 void CalculateEmitStore(Zone* zone);
1420
1421 // Determines whether the {FastCloneShallowObject} builtin can be used.
1422 bool IsFastCloningSupported() const;
1423
1424 // Assemble bitfield of flags for the CreateObjectLiteral helper.
1425 int ComputeFlags(bool disable_mementos = false) const {
1426 int flags = fast_elements() ? kFastElements : kNoFlags;
1427 if (has_shallow_properties()) {
1428 flags |= kShallowProperties;
1429 }
1430 if (disable_mementos) {
1431 flags |= kDisableMementos;
1432 }
1433 return flags;
1434 }
1435
1436 enum Flags {
1437 kNoFlags = 0,
1438 kFastElements = 1,
1439 kShallowProperties = 1 << 1,
1440 kDisableMementos = 1 << 2,
1441 kHasRestProperty = 1 << 3,
1442 };
1443
1444 struct Accessors: public ZoneObject {
AccessorsAccessors1445 Accessors() : getter(NULL), setter(NULL), bailout_id(BailoutId::None()) {}
1446 ObjectLiteralProperty* getter;
1447 ObjectLiteralProperty* setter;
1448 BailoutId bailout_id;
1449 };
1450
CreateLiteralId()1451 BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
1452
1453 // Return an AST id for a property that is used in simulate instructions.
GetIdForPropertySet(int i)1454 BailoutId GetIdForPropertySet(int i) { return BailoutId(local_id(i + 1)); }
1455
1456 // Unlike other AST nodes, this number of bailout IDs allocated for an
1457 // ObjectLiteral can vary, so num_ids() is not a static method.
num_ids()1458 int num_ids() const { return parent_num_ids() + 1 + properties()->length(); }
1459
1460 // Object literals need one feedback slot for each non-trivial value, as well
1461 // as some slots for home objects.
1462 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
1463 FeedbackSlotCache* cache);
1464
1465 private:
1466 friend class AstNodeFactory;
1467
ObjectLiteral(ZoneList<Property * > * properties,uint32_t boilerplate_properties,int pos,bool has_rest_property)1468 ObjectLiteral(ZoneList<Property*>* properties,
1469 uint32_t boilerplate_properties, int pos,
1470 bool has_rest_property)
1471 : MaterializedLiteral(pos, kObjectLiteral),
1472 boilerplate_properties_(boilerplate_properties),
1473 properties_(properties) {
1474 bit_field_ |= FastElementsField::encode(false) |
1475 HasElementsField::encode(false) |
1476 MayStoreDoublesField::encode(false) |
1477 HasRestPropertyField::encode(has_rest_property);
1478 }
1479
parent_num_ids()1480 static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
local_id(int n)1481 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
1482
1483 uint32_t boilerplate_properties_;
1484 Handle<BoilerplateDescription> constant_properties_;
1485 ZoneList<Property*>* properties_;
1486
1487 class FastElementsField
1488 : public BitField<bool, MaterializedLiteral::kNextBitFieldIndex, 1> {};
1489 class HasElementsField : public BitField<bool, FastElementsField::kNext, 1> {
1490 };
1491 class MayStoreDoublesField
1492 : public BitField<bool, HasElementsField::kNext, 1> {};
1493 class HasRestPropertyField
1494 : public BitField<bool, MayStoreDoublesField::kNext, 1> {};
1495 };
1496
1497
1498 // A map from property names to getter/setter pairs allocated in the zone.
1499 class AccessorTable
1500 : public base::TemplateHashMap<Literal, ObjectLiteral::Accessors,
1501 bool (*)(void*, void*),
1502 ZoneAllocationPolicy> {
1503 public:
AccessorTable(Zone * zone)1504 explicit AccessorTable(Zone* zone)
1505 : base::TemplateHashMap<Literal, ObjectLiteral::Accessors,
1506 bool (*)(void*, void*), ZoneAllocationPolicy>(
1507 Literal::Match, ZoneAllocationPolicy(zone)),
1508 zone_(zone) {}
1509
lookup(Literal * literal)1510 Iterator lookup(Literal* literal) {
1511 Iterator it = find(literal, true, ZoneAllocationPolicy(zone_));
1512 if (it->second == NULL) it->second = new (zone_) ObjectLiteral::Accessors();
1513 return it;
1514 }
1515
1516 private:
1517 Zone* zone_;
1518 };
1519
1520
1521 // Node for capturing a regexp literal.
1522 class RegExpLiteral final : public MaterializedLiteral {
1523 public:
pattern()1524 Handle<String> pattern() const { return pattern_->string(); }
raw_pattern()1525 const AstRawString* raw_pattern() const { return pattern_; }
flags()1526 int flags() const { return flags_; }
1527
1528 private:
1529 friend class AstNodeFactory;
1530
RegExpLiteral(const AstRawString * pattern,int flags,int pos)1531 RegExpLiteral(const AstRawString* pattern, int flags, int pos)
1532 : MaterializedLiteral(pos, kRegExpLiteral),
1533 flags_(flags),
1534 pattern_(pattern) {
1535 set_depth(1);
1536 }
1537
1538 int const flags_;
1539 const AstRawString* const pattern_;
1540 };
1541
1542
1543 // An array literal has a literals object that is used
1544 // for minimizing the work when constructing it at runtime.
1545 class ArrayLiteral final : public MaterializedLiteral {
1546 public:
constant_elements()1547 Handle<ConstantElementsPair> constant_elements() const {
1548 return constant_elements_;
1549 }
1550 ElementsKind constant_elements_kind() const;
1551
values()1552 ZoneList<Expression*>* values() const { return values_; }
1553
CreateLiteralId()1554 BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
1555
1556 // Return an AST id for an element that is used in simulate instructions.
GetIdForElement(int i)1557 BailoutId GetIdForElement(int i) { return BailoutId(local_id(i + 1)); }
1558
1559 // Unlike other AST nodes, this number of bailout IDs allocated for an
1560 // ArrayLiteral can vary, so num_ids() is not a static method.
num_ids()1561 int num_ids() const { return parent_num_ids() + 1 + values()->length(); }
1562
1563 // Populate the depth field and flags.
1564 void InitDepthAndFlags();
1565
1566 // Get the constant elements fixed array, populating it if necessary.
GetOrBuildConstantElements(Isolate * isolate)1567 Handle<ConstantElementsPair> GetOrBuildConstantElements(Isolate* isolate) {
1568 if (constant_elements_.is_null()) {
1569 BuildConstantElements(isolate);
1570 }
1571 return constant_elements();
1572 }
1573
1574 // Populate the constant elements fixed array.
1575 void BuildConstantElements(Isolate* isolate);
1576
1577 // Determines whether the {FastCloneShallowArray} builtin can be used.
1578 bool IsFastCloningSupported() const;
1579
1580 // Assemble bitfield of flags for the CreateArrayLiteral helper.
1581 int ComputeFlags(bool disable_mementos = false) const {
1582 int flags = depth() == 1 ? kShallowElements : kNoFlags;
1583 if (disable_mementos) {
1584 flags |= kDisableMementos;
1585 }
1586 return flags;
1587 }
1588
1589 // Provide a mechanism for iterating through values to rewrite spreads.
FirstSpread()1590 ZoneList<Expression*>::iterator FirstSpread() const {
1591 return (first_spread_index_ >= 0) ? values_->begin() + first_spread_index_
1592 : values_->end();
1593 }
EndValue()1594 ZoneList<Expression*>::iterator EndValue() const { return values_->end(); }
1595
1596 // Rewind an array literal omitting everything from the first spread on.
1597 void RewindSpreads();
1598
1599 enum Flags {
1600 kNoFlags = 0,
1601 kShallowElements = 1,
1602 kDisableMementos = 1 << 1
1603 };
1604
1605 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
1606 FeedbackSlotCache* cache);
LiteralFeedbackSlot()1607 FeedbackSlot LiteralFeedbackSlot() const { return literal_slot_; }
1608
1609 private:
1610 friend class AstNodeFactory;
1611
ArrayLiteral(ZoneList<Expression * > * values,int first_spread_index,int pos)1612 ArrayLiteral(ZoneList<Expression*>* values, int first_spread_index, int pos)
1613 : MaterializedLiteral(pos, kArrayLiteral),
1614 first_spread_index_(first_spread_index),
1615 values_(values) {}
1616
parent_num_ids()1617 static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
local_id(int n)1618 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
1619
1620 int first_spread_index_;
1621 FeedbackSlot literal_slot_;
1622 Handle<ConstantElementsPair> constant_elements_;
1623 ZoneList<Expression*>* values_;
1624 };
1625
1626
1627 class VariableProxy final : public Expression {
1628 public:
IsValidReferenceExpression()1629 bool IsValidReferenceExpression() const {
1630 return !is_this() && !is_new_target();
1631 }
1632
name()1633 Handle<String> name() const { return raw_name()->string(); }
raw_name()1634 const AstRawString* raw_name() const {
1635 return is_resolved() ? var_->raw_name() : raw_name_;
1636 }
1637
var()1638 Variable* var() const {
1639 DCHECK(is_resolved());
1640 return var_;
1641 }
set_var(Variable * v)1642 void set_var(Variable* v) {
1643 DCHECK(!is_resolved());
1644 DCHECK_NOT_NULL(v);
1645 var_ = v;
1646 }
1647
is_this()1648 bool is_this() const { return IsThisField::decode(bit_field_); }
1649
is_assigned()1650 bool is_assigned() const { return IsAssignedField::decode(bit_field_); }
set_is_assigned()1651 void set_is_assigned() {
1652 bit_field_ = IsAssignedField::update(bit_field_, true);
1653 if (is_resolved()) {
1654 var()->set_maybe_assigned();
1655 }
1656 }
1657
is_resolved()1658 bool is_resolved() const { return IsResolvedField::decode(bit_field_); }
set_is_resolved()1659 void set_is_resolved() {
1660 bit_field_ = IsResolvedField::update(bit_field_, true);
1661 }
1662
is_new_target()1663 bool is_new_target() const { return IsNewTargetField::decode(bit_field_); }
set_is_new_target()1664 void set_is_new_target() {
1665 bit_field_ = IsNewTargetField::update(bit_field_, true);
1666 }
1667
hole_check_mode()1668 HoleCheckMode hole_check_mode() const {
1669 return HoleCheckModeField::decode(bit_field_);
1670 }
set_needs_hole_check()1671 void set_needs_hole_check() {
1672 bit_field_ =
1673 HoleCheckModeField::update(bit_field_, HoleCheckMode::kRequired);
1674 }
1675
1676 // Bind this proxy to the variable var.
1677 void BindTo(Variable* var);
1678
UsesVariableFeedbackSlot()1679 bool UsesVariableFeedbackSlot() const {
1680 return var()->IsUnallocated() || var()->IsLookupSlot();
1681 }
1682
1683 void AssignFeedbackSlots(FeedbackVectorSpec* spec, TypeofMode typeof_mode,
1684 FeedbackSlotCache* cache);
1685
VariableFeedbackSlot()1686 FeedbackSlot VariableFeedbackSlot() { return variable_feedback_slot_; }
1687
num_ids()1688 static int num_ids() { return parent_num_ids() + 1; }
BeforeId()1689 BailoutId BeforeId() const { return BailoutId(local_id(0)); }
set_next_unresolved(VariableProxy * next)1690 void set_next_unresolved(VariableProxy* next) { next_unresolved_ = next; }
next_unresolved()1691 VariableProxy* next_unresolved() { return next_unresolved_; }
1692
1693 private:
1694 friend class AstNodeFactory;
1695
1696 VariableProxy(Variable* var, int start_position);
1697 VariableProxy(const AstRawString* name, VariableKind variable_kind,
1698 int start_position);
1699 explicit VariableProxy(const VariableProxy* copy_from);
1700
parent_num_ids()1701 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)1702 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
1703
1704 class IsThisField : public BitField<bool, Expression::kNextBitFieldIndex, 1> {
1705 };
1706 class IsAssignedField : public BitField<bool, IsThisField::kNext, 1> {};
1707 class IsResolvedField : public BitField<bool, IsAssignedField::kNext, 1> {};
1708 class IsNewTargetField : public BitField<bool, IsResolvedField::kNext, 1> {};
1709 class HoleCheckModeField
1710 : public BitField<HoleCheckMode, IsNewTargetField::kNext, 1> {};
1711
1712 FeedbackSlot variable_feedback_slot_;
1713 union {
1714 const AstRawString* raw_name_; // if !is_resolved_
1715 Variable* var_; // if is_resolved_
1716 };
1717 VariableProxy* next_unresolved_;
1718 };
1719
1720
1721 // Left-hand side can only be a property, a global or a (parameter or local)
1722 // slot.
1723 enum LhsKind {
1724 VARIABLE,
1725 NAMED_PROPERTY,
1726 KEYED_PROPERTY,
1727 NAMED_SUPER_PROPERTY,
1728 KEYED_SUPER_PROPERTY
1729 };
1730
1731
1732 class Property final : public Expression {
1733 public:
IsValidReferenceExpression()1734 bool IsValidReferenceExpression() const { return true; }
1735
obj()1736 Expression* obj() const { return obj_; }
key()1737 Expression* key() const { return key_; }
1738
set_obj(Expression * e)1739 void set_obj(Expression* e) { obj_ = e; }
set_key(Expression * e)1740 void set_key(Expression* e) { key_ = e; }
1741
num_ids()1742 static int num_ids() { return parent_num_ids() + 1; }
LoadId()1743 BailoutId LoadId() const { return BailoutId(local_id(0)); }
1744
IsStringAccess()1745 bool IsStringAccess() const {
1746 return IsStringAccessField::decode(bit_field_);
1747 }
1748
1749 // Type feedback information.
IsMonomorphic()1750 bool IsMonomorphic() const { return receiver_types_.length() == 1; }
GetReceiverTypes()1751 SmallMapList* GetReceiverTypes() { return &receiver_types_; }
GetStoreMode()1752 KeyedAccessStoreMode GetStoreMode() const { return STANDARD_STORE; }
GetKeyType()1753 IcCheckType GetKeyType() const { return KeyTypeField::decode(bit_field_); }
IsUninitialized()1754 bool IsUninitialized() const {
1755 return !is_for_call() && HasNoTypeInformation();
1756 }
HasNoTypeInformation()1757 bool HasNoTypeInformation() const {
1758 return GetInlineCacheState() == UNINITIALIZED;
1759 }
GetInlineCacheState()1760 InlineCacheState GetInlineCacheState() const {
1761 return InlineCacheStateField::decode(bit_field_);
1762 }
set_is_string_access(bool b)1763 void set_is_string_access(bool b) {
1764 bit_field_ = IsStringAccessField::update(bit_field_, b);
1765 }
set_key_type(IcCheckType key_type)1766 void set_key_type(IcCheckType key_type) {
1767 bit_field_ = KeyTypeField::update(bit_field_, key_type);
1768 }
set_inline_cache_state(InlineCacheState state)1769 void set_inline_cache_state(InlineCacheState state) {
1770 bit_field_ = InlineCacheStateField::update(bit_field_, state);
1771 }
mark_for_call()1772 void mark_for_call() {
1773 bit_field_ = IsForCallField::update(bit_field_, true);
1774 }
is_for_call()1775 bool is_for_call() const { return IsForCallField::decode(bit_field_); }
1776
IsSuperAccess()1777 bool IsSuperAccess() { return obj()->IsSuperPropertyReference(); }
1778
AssignFeedbackSlots(FeedbackVectorSpec * spec,LanguageMode language_mode,FeedbackSlotCache * cache)1779 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
1780 FeedbackSlotCache* cache) {
1781 if (key()->IsPropertyName()) {
1782 property_feedback_slot_ = spec->AddLoadICSlot();
1783 } else {
1784 property_feedback_slot_ = spec->AddKeyedLoadICSlot();
1785 }
1786 }
1787
PropertyFeedbackSlot()1788 FeedbackSlot PropertyFeedbackSlot() const { return property_feedback_slot_; }
1789
1790 // Returns the properties assign type.
GetAssignType(Property * property)1791 static LhsKind GetAssignType(Property* property) {
1792 if (property == NULL) return VARIABLE;
1793 bool super_access = property->IsSuperAccess();
1794 return (property->key()->IsPropertyName())
1795 ? (super_access ? NAMED_SUPER_PROPERTY : NAMED_PROPERTY)
1796 : (super_access ? KEYED_SUPER_PROPERTY : KEYED_PROPERTY);
1797 }
1798
1799 private:
1800 friend class AstNodeFactory;
1801
Property(Expression * obj,Expression * key,int pos)1802 Property(Expression* obj, Expression* key, int pos)
1803 : Expression(pos, kProperty), obj_(obj), key_(key) {
1804 bit_field_ |= IsForCallField::encode(false) |
1805 IsStringAccessField::encode(false) |
1806 InlineCacheStateField::encode(UNINITIALIZED);
1807 }
1808
parent_num_ids()1809 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)1810 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
1811
1812 class IsForCallField
1813 : public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
1814 class IsStringAccessField : public BitField<bool, IsForCallField::kNext, 1> {
1815 };
1816 class KeyTypeField
1817 : public BitField<IcCheckType, IsStringAccessField::kNext, 1> {};
1818 class InlineCacheStateField
1819 : public BitField<InlineCacheState, KeyTypeField::kNext, 4> {};
1820
1821 FeedbackSlot property_feedback_slot_;
1822 Expression* obj_;
1823 Expression* key_;
1824 SmallMapList receiver_types_;
1825 };
1826
1827
1828 class Call final : public Expression {
1829 public:
expression()1830 Expression* expression() const { return expression_; }
arguments()1831 ZoneList<Expression*>* arguments() const { return arguments_; }
1832
set_expression(Expression * e)1833 void set_expression(Expression* e) { expression_ = e; }
1834
1835 // Type feedback information.
1836 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
1837 FeedbackSlotCache* cache);
1838
CallFeedbackICSlot()1839 FeedbackSlot CallFeedbackICSlot() const { return ic_slot_; }
1840
GetReceiverTypes()1841 SmallMapList* GetReceiverTypes() {
1842 if (expression()->IsProperty()) {
1843 return expression()->AsProperty()->GetReceiverTypes();
1844 }
1845 return nullptr;
1846 }
1847
IsMonomorphic()1848 bool IsMonomorphic() const {
1849 if (expression()->IsProperty()) {
1850 return expression()->AsProperty()->IsMonomorphic();
1851 }
1852 return !target_.is_null();
1853 }
1854
target()1855 Handle<JSFunction> target() { return target_; }
1856
allocation_site()1857 Handle<AllocationSite> allocation_site() { return allocation_site_; }
1858
SetKnownGlobalTarget(Handle<JSFunction> target)1859 void SetKnownGlobalTarget(Handle<JSFunction> target) {
1860 target_ = target;
1861 set_is_uninitialized(false);
1862 }
set_target(Handle<JSFunction> target)1863 void set_target(Handle<JSFunction> target) { target_ = target; }
set_allocation_site(Handle<AllocationSite> site)1864 void set_allocation_site(Handle<AllocationSite> site) {
1865 allocation_site_ = site;
1866 }
1867
num_ids()1868 static int num_ids() { return parent_num_ids() + 2; }
ReturnId()1869 BailoutId ReturnId() const { return BailoutId(local_id(0)); }
CallId()1870 BailoutId CallId() const { return BailoutId(local_id(1)); }
1871
is_uninitialized()1872 bool is_uninitialized() const {
1873 return IsUninitializedField::decode(bit_field_);
1874 }
set_is_uninitialized(bool b)1875 void set_is_uninitialized(bool b) {
1876 bit_field_ = IsUninitializedField::update(bit_field_, b);
1877 }
1878
is_possibly_eval()1879 bool is_possibly_eval() const {
1880 return IsPossiblyEvalField::decode(bit_field_);
1881 }
1882
tail_call_mode()1883 TailCallMode tail_call_mode() const {
1884 return IsTailField::decode(bit_field_) ? TailCallMode::kAllow
1885 : TailCallMode::kDisallow;
1886 }
MarkTail()1887 void MarkTail() { bit_field_ = IsTailField::update(bit_field_, true); }
1888
only_last_arg_is_spread()1889 bool only_last_arg_is_spread() {
1890 return !arguments_->is_empty() && arguments_->last()->IsSpread();
1891 }
1892
1893 enum CallType {
1894 GLOBAL_CALL,
1895 WITH_CALL,
1896 NAMED_PROPERTY_CALL,
1897 KEYED_PROPERTY_CALL,
1898 NAMED_SUPER_PROPERTY_CALL,
1899 KEYED_SUPER_PROPERTY_CALL,
1900 SUPER_CALL,
1901 OTHER_CALL
1902 };
1903
1904 enum PossiblyEval {
1905 IS_POSSIBLY_EVAL,
1906 NOT_EVAL,
1907 };
1908
1909 // Helpers to determine how to handle the call.
1910 CallType GetCallType() const;
1911
1912 #ifdef DEBUG
1913 // Used to assert that the FullCodeGenerator records the return site.
1914 bool return_is_recorded_;
1915 #endif
1916
1917 private:
1918 friend class AstNodeFactory;
1919
Call(Expression * expression,ZoneList<Expression * > * arguments,int pos,PossiblyEval possibly_eval)1920 Call(Expression* expression, ZoneList<Expression*>* arguments, int pos,
1921 PossiblyEval possibly_eval)
1922 : Expression(pos, kCall),
1923 expression_(expression),
1924 arguments_(arguments) {
1925 bit_field_ |=
1926 IsUninitializedField::encode(false) |
1927 IsPossiblyEvalField::encode(possibly_eval == IS_POSSIBLY_EVAL);
1928
1929 if (expression->IsProperty()) {
1930 expression->AsProperty()->mark_for_call();
1931 }
1932 }
1933
parent_num_ids()1934 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)1935 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
1936
1937 class IsUninitializedField
1938 : public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
1939 class IsTailField : public BitField<bool, IsUninitializedField::kNext, 1> {};
1940 class IsPossiblyEvalField : public BitField<bool, IsTailField::kNext, 1> {};
1941
1942 FeedbackSlot ic_slot_;
1943 Expression* expression_;
1944 ZoneList<Expression*>* arguments_;
1945 Handle<JSFunction> target_;
1946 Handle<AllocationSite> allocation_site_;
1947 };
1948
1949
1950 class CallNew final : public Expression {
1951 public:
expression()1952 Expression* expression() const { return expression_; }
arguments()1953 ZoneList<Expression*>* arguments() const { return arguments_; }
1954
set_expression(Expression * e)1955 void set_expression(Expression* e) { expression_ = e; }
1956
1957 // Type feedback information.
AssignFeedbackSlots(FeedbackVectorSpec * spec,LanguageMode language_mode,FeedbackSlotCache * cache)1958 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
1959 FeedbackSlotCache* cache) {
1960 // CallNew stores feedback in the exact same way as Call. We can
1961 // piggyback on the type feedback infrastructure for calls.
1962 callnew_feedback_slot_ = spec->AddCallICSlot();
1963 }
1964
CallNewFeedbackSlot()1965 FeedbackSlot CallNewFeedbackSlot() {
1966 DCHECK(!callnew_feedback_slot_.IsInvalid());
1967 return callnew_feedback_slot_;
1968 }
1969
IsMonomorphic()1970 bool IsMonomorphic() const { return IsMonomorphicField::decode(bit_field_); }
target()1971 Handle<JSFunction> target() const { return target_; }
allocation_site()1972 Handle<AllocationSite> allocation_site() const {
1973 return allocation_site_;
1974 }
1975
num_ids()1976 static int num_ids() { return parent_num_ids() + 1; }
feedback_slots()1977 static int feedback_slots() { return 1; }
ReturnId()1978 BailoutId ReturnId() const { return BailoutId(local_id(0)); }
1979
set_allocation_site(Handle<AllocationSite> site)1980 void set_allocation_site(Handle<AllocationSite> site) {
1981 allocation_site_ = site;
1982 }
set_is_monomorphic(bool monomorphic)1983 void set_is_monomorphic(bool monomorphic) {
1984 bit_field_ = IsMonomorphicField::update(bit_field_, monomorphic);
1985 }
set_target(Handle<JSFunction> target)1986 void set_target(Handle<JSFunction> target) { target_ = target; }
SetKnownGlobalTarget(Handle<JSFunction> target)1987 void SetKnownGlobalTarget(Handle<JSFunction> target) {
1988 target_ = target;
1989 set_is_monomorphic(true);
1990 }
1991
only_last_arg_is_spread()1992 bool only_last_arg_is_spread() {
1993 return !arguments_->is_empty() && arguments_->last()->IsSpread();
1994 }
1995
1996 private:
1997 friend class AstNodeFactory;
1998
CallNew(Expression * expression,ZoneList<Expression * > * arguments,int pos)1999 CallNew(Expression* expression, ZoneList<Expression*>* arguments, int pos)
2000 : Expression(pos, kCallNew),
2001 expression_(expression),
2002 arguments_(arguments) {
2003 bit_field_ |= IsMonomorphicField::encode(false);
2004 }
2005
parent_num_ids()2006 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)2007 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2008
2009 FeedbackSlot callnew_feedback_slot_;
2010 Expression* expression_;
2011 ZoneList<Expression*>* arguments_;
2012 Handle<JSFunction> target_;
2013 Handle<AllocationSite> allocation_site_;
2014
2015 class IsMonomorphicField
2016 : public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
2017 };
2018
2019
2020 // The CallRuntime class does not represent any official JavaScript
2021 // language construct. Instead it is used to call a C or JS function
2022 // with a set of arguments. This is used from the builtins that are
2023 // implemented in JavaScript (see "v8natives.js").
2024 class CallRuntime final : public Expression {
2025 public:
arguments()2026 ZoneList<Expression*>* arguments() const { return arguments_; }
is_jsruntime()2027 bool is_jsruntime() const { return function_ == NULL; }
2028
context_index()2029 int context_index() const {
2030 DCHECK(is_jsruntime());
2031 return context_index_;
2032 }
set_context_index(int index)2033 void set_context_index(int index) {
2034 DCHECK(is_jsruntime());
2035 context_index_ = index;
2036 }
function()2037 const Runtime::Function* function() const {
2038 DCHECK(!is_jsruntime());
2039 return function_;
2040 }
2041
num_ids()2042 static int num_ids() { return parent_num_ids() + 1; }
CallId()2043 BailoutId CallId() { return BailoutId(local_id(0)); }
2044 const char* debug_name();
2045
2046 private:
2047 friend class AstNodeFactory;
2048
CallRuntime(const Runtime::Function * function,ZoneList<Expression * > * arguments,int pos)2049 CallRuntime(const Runtime::Function* function,
2050 ZoneList<Expression*>* arguments, int pos)
2051 : Expression(pos, kCallRuntime),
2052 function_(function),
2053 arguments_(arguments) {}
CallRuntime(int context_index,ZoneList<Expression * > * arguments,int pos)2054 CallRuntime(int context_index, ZoneList<Expression*>* arguments, int pos)
2055 : Expression(pos, kCallRuntime),
2056 context_index_(context_index),
2057 function_(NULL),
2058 arguments_(arguments) {}
2059
parent_num_ids()2060 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)2061 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2062
2063 int context_index_;
2064 const Runtime::Function* function_;
2065 ZoneList<Expression*>* arguments_;
2066 };
2067
2068
2069 class UnaryOperation final : public Expression {
2070 public:
op()2071 Token::Value op() const { return OperatorField::decode(bit_field_); }
expression()2072 Expression* expression() const { return expression_; }
set_expression(Expression * e)2073 void set_expression(Expression* e) { expression_ = e; }
2074
2075 // For unary not (Token::NOT), the AST ids where true and false will
2076 // actually be materialized, respectively.
num_ids()2077 static int num_ids() { return parent_num_ids() + 2; }
MaterializeTrueId()2078 BailoutId MaterializeTrueId() const { return BailoutId(local_id(0)); }
MaterializeFalseId()2079 BailoutId MaterializeFalseId() const { return BailoutId(local_id(1)); }
2080
2081 void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
2082
2083 private:
2084 friend class AstNodeFactory;
2085
UnaryOperation(Token::Value op,Expression * expression,int pos)2086 UnaryOperation(Token::Value op, Expression* expression, int pos)
2087 : Expression(pos, kUnaryOperation), expression_(expression) {
2088 bit_field_ |= OperatorField::encode(op);
2089 DCHECK(Token::IsUnaryOp(op));
2090 }
2091
parent_num_ids()2092 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)2093 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2094
2095 Expression* expression_;
2096
2097 class OperatorField
2098 : public BitField<Token::Value, Expression::kNextBitFieldIndex, 7> {};
2099 };
2100
2101
2102 class BinaryOperation final : public Expression {
2103 public:
op()2104 Token::Value op() const { return OperatorField::decode(bit_field_); }
left()2105 Expression* left() const { return left_; }
set_left(Expression * e)2106 void set_left(Expression* e) { left_ = e; }
right()2107 Expression* right() const { return right_; }
set_right(Expression * e)2108 void set_right(Expression* e) { right_ = e; }
allocation_site()2109 Handle<AllocationSite> allocation_site() const { return allocation_site_; }
set_allocation_site(Handle<AllocationSite> allocation_site)2110 void set_allocation_site(Handle<AllocationSite> allocation_site) {
2111 allocation_site_ = allocation_site;
2112 }
2113
MarkTail()2114 void MarkTail() {
2115 switch (op()) {
2116 case Token::COMMA:
2117 case Token::AND:
2118 case Token::OR:
2119 right_->MarkTail();
2120 default:
2121 break;
2122 }
2123 }
2124
2125 // The short-circuit logical operations need an AST ID for their
2126 // right-hand subexpression.
num_ids()2127 static int num_ids() { return parent_num_ids() + 2; }
RightId()2128 BailoutId RightId() const { return BailoutId(local_id(0)); }
2129
2130 // BinaryOperation will have both a slot in the feedback vector and the
2131 // TypeFeedbackId to record the type information. TypeFeedbackId is used
2132 // by full codegen and the feedback vector slot is used by interpreter.
2133 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
2134 FeedbackSlotCache* cache);
2135
BinaryOperationFeedbackSlot()2136 FeedbackSlot BinaryOperationFeedbackSlot() const { return feedback_slot_; }
2137
BinaryOperationFeedbackId()2138 TypeFeedbackId BinaryOperationFeedbackId() const {
2139 return TypeFeedbackId(local_id(1));
2140 }
fixed_right_arg()2141 Maybe<int> fixed_right_arg() const {
2142 return has_fixed_right_arg_ ? Just(fixed_right_arg_value_) : Nothing<int>();
2143 }
set_fixed_right_arg(Maybe<int> arg)2144 void set_fixed_right_arg(Maybe<int> arg) {
2145 has_fixed_right_arg_ = arg.IsJust();
2146 if (arg.IsJust()) fixed_right_arg_value_ = arg.FromJust();
2147 }
2148
2149 void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
2150
2151 private:
2152 friend class AstNodeFactory;
2153
BinaryOperation(Token::Value op,Expression * left,Expression * right,int pos)2154 BinaryOperation(Token::Value op, Expression* left, Expression* right, int pos)
2155 : Expression(pos, kBinaryOperation),
2156 has_fixed_right_arg_(false),
2157 fixed_right_arg_value_(0),
2158 left_(left),
2159 right_(right) {
2160 bit_field_ |= OperatorField::encode(op);
2161 DCHECK(Token::IsBinaryOp(op));
2162 }
2163
parent_num_ids()2164 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)2165 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2166
2167 // TODO(rossberg): the fixed arg should probably be represented as a Constant
2168 // type for the RHS. Currenty it's actually a Maybe<int>
2169 bool has_fixed_right_arg_;
2170 int fixed_right_arg_value_;
2171 Expression* left_;
2172 Expression* right_;
2173 Handle<AllocationSite> allocation_site_;
2174 FeedbackSlot feedback_slot_;
2175
2176 class OperatorField
2177 : public BitField<Token::Value, Expression::kNextBitFieldIndex, 7> {};
2178 };
2179
2180
2181 class CountOperation final : public Expression {
2182 public:
is_prefix()2183 bool is_prefix() const { return IsPrefixField::decode(bit_field_); }
is_postfix()2184 bool is_postfix() const { return !is_prefix(); }
2185
op()2186 Token::Value op() const { return TokenField::decode(bit_field_); }
binary_op()2187 Token::Value binary_op() {
2188 return (op() == Token::INC) ? Token::ADD : Token::SUB;
2189 }
2190
expression()2191 Expression* expression() const { return expression_; }
set_expression(Expression * e)2192 void set_expression(Expression* e) { expression_ = e; }
2193
IsMonomorphic()2194 bool IsMonomorphic() const { return receiver_types_.length() == 1; }
GetReceiverTypes()2195 SmallMapList* GetReceiverTypes() { return &receiver_types_; }
GetKeyType()2196 IcCheckType GetKeyType() const { return KeyTypeField::decode(bit_field_); }
GetStoreMode()2197 KeyedAccessStoreMode GetStoreMode() const {
2198 return StoreModeField::decode(bit_field_);
2199 }
type()2200 AstType* type() const { return type_; }
set_key_type(IcCheckType type)2201 void set_key_type(IcCheckType type) {
2202 bit_field_ = KeyTypeField::update(bit_field_, type);
2203 }
set_store_mode(KeyedAccessStoreMode mode)2204 void set_store_mode(KeyedAccessStoreMode mode) {
2205 bit_field_ = StoreModeField::update(bit_field_, mode);
2206 }
set_type(AstType * type)2207 void set_type(AstType* type) { type_ = type; }
2208
num_ids()2209 static int num_ids() { return parent_num_ids() + 4; }
AssignmentId()2210 BailoutId AssignmentId() const { return BailoutId(local_id(0)); }
ToNumberId()2211 BailoutId ToNumberId() const { return BailoutId(local_id(1)); }
CountBinOpFeedbackId()2212 TypeFeedbackId CountBinOpFeedbackId() const {
2213 return TypeFeedbackId(local_id(2));
2214 }
CountStoreFeedbackId()2215 TypeFeedbackId CountStoreFeedbackId() const {
2216 return TypeFeedbackId(local_id(3));
2217 }
2218
2219 // Feedback slot for binary operation is only used by ignition.
CountBinaryOpFeedbackSlot()2220 FeedbackSlot CountBinaryOpFeedbackSlot() const {
2221 return binary_operation_slot_;
2222 }
2223
2224 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
2225 FeedbackSlotCache* cache);
CountSlot()2226 FeedbackSlot CountSlot() const { return slot_; }
2227
2228 private:
2229 friend class AstNodeFactory;
2230
CountOperation(Token::Value op,bool is_prefix,Expression * expr,int pos)2231 CountOperation(Token::Value op, bool is_prefix, Expression* expr, int pos)
2232 : Expression(pos, kCountOperation), type_(NULL), expression_(expr) {
2233 bit_field_ |=
2234 IsPrefixField::encode(is_prefix) | KeyTypeField::encode(ELEMENT) |
2235 StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op);
2236 }
2237
parent_num_ids()2238 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)2239 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2240
2241 class IsPrefixField
2242 : public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
2243 class KeyTypeField : public BitField<IcCheckType, IsPrefixField::kNext, 1> {};
2244 class StoreModeField
2245 : public BitField<KeyedAccessStoreMode, KeyTypeField::kNext, 3> {};
2246 class TokenField : public BitField<Token::Value, StoreModeField::kNext, 7> {};
2247
2248 FeedbackSlot slot_;
2249 FeedbackSlot binary_operation_slot_;
2250 AstType* type_;
2251 Expression* expression_;
2252 SmallMapList receiver_types_;
2253 };
2254
2255
2256 class CompareOperation final : public Expression {
2257 public:
op()2258 Token::Value op() const { return OperatorField::decode(bit_field_); }
left()2259 Expression* left() const { return left_; }
right()2260 Expression* right() const { return right_; }
2261
set_left(Expression * e)2262 void set_left(Expression* e) { left_ = e; }
set_right(Expression * e)2263 void set_right(Expression* e) { right_ = e; }
2264
2265 // Type feedback information.
num_ids()2266 static int num_ids() { return parent_num_ids() + 1; }
CompareOperationFeedbackId()2267 TypeFeedbackId CompareOperationFeedbackId() const {
2268 return TypeFeedbackId(local_id(0));
2269 }
combined_type()2270 AstType* combined_type() const { return combined_type_; }
set_combined_type(AstType * type)2271 void set_combined_type(AstType* type) { combined_type_ = type; }
2272
2273 // CompareOperation will have both a slot in the feedback vector and the
2274 // TypeFeedbackId to record the type information. TypeFeedbackId is used
2275 // by full codegen and the feedback vector slot is used by interpreter.
2276 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
2277 FeedbackSlotCache* cache);
2278
CompareOperationFeedbackSlot()2279 FeedbackSlot CompareOperationFeedbackSlot() const { return feedback_slot_; }
2280
2281 // Match special cases.
2282 bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
2283 bool IsLiteralCompareUndefined(Expression** expr);
2284 bool IsLiteralCompareNull(Expression** expr);
2285
2286 private:
2287 friend class AstNodeFactory;
2288
CompareOperation(Token::Value op,Expression * left,Expression * right,int pos)2289 CompareOperation(Token::Value op, Expression* left, Expression* right,
2290 int pos)
2291 : Expression(pos, kCompareOperation),
2292 left_(left),
2293 right_(right),
2294 combined_type_(AstType::None()) {
2295 bit_field_ |= OperatorField::encode(op);
2296 DCHECK(Token::IsCompareOp(op));
2297 }
2298
parent_num_ids()2299 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)2300 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2301
2302 Expression* left_;
2303 Expression* right_;
2304
2305 AstType* combined_type_;
2306 FeedbackSlot feedback_slot_;
2307 class OperatorField
2308 : public BitField<Token::Value, Expression::kNextBitFieldIndex, 7> {};
2309 };
2310
2311
2312 class Spread final : public Expression {
2313 public:
expression()2314 Expression* expression() const { return expression_; }
set_expression(Expression * e)2315 void set_expression(Expression* e) { expression_ = e; }
2316
expression_position()2317 int expression_position() const { return expr_pos_; }
2318
num_ids()2319 static int num_ids() { return parent_num_ids(); }
2320
2321 private:
2322 friend class AstNodeFactory;
2323
Spread(Expression * expression,int pos,int expr_pos)2324 Spread(Expression* expression, int pos, int expr_pos)
2325 : Expression(pos, kSpread),
2326 expr_pos_(expr_pos),
2327 expression_(expression) {}
2328
parent_num_ids()2329 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)2330 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2331
2332 int expr_pos_;
2333 Expression* expression_;
2334 };
2335
2336
2337 class Conditional final : public Expression {
2338 public:
condition()2339 Expression* condition() const { return condition_; }
then_expression()2340 Expression* then_expression() const { return then_expression_; }
else_expression()2341 Expression* else_expression() const { return else_expression_; }
2342
set_condition(Expression * e)2343 void set_condition(Expression* e) { condition_ = e; }
set_then_expression(Expression * e)2344 void set_then_expression(Expression* e) { then_expression_ = e; }
set_else_expression(Expression * e)2345 void set_else_expression(Expression* e) { else_expression_ = e; }
2346
MarkTail()2347 void MarkTail() {
2348 then_expression_->MarkTail();
2349 else_expression_->MarkTail();
2350 }
2351
num_ids()2352 static int num_ids() { return parent_num_ids() + 2; }
ThenId()2353 BailoutId ThenId() const { return BailoutId(local_id(0)); }
ElseId()2354 BailoutId ElseId() const { return BailoutId(local_id(1)); }
2355
2356 private:
2357 friend class AstNodeFactory;
2358
Conditional(Expression * condition,Expression * then_expression,Expression * else_expression,int position)2359 Conditional(Expression* condition, Expression* then_expression,
2360 Expression* else_expression, int position)
2361 : Expression(position, kConditional),
2362 condition_(condition),
2363 then_expression_(then_expression),
2364 else_expression_(else_expression) {}
2365
parent_num_ids()2366 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)2367 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2368
2369 Expression* condition_;
2370 Expression* then_expression_;
2371 Expression* else_expression_;
2372 };
2373
2374
2375 class Assignment final : public Expression {
2376 public:
AsSimpleAssignment()2377 Assignment* AsSimpleAssignment() { return !is_compound() ? this : NULL; }
2378
2379 Token::Value binary_op() const;
2380
op()2381 Token::Value op() const { return TokenField::decode(bit_field_); }
target()2382 Expression* target() const { return target_; }
value()2383 Expression* value() const { return value_; }
2384
set_target(Expression * e)2385 void set_target(Expression* e) { target_ = e; }
set_value(Expression * e)2386 void set_value(Expression* e) { value_ = e; }
2387
binary_operation()2388 BinaryOperation* binary_operation() const { return binary_operation_; }
2389
2390 // This check relies on the definition order of token in token.h.
is_compound()2391 bool is_compound() const { return op() > Token::ASSIGN; }
2392
num_ids()2393 static int num_ids() { return parent_num_ids() + 2; }
AssignmentId()2394 BailoutId AssignmentId() const { return BailoutId(local_id(0)); }
2395
2396 // Type feedback information.
AssignmentFeedbackId()2397 TypeFeedbackId AssignmentFeedbackId() { return TypeFeedbackId(local_id(1)); }
IsUninitialized()2398 bool IsUninitialized() const {
2399 return IsUninitializedField::decode(bit_field_);
2400 }
HasNoTypeInformation()2401 bool HasNoTypeInformation() {
2402 return IsUninitializedField::decode(bit_field_);
2403 }
IsMonomorphic()2404 bool IsMonomorphic() const { return receiver_types_.length() == 1; }
GetReceiverTypes()2405 SmallMapList* GetReceiverTypes() { return &receiver_types_; }
GetKeyType()2406 IcCheckType GetKeyType() const { return KeyTypeField::decode(bit_field_); }
GetStoreMode()2407 KeyedAccessStoreMode GetStoreMode() const {
2408 return StoreModeField::decode(bit_field_);
2409 }
set_is_uninitialized(bool b)2410 void set_is_uninitialized(bool b) {
2411 bit_field_ = IsUninitializedField::update(bit_field_, b);
2412 }
set_key_type(IcCheckType key_type)2413 void set_key_type(IcCheckType key_type) {
2414 bit_field_ = KeyTypeField::update(bit_field_, key_type);
2415 }
set_store_mode(KeyedAccessStoreMode mode)2416 void set_store_mode(KeyedAccessStoreMode mode) {
2417 bit_field_ = StoreModeField::update(bit_field_, mode);
2418 }
2419
2420 void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
2421 FeedbackSlotCache* cache);
AssignmentSlot()2422 FeedbackSlot AssignmentSlot() const { return slot_; }
2423
2424 private:
2425 friend class AstNodeFactory;
2426
2427 Assignment(Token::Value op, Expression* target, Expression* value, int pos);
2428
parent_num_ids()2429 static int parent_num_ids() { return Expression::num_ids(); }
local_id(int n)2430 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2431
2432 class IsUninitializedField
2433 : public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
2434 class KeyTypeField
2435 : public BitField<IcCheckType, IsUninitializedField::kNext, 1> {};
2436 class StoreModeField
2437 : public BitField<KeyedAccessStoreMode, KeyTypeField::kNext, 3> {};
2438 class TokenField : public BitField<Token::Value, StoreModeField::kNext, 7> {};
2439
2440 FeedbackSlot slot_;
2441 Expression* target_;
2442 Expression* value_;
2443 BinaryOperation* binary_operation_;
2444 SmallMapList receiver_types_;
2445 };
2446
2447
2448 // The RewritableExpression class is a wrapper for AST nodes that wait
2449 // for some potential rewriting. However, even if such nodes are indeed
2450 // rewritten, the RewritableExpression wrapper nodes will survive in the
2451 // final AST and should be just ignored, i.e., they should be treated as
2452 // equivalent to the wrapped nodes. For this reason and to simplify later
2453 // phases, RewritableExpressions are considered as exceptions of AST nodes
2454 // in the following sense:
2455 //
2456 // 1. IsRewritableExpression and AsRewritableExpression behave as usual.
2457 // 2. All other Is* and As* methods are practically delegated to the
2458 // wrapped node, i.e. IsArrayLiteral() will return true iff the
2459 // wrapped node is an array literal.
2460 //
2461 // Furthermore, an invariant that should be respected is that the wrapped
2462 // node is not a RewritableExpression.
2463 class RewritableExpression final : public Expression {
2464 public:
expression()2465 Expression* expression() const { return expr_; }
is_rewritten()2466 bool is_rewritten() const { return IsRewrittenField::decode(bit_field_); }
2467
Rewrite(Expression * new_expression)2468 void Rewrite(Expression* new_expression) {
2469 DCHECK(!is_rewritten());
2470 DCHECK_NOT_NULL(new_expression);
2471 DCHECK(!new_expression->IsRewritableExpression());
2472 expr_ = new_expression;
2473 bit_field_ = IsRewrittenField::update(bit_field_, true);
2474 }
2475
num_ids()2476 static int num_ids() { return parent_num_ids(); }
2477
2478 private:
2479 friend class AstNodeFactory;
2480
RewritableExpression(Expression * expression)2481 explicit RewritableExpression(Expression* expression)
2482 : Expression(expression->position(), kRewritableExpression),
2483 expr_(expression) {
2484 bit_field_ |= IsRewrittenField::encode(false);
2485 DCHECK(!expression->IsRewritableExpression());
2486 }
2487
local_id(int n)2488 int local_id(int n) const { return base_id() + parent_num_ids() + n; }
2489
2490 Expression* expr_;
2491
2492 class IsRewrittenField
2493 : public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
2494 };
2495
2496 // Our Yield is different from the JS yield in that it "returns" its argument as
2497 // is, without wrapping it in an iterator result object. Such wrapping, if
2498 // desired, must be done beforehand (see the parser).
2499 class Yield final : public Expression {
2500 public:
2501 enum OnException { kOnExceptionThrow, kOnExceptionRethrow };
2502
generator_object()2503 Expression* generator_object() const { return generator_object_; }
expression()2504 Expression* expression() const { return expression_; }
on_exception()2505 OnException on_exception() const {
2506 return OnExceptionField::decode(bit_field_);
2507 }
rethrow_on_exception()2508 bool rethrow_on_exception() const {
2509 return on_exception() == kOnExceptionRethrow;
2510 }
yield_id()2511 int yield_id() const { return yield_id_; }
2512
set_generator_object(Expression * e)2513 void set_generator_object(Expression* e) { generator_object_ = e; }
set_expression(Expression * e)2514 void set_expression(Expression* e) { expression_ = e; }
set_yield_id(int yield_id)2515 void set_yield_id(int yield_id) { yield_id_ = yield_id; }
2516
2517 private:
2518 friend class AstNodeFactory;
2519
Yield(Expression * generator_object,Expression * expression,int pos,OnException on_exception)2520 Yield(Expression* generator_object, Expression* expression, int pos,
2521 OnException on_exception)
2522 : Expression(pos, kYield),
2523 yield_id_(-1),
2524 generator_object_(generator_object),
2525 expression_(expression) {
2526 bit_field_ |= OnExceptionField::encode(on_exception);
2527 }
2528
2529 int yield_id_;
2530 Expression* generator_object_;
2531 Expression* expression_;
2532
2533 class OnExceptionField
2534 : public BitField<OnException, Expression::kNextBitFieldIndex, 1> {};
2535 };
2536
2537
2538 class Throw final : public Expression {
2539 public:
exception()2540 Expression* exception() const { return exception_; }
set_exception(Expression * e)2541 void set_exception(Expression* e) { exception_ = e; }
2542
2543 private:
2544 friend class AstNodeFactory;
2545
Throw(Expression * exception,int pos)2546 Throw(Expression* exception, int pos)
2547 : Expression(pos, kThrow), exception_(exception) {}
2548
2549 Expression* exception_;
2550 };
2551
2552
2553 class FunctionLiteral final : public Expression {
2554 public:
2555 enum FunctionType {
2556 kAnonymousExpression,
2557 kNamedExpression,
2558 kDeclaration,
2559 kAccessorOrMethod
2560 };
2561
2562 enum IdType { kIdTypeInvalid = -1, kIdTypeTopLevel = 0 };
2563
2564 enum ParameterFlag { kNoDuplicateParameters, kHasDuplicateParameters };
2565
2566 enum EagerCompileHint { kShouldEagerCompile, kShouldLazyCompile };
2567
name()2568 Handle<String> name() const { return raw_name_->string(); }
raw_name()2569 const AstString* raw_name() const { return raw_name_; }
set_raw_name(const AstString * name)2570