|
1 /* |
|
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) |
|
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) |
|
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
|
5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) |
|
6 * Copyright (C) 2007 Maks Orlovich |
|
7 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> |
|
8 * |
|
9 * This library is free software; you can redistribute it and/or |
|
10 * modify it under the terms of the GNU Library General Public |
|
11 * License as published by the Free Software Foundation; either |
|
12 * version 2 of the License, or (at your option) any later version. |
|
13 * |
|
14 * This library is distributed in the hope that it will be useful, |
|
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
17 * Library General Public License for more details. |
|
18 * |
|
19 * You should have received a copy of the GNU Library General Public License |
|
20 * along with this library; see the file COPYING.LIB. If not, write to |
|
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
22 * Boston, MA 02110-1301, USA. |
|
23 * |
|
24 */ |
|
25 |
|
26 #ifndef Nodes_h |
|
27 #define Nodes_h |
|
28 |
|
29 #include "Error.h" |
|
30 #include "JITCode.h" |
|
31 #include "Opcode.h" |
|
32 #include "ParserArena.h" |
|
33 #include "ResultType.h" |
|
34 #include "SourceCode.h" |
|
35 #include "SymbolTable.h" |
|
36 #include <wtf/MathExtras.h> |
|
37 |
|
38 namespace JSC { |
|
39 |
|
40 class ArgumentListNode; |
|
41 class BytecodeGenerator; |
|
42 class FunctionBodyNode; |
|
43 class Label; |
|
44 class PropertyListNode; |
|
45 class ReadModifyResolveNode; |
|
46 class RegisterID; |
|
47 class ScopeChainNode; |
|
48 class ScopeNode; |
|
49 |
|
50 typedef unsigned CodeFeatures; |
|
51 |
|
52 const CodeFeatures NoFeatures = 0; |
|
53 const CodeFeatures EvalFeature = 1 << 0; |
|
54 const CodeFeatures ClosureFeature = 1 << 1; |
|
55 const CodeFeatures AssignFeature = 1 << 2; |
|
56 const CodeFeatures ArgumentsFeature = 1 << 3; |
|
57 const CodeFeatures WithFeature = 1 << 4; |
|
58 const CodeFeatures CatchFeature = 1 << 5; |
|
59 const CodeFeatures ThisFeature = 1 << 6; |
|
60 const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature; |
|
61 |
|
62 enum Operator { |
|
63 OpEqual, |
|
64 OpPlusEq, |
|
65 OpMinusEq, |
|
66 OpMultEq, |
|
67 OpDivEq, |
|
68 OpPlusPlus, |
|
69 OpMinusMinus, |
|
70 OpAndEq, |
|
71 OpXOrEq, |
|
72 OpOrEq, |
|
73 OpModEq, |
|
74 OpLShift, |
|
75 OpRShift, |
|
76 OpURShift |
|
77 }; |
|
78 |
|
79 enum LogicalOperator { |
|
80 OpLogicalAnd, |
|
81 OpLogicalOr |
|
82 }; |
|
83 |
|
84 namespace DeclarationStacks { |
|
85 enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; |
|
86 typedef Vector<std::pair<const Identifier*, unsigned> > VarStack; |
|
87 typedef Vector<FunctionBodyNode*> FunctionStack; |
|
88 } |
|
89 |
|
90 struct SwitchInfo { |
|
91 enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString }; |
|
92 uint32_t bytecodeOffset; |
|
93 SwitchType switchType; |
|
94 }; |
|
95 |
|
96 class ParserArenaFreeable { |
|
97 public: |
|
98 // ParserArenaFreeable objects are are freed when the arena is deleted. |
|
99 // Destructors are not called. Clients must not call delete on such objects. |
|
100 void* operator new(size_t, JSGlobalData*); |
|
101 }; |
|
102 |
|
103 class ParserArenaDeletable { |
|
104 public: |
|
105 virtual ~ParserArenaDeletable() { } |
|
106 |
|
107 // ParserArenaDeletable objects are deleted when the arena is deleted. |
|
108 // Clients must not call delete directly on such objects. |
|
109 void* operator new(size_t, JSGlobalData*); |
|
110 }; |
|
111 |
|
112 class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> { |
|
113 protected: |
|
114 ParserArenaRefCounted(JSGlobalData*); |
|
115 |
|
116 public: |
|
117 virtual ~ParserArenaRefCounted() |
|
118 { |
|
119 ASSERT(deletionHasBegun()); |
|
120 } |
|
121 }; |
|
122 |
|
123 class Node : public ParserArenaFreeable { |
|
124 protected: |
|
125 Node(JSGlobalData*); |
|
126 |
|
127 public: |
|
128 virtual ~Node() { } |
|
129 |
|
130 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; |
|
131 |
|
132 int lineNo() const { return m_line; } |
|
133 |
|
134 protected: |
|
135 int m_line; |
|
136 }; |
|
137 |
|
138 class ExpressionNode : public Node { |
|
139 protected: |
|
140 ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType()); |
|
141 |
|
142 public: |
|
143 virtual bool isNumber() const { return false; } |
|
144 virtual bool isString() const { return false; } |
|
145 virtual bool isNull() const { return false; } |
|
146 virtual bool isPure(BytecodeGenerator&) const { return false; } |
|
147 virtual bool isLocation() const { return false; } |
|
148 virtual bool isResolveNode() const { return false; } |
|
149 virtual bool isBracketAccessorNode() const { return false; } |
|
150 virtual bool isDotAccessorNode() const { return false; } |
|
151 virtual bool isFuncExprNode() const { return false; } |
|
152 virtual bool isCommaNode() const { return false; } |
|
153 virtual bool isSimpleArray() const { return false; } |
|
154 virtual bool isAdd() const { return false; } |
|
155 virtual bool isSubtract() const { return false; } |
|
156 virtual bool hasConditionContextCodegen() const { return false; } |
|
157 |
|
158 virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); } |
|
159 |
|
160 virtual ExpressionNode* stripUnaryPlus() { return this; } |
|
161 |
|
162 ResultType resultDescriptor() const { return m_resultType; } |
|
163 |
|
164 private: |
|
165 ResultType m_resultType; |
|
166 }; |
|
167 |
|
168 class StatementNode : public Node { |
|
169 protected: |
|
170 StatementNode(JSGlobalData*); |
|
171 |
|
172 public: |
|
173 void setLoc(int firstLine, int lastLine); |
|
174 int firstLine() const { return lineNo(); } |
|
175 int lastLine() const { return m_lastLine; } |
|
176 |
|
177 virtual bool isEmptyStatement() const { return false; } |
|
178 virtual bool isReturnNode() const { return false; } |
|
179 virtual bool isExprStatement() const { return false; } |
|
180 |
|
181 virtual bool isBlock() const { return false; } |
|
182 |
|
183 private: |
|
184 int m_lastLine; |
|
185 }; |
|
186 |
|
187 class NullNode : public ExpressionNode { |
|
188 public: |
|
189 NullNode(JSGlobalData*); |
|
190 |
|
191 private: |
|
192 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
193 |
|
194 virtual bool isNull() const { return true; } |
|
195 }; |
|
196 |
|
197 class BooleanNode : public ExpressionNode { |
|
198 public: |
|
199 BooleanNode(JSGlobalData*, bool value); |
|
200 |
|
201 private: |
|
202 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
203 |
|
204 virtual bool isPure(BytecodeGenerator&) const { return true; } |
|
205 |
|
206 bool m_value; |
|
207 }; |
|
208 |
|
209 class NumberNode : public ExpressionNode { |
|
210 public: |
|
211 NumberNode(JSGlobalData*, double value); |
|
212 |
|
213 double value() const { return m_value; } |
|
214 void setValue(double value) { m_value = value; } |
|
215 |
|
216 private: |
|
217 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
218 |
|
219 virtual bool isNumber() const { return true; } |
|
220 virtual bool isPure(BytecodeGenerator&) const { return true; } |
|
221 |
|
222 double m_value; |
|
223 }; |
|
224 |
|
225 class StringNode : public ExpressionNode { |
|
226 public: |
|
227 StringNode(JSGlobalData*, const Identifier&); |
|
228 |
|
229 const Identifier& value() { return m_value; } |
|
230 |
|
231 private: |
|
232 virtual bool isPure(BytecodeGenerator&) const { return true; } |
|
233 |
|
234 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
235 |
|
236 virtual bool isString() const { return true; } |
|
237 |
|
238 const Identifier& m_value; |
|
239 }; |
|
240 |
|
241 class ThrowableExpressionData { |
|
242 public: |
|
243 ThrowableExpressionData() |
|
244 : m_divot(static_cast<uint32_t>(-1)) |
|
245 , m_startOffset(static_cast<uint16_t>(-1)) |
|
246 , m_endOffset(static_cast<uint16_t>(-1)) |
|
247 { |
|
248 } |
|
249 |
|
250 ThrowableExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) |
|
251 : m_divot(divot) |
|
252 , m_startOffset(startOffset) |
|
253 , m_endOffset(endOffset) |
|
254 { |
|
255 } |
|
256 |
|
257 void setExceptionSourceCode(unsigned divot, unsigned startOffset, unsigned endOffset) |
|
258 { |
|
259 m_divot = divot; |
|
260 m_startOffset = startOffset; |
|
261 m_endOffset = endOffset; |
|
262 } |
|
263 |
|
264 uint32_t divot() const { return m_divot; } |
|
265 uint16_t startOffset() const { return m_startOffset; } |
|
266 uint16_t endOffset() const { return m_endOffset; } |
|
267 |
|
268 protected: |
|
269 RegisterID* emitThrowError(BytecodeGenerator&, bool isReferenceError, const char* message); |
|
270 RegisterID* emitThrowError(BytecodeGenerator&, bool isReferenceError, const char* message, const UString&); |
|
271 RegisterID* emitThrowError(BytecodeGenerator&, bool isReferenceError, const char* message, const Identifier&); |
|
272 |
|
273 private: |
|
274 uint32_t m_divot; |
|
275 uint16_t m_startOffset; |
|
276 uint16_t m_endOffset; |
|
277 }; |
|
278 |
|
279 class ThrowableSubExpressionData : public ThrowableExpressionData { |
|
280 public: |
|
281 ThrowableSubExpressionData() |
|
282 : m_subexpressionDivotOffset(0) |
|
283 , m_subexpressionEndOffset(0) |
|
284 { |
|
285 } |
|
286 |
|
287 ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) |
|
288 : ThrowableExpressionData(divot, startOffset, endOffset) |
|
289 , m_subexpressionDivotOffset(0) |
|
290 , m_subexpressionEndOffset(0) |
|
291 { |
|
292 } |
|
293 |
|
294 void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) |
|
295 { |
|
296 ASSERT(subexpressionDivot <= divot()); |
|
297 if ((divot() - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot |
|
298 return; |
|
299 m_subexpressionDivotOffset = divot() - subexpressionDivot; |
|
300 m_subexpressionEndOffset = subexpressionOffset; |
|
301 } |
|
302 |
|
303 protected: |
|
304 uint16_t m_subexpressionDivotOffset; |
|
305 uint16_t m_subexpressionEndOffset; |
|
306 }; |
|
307 |
|
308 class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData { |
|
309 public: |
|
310 ThrowablePrefixedSubExpressionData() |
|
311 : m_subexpressionDivotOffset(0) |
|
312 , m_subexpressionStartOffset(0) |
|
313 { |
|
314 } |
|
315 |
|
316 ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) |
|
317 : ThrowableExpressionData(divot, startOffset, endOffset) |
|
318 , m_subexpressionDivotOffset(0) |
|
319 , m_subexpressionStartOffset(0) |
|
320 { |
|
321 } |
|
322 |
|
323 void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) |
|
324 { |
|
325 ASSERT(subexpressionDivot >= divot()); |
|
326 if ((subexpressionDivot - divot()) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot |
|
327 return; |
|
328 m_subexpressionDivotOffset = subexpressionDivot - divot(); |
|
329 m_subexpressionStartOffset = subexpressionOffset; |
|
330 } |
|
331 |
|
332 protected: |
|
333 uint16_t m_subexpressionDivotOffset; |
|
334 uint16_t m_subexpressionStartOffset; |
|
335 }; |
|
336 |
|
337 class RegExpNode : public ExpressionNode, public ThrowableExpressionData { |
|
338 public: |
|
339 RegExpNode(JSGlobalData*, const Identifier& pattern, const Identifier& flags); |
|
340 |
|
341 private: |
|
342 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
343 |
|
344 const Identifier& m_pattern; |
|
345 const Identifier& m_flags; |
|
346 }; |
|
347 |
|
348 class ThisNode : public ExpressionNode { |
|
349 public: |
|
350 ThisNode(JSGlobalData*); |
|
351 |
|
352 private: |
|
353 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
354 }; |
|
355 |
|
356 class ResolveNode : public ExpressionNode { |
|
357 public: |
|
358 ResolveNode(JSGlobalData*, const Identifier&, int startOffset); |
|
359 |
|
360 const Identifier& identifier() const { return m_ident; } |
|
361 |
|
362 private: |
|
363 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
364 |
|
365 virtual bool isPure(BytecodeGenerator&) const ; |
|
366 virtual bool isLocation() const { return true; } |
|
367 virtual bool isResolveNode() const { return true; } |
|
368 |
|
369 const Identifier& m_ident; |
|
370 int32_t m_startOffset; |
|
371 }; |
|
372 |
|
373 class ElementNode : public ParserArenaFreeable { |
|
374 public: |
|
375 ElementNode(JSGlobalData*, int elision, ExpressionNode*); |
|
376 ElementNode(JSGlobalData*, ElementNode*, int elision, ExpressionNode*); |
|
377 |
|
378 int elision() const { return m_elision; } |
|
379 ExpressionNode* value() { return m_node; } |
|
380 ElementNode* next() { return m_next; } |
|
381 |
|
382 private: |
|
383 ElementNode* m_next; |
|
384 int m_elision; |
|
385 ExpressionNode* m_node; |
|
386 }; |
|
387 |
|
388 class ArrayNode : public ExpressionNode { |
|
389 public: |
|
390 ArrayNode(JSGlobalData*, int elision); |
|
391 ArrayNode(JSGlobalData*, ElementNode*); |
|
392 ArrayNode(JSGlobalData*, int elision, ElementNode*); |
|
393 |
|
394 ArgumentListNode* toArgumentList(JSGlobalData*) const; |
|
395 |
|
396 private: |
|
397 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
398 |
|
399 virtual bool isSimpleArray() const ; |
|
400 |
|
401 ElementNode* m_element; |
|
402 int m_elision; |
|
403 bool m_optional; |
|
404 }; |
|
405 |
|
406 class PropertyNode : public ParserArenaFreeable { |
|
407 public: |
|
408 enum Type { Constant = 1, Getter = 2, Setter = 4 }; |
|
409 |
|
410 PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type); |
|
411 PropertyNode(JSGlobalData*, double name, ExpressionNode* value, Type); |
|
412 |
|
413 const Identifier& name() const { return m_name; } |
|
414 Type type() const { return m_type; } |
|
415 |
|
416 private: |
|
417 friend class PropertyListNode; |
|
418 const Identifier& m_name; |
|
419 ExpressionNode* m_assign; |
|
420 Type m_type; |
|
421 }; |
|
422 |
|
423 class PropertyListNode : public Node { |
|
424 public: |
|
425 PropertyListNode(JSGlobalData*, PropertyNode*); |
|
426 PropertyListNode(JSGlobalData*, PropertyNode*, PropertyListNode*); |
|
427 |
|
428 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
429 |
|
430 private: |
|
431 PropertyNode* m_node; |
|
432 PropertyListNode* m_next; |
|
433 }; |
|
434 |
|
435 class ObjectLiteralNode : public ExpressionNode { |
|
436 public: |
|
437 ObjectLiteralNode(JSGlobalData*); |
|
438 ObjectLiteralNode(JSGlobalData*, PropertyListNode*); |
|
439 |
|
440 private: |
|
441 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
442 |
|
443 PropertyListNode* m_list; |
|
444 }; |
|
445 |
|
446 class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData { |
|
447 public: |
|
448 BracketAccessorNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments); |
|
449 |
|
450 ExpressionNode* base() const { return m_base; } |
|
451 ExpressionNode* subscript() const { return m_subscript; } |
|
452 |
|
453 private: |
|
454 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
455 |
|
456 virtual bool isLocation() const { return true; } |
|
457 virtual bool isBracketAccessorNode() const { return true; } |
|
458 |
|
459 ExpressionNode* m_base; |
|
460 ExpressionNode* m_subscript; |
|
461 bool m_subscriptHasAssignments; |
|
462 }; |
|
463 |
|
464 class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData { |
|
465 public: |
|
466 DotAccessorNode(JSGlobalData*, ExpressionNode* base, const Identifier&); |
|
467 |
|
468 ExpressionNode* base() const { return m_base; } |
|
469 const Identifier& identifier() const { return m_ident; } |
|
470 |
|
471 private: |
|
472 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
473 |
|
474 virtual bool isLocation() const { return true; } |
|
475 virtual bool isDotAccessorNode() const { return true; } |
|
476 |
|
477 ExpressionNode* m_base; |
|
478 const Identifier& m_ident; |
|
479 }; |
|
480 |
|
481 class ArgumentListNode : public Node { |
|
482 public: |
|
483 ArgumentListNode(JSGlobalData*, ExpressionNode*); |
|
484 ArgumentListNode(JSGlobalData*, ArgumentListNode*, ExpressionNode*); |
|
485 |
|
486 ArgumentListNode* m_next; |
|
487 ExpressionNode* m_expr; |
|
488 |
|
489 private: |
|
490 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
491 }; |
|
492 |
|
493 class ArgumentsNode : public ParserArenaFreeable { |
|
494 public: |
|
495 ArgumentsNode(JSGlobalData*); |
|
496 ArgumentsNode(JSGlobalData*, ArgumentListNode*); |
|
497 |
|
498 ArgumentListNode* m_listNode; |
|
499 }; |
|
500 |
|
501 class NewExprNode : public ExpressionNode, public ThrowableExpressionData { |
|
502 public: |
|
503 NewExprNode(JSGlobalData*, ExpressionNode*); |
|
504 NewExprNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*); |
|
505 |
|
506 private: |
|
507 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
508 |
|
509 ExpressionNode* m_expr; |
|
510 ArgumentsNode* m_args; |
|
511 }; |
|
512 |
|
513 class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { |
|
514 public: |
|
515 EvalFunctionCallNode(JSGlobalData*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
516 |
|
517 private: |
|
518 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
519 |
|
520 ArgumentsNode* m_args; |
|
521 }; |
|
522 |
|
523 class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData { |
|
524 public: |
|
525 FunctionCallValueNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
526 |
|
527 private: |
|
528 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
529 |
|
530 ExpressionNode* m_expr; |
|
531 ArgumentsNode* m_args; |
|
532 }; |
|
533 |
|
534 class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { |
|
535 public: |
|
536 FunctionCallResolveNode(JSGlobalData*, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
537 |
|
538 private: |
|
539 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
540 |
|
541 const Identifier& m_ident; |
|
542 ArgumentsNode* m_args; |
|
543 size_t m_index; // Used by LocalVarFunctionCallNode. |
|
544 size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode |
|
545 }; |
|
546 |
|
547 class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { |
|
548 public: |
|
549 FunctionCallBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
550 |
|
551 private: |
|
552 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
553 |
|
554 ExpressionNode* m_base; |
|
555 ExpressionNode* m_subscript; |
|
556 ArgumentsNode* m_args; |
|
557 }; |
|
558 |
|
559 class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { |
|
560 public: |
|
561 FunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
562 |
|
563 private: |
|
564 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
565 |
|
566 protected: |
|
567 ExpressionNode* m_base; |
|
568 const Identifier& m_ident; |
|
569 ArgumentsNode* m_args; |
|
570 }; |
|
571 |
|
572 class CallFunctionCallDotNode : public FunctionCallDotNode { |
|
573 public: |
|
574 CallFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
575 |
|
576 private: |
|
577 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
578 }; |
|
579 |
|
580 class ApplyFunctionCallDotNode : public FunctionCallDotNode { |
|
581 public: |
|
582 ApplyFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
583 |
|
584 private: |
|
585 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
586 }; |
|
587 |
|
588 class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData { |
|
589 public: |
|
590 PrePostResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
591 |
|
592 protected: |
|
593 const Identifier& m_ident; |
|
594 }; |
|
595 |
|
596 class PostfixResolveNode : public PrePostResolveNode { |
|
597 public: |
|
598 PostfixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
599 |
|
600 private: |
|
601 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
602 |
|
603 Operator m_operator; |
|
604 }; |
|
605 |
|
606 class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData { |
|
607 public: |
|
608 PostfixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
609 |
|
610 private: |
|
611 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
612 |
|
613 ExpressionNode* m_base; |
|
614 ExpressionNode* m_subscript; |
|
615 Operator m_operator; |
|
616 }; |
|
617 |
|
618 class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData { |
|
619 public: |
|
620 PostfixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
621 |
|
622 private: |
|
623 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
624 |
|
625 ExpressionNode* m_base; |
|
626 const Identifier& m_ident; |
|
627 Operator m_operator; |
|
628 }; |
|
629 |
|
630 class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData { |
|
631 public: |
|
632 PostfixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
633 |
|
634 private: |
|
635 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
636 |
|
637 ExpressionNode* m_expr; |
|
638 Operator m_operator; |
|
639 }; |
|
640 |
|
641 class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { |
|
642 public: |
|
643 DeleteResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
644 |
|
645 private: |
|
646 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
647 |
|
648 const Identifier& m_ident; |
|
649 }; |
|
650 |
|
651 class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { |
|
652 public: |
|
653 DeleteBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
654 |
|
655 private: |
|
656 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
657 |
|
658 ExpressionNode* m_base; |
|
659 ExpressionNode* m_subscript; |
|
660 }; |
|
661 |
|
662 class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { |
|
663 public: |
|
664 DeleteDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
665 |
|
666 private: |
|
667 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
668 |
|
669 ExpressionNode* m_base; |
|
670 const Identifier& m_ident; |
|
671 }; |
|
672 |
|
673 class DeleteValueNode : public ExpressionNode { |
|
674 public: |
|
675 DeleteValueNode(JSGlobalData*, ExpressionNode*); |
|
676 |
|
677 private: |
|
678 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
679 |
|
680 ExpressionNode* m_expr; |
|
681 }; |
|
682 |
|
683 class VoidNode : public ExpressionNode { |
|
684 public: |
|
685 VoidNode(JSGlobalData*, ExpressionNode*); |
|
686 |
|
687 private: |
|
688 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
689 |
|
690 ExpressionNode* m_expr; |
|
691 }; |
|
692 |
|
693 class TypeOfResolveNode : public ExpressionNode { |
|
694 public: |
|
695 TypeOfResolveNode(JSGlobalData*, const Identifier&); |
|
696 |
|
697 const Identifier& identifier() const { return m_ident; } |
|
698 |
|
699 private: |
|
700 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
701 |
|
702 const Identifier& m_ident; |
|
703 }; |
|
704 |
|
705 class TypeOfValueNode : public ExpressionNode { |
|
706 public: |
|
707 TypeOfValueNode(JSGlobalData*, ExpressionNode*); |
|
708 |
|
709 private: |
|
710 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
711 |
|
712 ExpressionNode* m_expr; |
|
713 }; |
|
714 |
|
715 class PrefixResolveNode : public PrePostResolveNode { |
|
716 public: |
|
717 PrefixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
718 |
|
719 private: |
|
720 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
721 |
|
722 Operator m_operator; |
|
723 }; |
|
724 |
|
725 class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { |
|
726 public: |
|
727 PrefixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
728 |
|
729 private: |
|
730 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
731 |
|
732 ExpressionNode* m_base; |
|
733 ExpressionNode* m_subscript; |
|
734 Operator m_operator; |
|
735 }; |
|
736 |
|
737 class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { |
|
738 public: |
|
739 PrefixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
740 |
|
741 private: |
|
742 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
743 |
|
744 ExpressionNode* m_base; |
|
745 const Identifier& m_ident; |
|
746 Operator m_operator; |
|
747 }; |
|
748 |
|
749 class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData { |
|
750 public: |
|
751 PrefixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
752 |
|
753 private: |
|
754 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
755 |
|
756 ExpressionNode* m_expr; |
|
757 Operator m_operator; |
|
758 }; |
|
759 |
|
760 class UnaryOpNode : public ExpressionNode { |
|
761 public: |
|
762 UnaryOpNode(JSGlobalData*, ResultType, ExpressionNode*, OpcodeID); |
|
763 |
|
764 protected: |
|
765 ExpressionNode* expr() { return m_expr; } |
|
766 const ExpressionNode* expr() const { return m_expr; } |
|
767 |
|
768 private: |
|
769 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
770 |
|
771 OpcodeID opcodeID() const { return m_opcodeID; } |
|
772 |
|
773 ExpressionNode* m_expr; |
|
774 OpcodeID m_opcodeID; |
|
775 }; |
|
776 |
|
777 class UnaryPlusNode : public UnaryOpNode { |
|
778 public: |
|
779 UnaryPlusNode(JSGlobalData*, ExpressionNode*); |
|
780 |
|
781 private: |
|
782 virtual ExpressionNode* stripUnaryPlus() { return expr(); } |
|
783 }; |
|
784 |
|
785 class NegateNode : public UnaryOpNode { |
|
786 public: |
|
787 NegateNode(JSGlobalData*, ExpressionNode*); |
|
788 }; |
|
789 |
|
790 class BitwiseNotNode : public UnaryOpNode { |
|
791 public: |
|
792 BitwiseNotNode(JSGlobalData*, ExpressionNode*); |
|
793 }; |
|
794 |
|
795 class LogicalNotNode : public UnaryOpNode { |
|
796 public: |
|
797 LogicalNotNode(JSGlobalData*, ExpressionNode*); |
|
798 private: |
|
799 void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); |
|
800 virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); } |
|
801 }; |
|
802 |
|
803 class BinaryOpNode : public ExpressionNode { |
|
804 public: |
|
805 BinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); |
|
806 BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); |
|
807 |
|
808 RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); |
|
809 |
|
810 ExpressionNode* lhs() { return m_expr1; }; |
|
811 ExpressionNode* rhs() { return m_expr2; }; |
|
812 |
|
813 private: |
|
814 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
815 |
|
816 protected: |
|
817 OpcodeID opcodeID() const { return m_opcodeID; } |
|
818 |
|
819 protected: |
|
820 ExpressionNode* m_expr1; |
|
821 ExpressionNode* m_expr2; |
|
822 private: |
|
823 OpcodeID m_opcodeID; |
|
824 protected: |
|
825 bool m_rightHasAssignments; |
|
826 }; |
|
827 |
|
828 class ReverseBinaryOpNode : public BinaryOpNode { |
|
829 public: |
|
830 ReverseBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); |
|
831 ReverseBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); |
|
832 |
|
833 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
834 }; |
|
835 |
|
836 class MultNode : public BinaryOpNode { |
|
837 public: |
|
838 MultNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
839 }; |
|
840 |
|
841 class DivNode : public BinaryOpNode { |
|
842 public: |
|
843 DivNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
844 }; |
|
845 |
|
846 class ModNode : public BinaryOpNode { |
|
847 public: |
|
848 ModNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
849 }; |
|
850 |
|
851 class AddNode : public BinaryOpNode { |
|
852 public: |
|
853 AddNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
854 |
|
855 virtual bool isAdd() const { return true; } |
|
856 }; |
|
857 |
|
858 class SubNode : public BinaryOpNode { |
|
859 public: |
|
860 SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
861 |
|
862 virtual bool isSubtract() const { return true; } |
|
863 }; |
|
864 |
|
865 class LeftShiftNode : public BinaryOpNode { |
|
866 public: |
|
867 LeftShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
868 }; |
|
869 |
|
870 class RightShiftNode : public BinaryOpNode { |
|
871 public: |
|
872 RightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
873 }; |
|
874 |
|
875 class UnsignedRightShiftNode : public BinaryOpNode { |
|
876 public: |
|
877 UnsignedRightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
878 }; |
|
879 |
|
880 class LessNode : public BinaryOpNode { |
|
881 public: |
|
882 LessNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
883 }; |
|
884 |
|
885 class GreaterNode : public ReverseBinaryOpNode { |
|
886 public: |
|
887 GreaterNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
888 }; |
|
889 |
|
890 class LessEqNode : public BinaryOpNode { |
|
891 public: |
|
892 LessEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
893 }; |
|
894 |
|
895 class GreaterEqNode : public ReverseBinaryOpNode { |
|
896 public: |
|
897 GreaterEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
898 }; |
|
899 |
|
900 class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData { |
|
901 public: |
|
902 ThrowableBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); |
|
903 ThrowableBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); |
|
904 |
|
905 private: |
|
906 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
907 }; |
|
908 |
|
909 class InstanceOfNode : public ThrowableBinaryOpNode { |
|
910 public: |
|
911 InstanceOfNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
912 |
|
913 private: |
|
914 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
915 }; |
|
916 |
|
917 class InNode : public ThrowableBinaryOpNode { |
|
918 public: |
|
919 InNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
920 }; |
|
921 |
|
922 class EqualNode : public BinaryOpNode { |
|
923 public: |
|
924 EqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
925 |
|
926 private: |
|
927 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
928 }; |
|
929 |
|
930 class NotEqualNode : public BinaryOpNode { |
|
931 public: |
|
932 NotEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
933 }; |
|
934 |
|
935 class StrictEqualNode : public BinaryOpNode { |
|
936 public: |
|
937 StrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
938 |
|
939 private: |
|
940 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
941 }; |
|
942 |
|
943 class NotStrictEqualNode : public BinaryOpNode { |
|
944 public: |
|
945 NotStrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
946 }; |
|
947 |
|
948 class BitAndNode : public BinaryOpNode { |
|
949 public: |
|
950 BitAndNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
951 }; |
|
952 |
|
953 class BitOrNode : public BinaryOpNode { |
|
954 public: |
|
955 BitOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
956 }; |
|
957 |
|
958 class BitXOrNode : public BinaryOpNode { |
|
959 public: |
|
960 BitXOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); |
|
961 }; |
|
962 |
|
963 // m_expr1 && m_expr2, m_expr1 || m_expr2 |
|
964 class LogicalOpNode : public ExpressionNode { |
|
965 public: |
|
966 LogicalOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); |
|
967 |
|
968 private: |
|
969 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
970 void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); |
|
971 virtual bool hasConditionContextCodegen() const { return true; } |
|
972 |
|
973 ExpressionNode* m_expr1; |
|
974 ExpressionNode* m_expr2; |
|
975 LogicalOperator m_operator; |
|
976 }; |
|
977 |
|
978 // The ternary operator, "m_logical ? m_expr1 : m_expr2" |
|
979 class ConditionalNode : public ExpressionNode { |
|
980 public: |
|
981 ConditionalNode(JSGlobalData*, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); |
|
982 |
|
983 private: |
|
984 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
985 |
|
986 ExpressionNode* m_logical; |
|
987 ExpressionNode* m_expr1; |
|
988 ExpressionNode* m_expr2; |
|
989 }; |
|
990 |
|
991 class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { |
|
992 public: |
|
993 ReadModifyResolveNode(JSGlobalData*, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
994 |
|
995 private: |
|
996 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
997 |
|
998 const Identifier& m_ident; |
|
999 ExpressionNode* m_right; |
|
1000 size_t m_index; // Used by ReadModifyLocalVarNode. |
|
1001 Operator m_operator; |
|
1002 bool m_rightHasAssignments; |
|
1003 }; |
|
1004 |
|
1005 class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData { |
|
1006 public: |
|
1007 AssignResolveNode(JSGlobalData*, const Identifier&, ExpressionNode* right, bool rightHasAssignments); |
|
1008 |
|
1009 private: |
|
1010 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1011 |
|
1012 const Identifier& m_ident; |
|
1013 ExpressionNode* m_right; |
|
1014 size_t m_index; // Used by ReadModifyLocalVarNode. |
|
1015 bool m_rightHasAssignments; |
|
1016 }; |
|
1017 |
|
1018 class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { |
|
1019 public: |
|
1020 ReadModifyBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
1021 |
|
1022 private: |
|
1023 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1024 |
|
1025 ExpressionNode* m_base; |
|
1026 ExpressionNode* m_subscript; |
|
1027 ExpressionNode* m_right; |
|
1028 Operator m_operator : 30; |
|
1029 bool m_subscriptHasAssignments : 1; |
|
1030 bool m_rightHasAssignments : 1; |
|
1031 }; |
|
1032 |
|
1033 class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData { |
|
1034 public: |
|
1035 AssignBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
1036 |
|
1037 private: |
|
1038 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1039 |
|
1040 ExpressionNode* m_base; |
|
1041 ExpressionNode* m_subscript; |
|
1042 ExpressionNode* m_right; |
|
1043 bool m_subscriptHasAssignments : 1; |
|
1044 bool m_rightHasAssignments : 1; |
|
1045 }; |
|
1046 |
|
1047 class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { |
|
1048 public: |
|
1049 AssignDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
1050 |
|
1051 private: |
|
1052 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1053 |
|
1054 ExpressionNode* m_base; |
|
1055 const Identifier& m_ident; |
|
1056 ExpressionNode* m_right; |
|
1057 bool m_rightHasAssignments; |
|
1058 }; |
|
1059 |
|
1060 class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { |
|
1061 public: |
|
1062 ReadModifyDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
1063 |
|
1064 private: |
|
1065 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1066 |
|
1067 ExpressionNode* m_base; |
|
1068 const Identifier& m_ident; |
|
1069 ExpressionNode* m_right; |
|
1070 Operator m_operator : 31; |
|
1071 bool m_rightHasAssignments : 1; |
|
1072 }; |
|
1073 |
|
1074 class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData { |
|
1075 public: |
|
1076 AssignErrorNode(JSGlobalData*, ExpressionNode* left, Operator, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset); |
|
1077 |
|
1078 private: |
|
1079 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1080 |
|
1081 ExpressionNode* m_left; |
|
1082 Operator m_operator; |
|
1083 ExpressionNode* m_right; |
|
1084 }; |
|
1085 |
|
1086 typedef Vector<ExpressionNode*, 8> ExpressionVector; |
|
1087 |
|
1088 class CommaNode : public ExpressionNode, public ParserArenaDeletable { |
|
1089 public: |
|
1090 CommaNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2); |
|
1091 |
|
1092 using ParserArenaDeletable::operator new; |
|
1093 |
|
1094 void append(ExpressionNode* expr) { m_expressions.append(expr); } |
|
1095 |
|
1096 private: |
|
1097 virtual bool isCommaNode() const { return true; } |
|
1098 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1099 |
|
1100 ExpressionVector m_expressions; |
|
1101 }; |
|
1102 |
|
1103 class ConstDeclNode : public ExpressionNode { |
|
1104 public: |
|
1105 ConstDeclNode(JSGlobalData*, const Identifier&, ExpressionNode*); |
|
1106 |
|
1107 bool hasInitializer() const { return m_init; } |
|
1108 const Identifier& ident() { return m_ident; } |
|
1109 |
|
1110 private: |
|
1111 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1112 virtual RegisterID* emitCodeSingle(BytecodeGenerator&); |
|
1113 |
|
1114 const Identifier& m_ident; |
|
1115 |
|
1116 public: |
|
1117 ConstDeclNode* m_next; |
|
1118 |
|
1119 private: |
|
1120 ExpressionNode* m_init; |
|
1121 }; |
|
1122 |
|
1123 class ConstStatementNode : public StatementNode { |
|
1124 public: |
|
1125 ConstStatementNode(JSGlobalData*, ConstDeclNode* next); |
|
1126 |
|
1127 private: |
|
1128 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1129 |
|
1130 ConstDeclNode* m_next; |
|
1131 }; |
|
1132 |
|
1133 class SourceElements : public ParserArenaDeletable { |
|
1134 public: |
|
1135 SourceElements(JSGlobalData*); |
|
1136 |
|
1137 void append(StatementNode*); |
|
1138 |
|
1139 StatementNode* singleStatement() const; |
|
1140 StatementNode* lastStatement() const; |
|
1141 |
|
1142 void emitBytecode(BytecodeGenerator&, RegisterID* destination); |
|
1143 |
|
1144 private: |
|
1145 Vector<StatementNode*> m_statements; |
|
1146 }; |
|
1147 |
|
1148 class BlockNode : public StatementNode { |
|
1149 public: |
|
1150 BlockNode(JSGlobalData*, SourceElements* = 0); |
|
1151 |
|
1152 StatementNode* singleStatement() const; |
|
1153 StatementNode* lastStatement() const; |
|
1154 |
|
1155 private: |
|
1156 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1157 |
|
1158 virtual bool isBlock() const { return true; } |
|
1159 |
|
1160 SourceElements* m_statements; |
|
1161 }; |
|
1162 |
|
1163 class EmptyStatementNode : public StatementNode { |
|
1164 public: |
|
1165 EmptyStatementNode(JSGlobalData*); |
|
1166 |
|
1167 private: |
|
1168 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1169 |
|
1170 virtual bool isEmptyStatement() const { return true; } |
|
1171 }; |
|
1172 |
|
1173 class DebuggerStatementNode : public StatementNode { |
|
1174 public: |
|
1175 DebuggerStatementNode(JSGlobalData*); |
|
1176 |
|
1177 private: |
|
1178 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1179 }; |
|
1180 |
|
1181 class ExprStatementNode : public StatementNode { |
|
1182 public: |
|
1183 ExprStatementNode(JSGlobalData*, ExpressionNode*); |
|
1184 |
|
1185 ExpressionNode* expr() const { return m_expr; } |
|
1186 |
|
1187 private: |
|
1188 virtual bool isExprStatement() const { return true; } |
|
1189 |
|
1190 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1191 |
|
1192 ExpressionNode* m_expr; |
|
1193 }; |
|
1194 |
|
1195 class VarStatementNode : public StatementNode { |
|
1196 public: |
|
1197 VarStatementNode(JSGlobalData*, ExpressionNode*); |
|
1198 |
|
1199 private: |
|
1200 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1201 |
|
1202 ExpressionNode* m_expr; |
|
1203 }; |
|
1204 |
|
1205 class IfNode : public StatementNode { |
|
1206 public: |
|
1207 IfNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock); |
|
1208 |
|
1209 protected: |
|
1210 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1211 |
|
1212 ExpressionNode* m_condition; |
|
1213 StatementNode* m_ifBlock; |
|
1214 }; |
|
1215 |
|
1216 class IfElseNode : public IfNode { |
|
1217 public: |
|
1218 IfElseNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); |
|
1219 |
|
1220 private: |
|
1221 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1222 |
|
1223 StatementNode* m_elseBlock; |
|
1224 }; |
|
1225 |
|
1226 class DoWhileNode : public StatementNode { |
|
1227 public: |
|
1228 DoWhileNode(JSGlobalData*, StatementNode* statement, ExpressionNode*); |
|
1229 |
|
1230 private: |
|
1231 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1232 |
|
1233 StatementNode* m_statement; |
|
1234 ExpressionNode* m_expr; |
|
1235 }; |
|
1236 |
|
1237 class WhileNode : public StatementNode { |
|
1238 public: |
|
1239 WhileNode(JSGlobalData*, ExpressionNode*, StatementNode* statement); |
|
1240 |
|
1241 private: |
|
1242 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1243 |
|
1244 ExpressionNode* m_expr; |
|
1245 StatementNode* m_statement; |
|
1246 }; |
|
1247 |
|
1248 class ForNode : public StatementNode { |
|
1249 public: |
|
1250 ForNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl); |
|
1251 |
|
1252 private: |
|
1253 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1254 |
|
1255 ExpressionNode* m_expr1; |
|
1256 ExpressionNode* m_expr2; |
|
1257 ExpressionNode* m_expr3; |
|
1258 StatementNode* m_statement; |
|
1259 bool m_expr1WasVarDecl; |
|
1260 }; |
|
1261 |
|
1262 class ForInNode : public StatementNode, public ThrowableExpressionData { |
|
1263 public: |
|
1264 ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*); |
|
1265 ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset); |
|
1266 |
|
1267 private: |
|
1268 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1269 |
|
1270 const Identifier& m_ident; |
|
1271 ExpressionNode* m_init; |
|
1272 ExpressionNode* m_lexpr; |
|
1273 ExpressionNode* m_expr; |
|
1274 StatementNode* m_statement; |
|
1275 bool m_identIsVarDecl; |
|
1276 }; |
|
1277 |
|
1278 class ContinueNode : public StatementNode, public ThrowableExpressionData { |
|
1279 public: |
|
1280 ContinueNode(JSGlobalData*); |
|
1281 ContinueNode(JSGlobalData*, const Identifier&); |
|
1282 |
|
1283 private: |
|
1284 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1285 |
|
1286 const Identifier& m_ident; |
|
1287 }; |
|
1288 |
|
1289 class BreakNode : public StatementNode, public ThrowableExpressionData { |
|
1290 public: |
|
1291 BreakNode(JSGlobalData*); |
|
1292 BreakNode(JSGlobalData*, const Identifier&); |
|
1293 |
|
1294 private: |
|
1295 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1296 |
|
1297 const Identifier& m_ident; |
|
1298 }; |
|
1299 |
|
1300 class ReturnNode : public StatementNode, public ThrowableExpressionData { |
|
1301 public: |
|
1302 ReturnNode(JSGlobalData*, ExpressionNode* value); |
|
1303 |
|
1304 ExpressionNode* value() { return m_value; } |
|
1305 |
|
1306 private: |
|
1307 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1308 |
|
1309 virtual bool isReturnNode() const { return true; } |
|
1310 |
|
1311 ExpressionNode* m_value; |
|
1312 }; |
|
1313 |
|
1314 class WithNode : public StatementNode { |
|
1315 public: |
|
1316 WithNode(JSGlobalData*, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength); |
|
1317 |
|
1318 private: |
|
1319 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1320 |
|
1321 ExpressionNode* m_expr; |
|
1322 StatementNode* m_statement; |
|
1323 uint32_t m_divot; |
|
1324 uint32_t m_expressionLength; |
|
1325 }; |
|
1326 |
|
1327 class LabelNode : public StatementNode, public ThrowableExpressionData { |
|
1328 public: |
|
1329 LabelNode(JSGlobalData*, const Identifier& name, StatementNode*); |
|
1330 |
|
1331 private: |
|
1332 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1333 |
|
1334 const Identifier& m_name; |
|
1335 StatementNode* m_statement; |
|
1336 }; |
|
1337 |
|
1338 class ThrowNode : public StatementNode, public ThrowableExpressionData { |
|
1339 public: |
|
1340 ThrowNode(JSGlobalData*, ExpressionNode*); |
|
1341 |
|
1342 private: |
|
1343 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1344 |
|
1345 ExpressionNode* m_expr; |
|
1346 }; |
|
1347 |
|
1348 class TryNode : public StatementNode { |
|
1349 public: |
|
1350 TryNode(JSGlobalData*, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock); |
|
1351 |
|
1352 private: |
|
1353 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1354 |
|
1355 StatementNode* m_tryBlock; |
|
1356 const Identifier& m_exceptionIdent; |
|
1357 StatementNode* m_catchBlock; |
|
1358 StatementNode* m_finallyBlock; |
|
1359 bool m_catchHasEval; |
|
1360 }; |
|
1361 |
|
1362 class ParameterNode : public ParserArenaFreeable { |
|
1363 public: |
|
1364 ParameterNode(JSGlobalData*, const Identifier&); |
|
1365 ParameterNode(JSGlobalData*, ParameterNode*, const Identifier&); |
|
1366 |
|
1367 const Identifier& ident() const { return m_ident; } |
|
1368 ParameterNode* nextParam() const { return m_next; } |
|
1369 |
|
1370 private: |
|
1371 const Identifier& m_ident; |
|
1372 ParameterNode* m_next; |
|
1373 }; |
|
1374 |
|
1375 struct ScopeNodeData : FastAllocBase { |
|
1376 typedef DeclarationStacks::VarStack VarStack; |
|
1377 typedef DeclarationStacks::FunctionStack FunctionStack; |
|
1378 |
|
1379 ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, int numConstants); |
|
1380 |
|
1381 ParserArena m_arena; |
|
1382 VarStack m_varStack; |
|
1383 FunctionStack m_functionStack; |
|
1384 int m_numConstants; |
|
1385 SourceElements* m_statements; |
|
1386 }; |
|
1387 |
|
1388 class ScopeNode : public StatementNode, public ParserArenaRefCounted { |
|
1389 public: |
|
1390 typedef DeclarationStacks::VarStack VarStack; |
|
1391 typedef DeclarationStacks::FunctionStack FunctionStack; |
|
1392 |
|
1393 ScopeNode(JSGlobalData*); |
|
1394 ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants); |
|
1395 |
|
1396 using ParserArenaRefCounted::operator new; |
|
1397 |
|
1398 ScopeNodeData* data() const { return m_data.get(); } |
|
1399 void destroyData() { m_data.clear(); } |
|
1400 |
|
1401 const SourceCode& source() const { return m_source; } |
|
1402 const UString& sourceURL() const { return m_source.provider()->url(); } |
|
1403 intptr_t sourceID() const { return m_source.provider()->asID(); } |
|
1404 |
|
1405 void setFeatures(CodeFeatures features) { m_features = features; } |
|
1406 CodeFeatures features() { return m_features; } |
|
1407 |
|
1408 bool usesEval() const { return m_features & EvalFeature; } |
|
1409 bool usesArguments() const { return m_features & ArgumentsFeature; } |
|
1410 void setUsesArguments() { m_features |= ArgumentsFeature; } |
|
1411 bool usesThis() const { return m_features & ThisFeature; } |
|
1412 bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); } |
|
1413 |
|
1414 VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } |
|
1415 FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } |
|
1416 |
|
1417 int neededConstants() |
|
1418 { |
|
1419 ASSERT(m_data); |
|
1420 // We may need 2 more constants than the count given by the parser, |
|
1421 // because of the various uses of jsUndefined() and jsNull(). |
|
1422 return m_data->m_numConstants + 2; |
|
1423 } |
|
1424 |
|
1425 StatementNode* singleStatement() const; |
|
1426 |
|
1427 void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination); |
|
1428 |
|
1429 protected: |
|
1430 void setSource(const SourceCode& source) { m_source = source; } |
|
1431 |
|
1432 private: |
|
1433 OwnPtr<ScopeNodeData> m_data; |
|
1434 CodeFeatures m_features; |
|
1435 SourceCode m_source; |
|
1436 }; |
|
1437 |
|
1438 class ProgramNode : public ScopeNode { |
|
1439 public: |
|
1440 static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); |
|
1441 |
|
1442 static const bool scopeIsFunction = false; |
|
1443 |
|
1444 private: |
|
1445 ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); |
|
1446 |
|
1447 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1448 }; |
|
1449 |
|
1450 class EvalNode : public ScopeNode { |
|
1451 public: |
|
1452 static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); |
|
1453 |
|
1454 static const bool scopeIsFunction = false; |
|
1455 |
|
1456 private: |
|
1457 EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); |
|
1458 |
|
1459 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1460 }; |
|
1461 |
|
1462 class FunctionParameters : public Vector<Identifier>, public RefCounted<FunctionParameters> { |
|
1463 public: |
|
1464 static PassRefPtr<FunctionParameters> create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); } |
|
1465 |
|
1466 private: |
|
1467 FunctionParameters(ParameterNode*); |
|
1468 }; |
|
1469 |
|
1470 class FunctionBodyNode : public ScopeNode { |
|
1471 public: |
|
1472 static FunctionBodyNode* create(JSGlobalData*); |
|
1473 static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); |
|
1474 |
|
1475 FunctionParameters* parameters() const { return m_parameters.get(); } |
|
1476 size_t parameterCount() const { return m_parameters->size(); } |
|
1477 |
|
1478 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1479 |
|
1480 void finishParsing(const SourceCode&, ParameterNode*, const Identifier&); |
|
1481 void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&); |
|
1482 |
|
1483 const Identifier& ident() { return m_ident; } |
|
1484 |
|
1485 static const bool scopeIsFunction = true; |
|
1486 |
|
1487 private: |
|
1488 FunctionBodyNode(JSGlobalData*); |
|
1489 FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); |
|
1490 |
|
1491 Identifier m_ident; |
|
1492 RefPtr<FunctionParameters> m_parameters; |
|
1493 }; |
|
1494 |
|
1495 class FuncExprNode : public ExpressionNode { |
|
1496 public: |
|
1497 FuncExprNode(JSGlobalData*, const Identifier&, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0); |
|
1498 |
|
1499 FunctionBodyNode* body() { return m_body; } |
|
1500 |
|
1501 private: |
|
1502 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1503 |
|
1504 virtual bool isFuncExprNode() const { return true; } |
|
1505 |
|
1506 FunctionBodyNode* m_body; |
|
1507 }; |
|
1508 |
|
1509 class FuncDeclNode : public StatementNode { |
|
1510 public: |
|
1511 FuncDeclNode(JSGlobalData*, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); |
|
1512 |
|
1513 FunctionBodyNode* body() { return m_body; } |
|
1514 |
|
1515 private: |
|
1516 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1517 |
|
1518 FunctionBodyNode* m_body; |
|
1519 }; |
|
1520 |
|
1521 class CaseClauseNode : public ParserArenaFreeable { |
|
1522 public: |
|
1523 CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements* = 0); |
|
1524 |
|
1525 ExpressionNode* expr() const { return m_expr; } |
|
1526 |
|
1527 void emitBytecode(BytecodeGenerator&, RegisterID* destination); |
|
1528 |
|
1529 private: |
|
1530 ExpressionNode* m_expr; |
|
1531 SourceElements* m_statements; |
|
1532 }; |
|
1533 |
|
1534 class ClauseListNode : public ParserArenaFreeable { |
|
1535 public: |
|
1536 ClauseListNode(JSGlobalData*, CaseClauseNode*); |
|
1537 ClauseListNode(JSGlobalData*, ClauseListNode*, CaseClauseNode*); |
|
1538 |
|
1539 CaseClauseNode* getClause() const { return m_clause; } |
|
1540 ClauseListNode* getNext() const { return m_next; } |
|
1541 |
|
1542 private: |
|
1543 CaseClauseNode* m_clause; |
|
1544 ClauseListNode* m_next; |
|
1545 }; |
|
1546 |
|
1547 class CaseBlockNode : public ParserArenaFreeable { |
|
1548 public: |
|
1549 CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2); |
|
1550 |
|
1551 RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination); |
|
1552 |
|
1553 private: |
|
1554 SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num); |
|
1555 ClauseListNode* m_list1; |
|
1556 CaseClauseNode* m_defaultClause; |
|
1557 ClauseListNode* m_list2; |
|
1558 }; |
|
1559 |
|
1560 class SwitchNode : public StatementNode { |
|
1561 public: |
|
1562 SwitchNode(JSGlobalData*, ExpressionNode*, CaseBlockNode*); |
|
1563 |
|
1564 private: |
|
1565 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); |
|
1566 |
|
1567 ExpressionNode* m_expr; |
|
1568 CaseBlockNode* m_block; |
|
1569 }; |
|
1570 |
|
1571 struct ElementList { |
|
1572 ElementNode* head; |
|
1573 ElementNode* tail; |
|
1574 }; |
|
1575 |
|
1576 struct PropertyList { |
|
1577 PropertyListNode* head; |
|
1578 PropertyListNode* tail; |
|
1579 }; |
|
1580 |
|
1581 struct ArgumentList { |
|
1582 ArgumentListNode* head; |
|
1583 ArgumentListNode* tail; |
|
1584 }; |
|
1585 |
|
1586 struct ConstDeclList { |
|
1587 ConstDeclNode* head; |
|
1588 ConstDeclNode* tail; |
|
1589 }; |
|
1590 |
|
1591 struct ParameterList { |
|
1592 ParameterNode* head; |
|
1593 ParameterNode* tail; |
|
1594 }; |
|
1595 |
|
1596 struct ClauseList { |
|
1597 ClauseListNode* head; |
|
1598 ClauseListNode* tail; |
|
1599 }; |
|
1600 |
|
1601 } // namespace JSC |
|
1602 |
|
1603 #endif // Nodes_h |