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