source: webkit/trunk/JavaScriptCore/parser/Nodes.cpp@ 38247

Last change on this file since 38247 was 38247, checked in by Darin Adler, 17 years ago

JavaScriptCore:

2008-11-09 Darin Adler <Darin Adler>

Reviewed by Sam Weinig and Maciej Stachowiak.
Includes some work done by Chris Brichford.

Test: fast/js/large-expressions.html

1) Code generation is recursive, so takes stack proportional to the complexity

of the source code expression. Fixed by setting an arbitrary recursion limit
of 10,000 nodes.

2) Destruction of the syntax tree was recursive. Fixed by introducing a

non-recursive mechanism for destroying the tree.

  • bytecompiler/CodeGenerator.cpp: (JSC::CodeGenerator::CodeGenerator): Initialize depth to 0. (JSC::CodeGenerator::emitThrowExpressionTooDeepException): Added. Emits the code to throw a "too deep" exception.
  • bytecompiler/CodeGenerator.h: (JSC::CodeGenerator::emitNode): Check depth and emit an exception if we exceed the maximum depth.
  • parser/Nodes.cpp: (JSC::NodeReleaser::releaseAllNodes): Added. To be called inside node destructors to avoid recursive calls to destructors for nodes inside this one. (JSC::NodeReleaser::release): Added. To be called inside releaseNodes functions. Also added releaseNodes functions and calls to releaseAllNodes inside destructors for each class derived from Node that has RefPtr to other nodes. (JSC::NodeReleaser::adopt): Added. Used by the release function. (JSC::NodeReleaser::adoptFunctionBodyNode): Added.
  • parser/Nodes.h: Added declarations of releaseNodes and destructors in all classes that needed it. Eliminated use of ListRefPtr and releaseNext, which are the two parts of an older solution to the non-recursive destruction problem that works only for lists, whereas the new solution works for other graphs. Changed ReverseBinaryOpNode to use BinaryOpNode as a base class to avoid some duplicated code.

LayoutTests:

2008-11-09 Alexey Proskuryakov <[email protected]>

Reviewed by Darin Adler.

https://bugs.webkit.org/show_bug.cgi?id=22104
Javascript URL percent encoding/decoding broken by some characters

  • fast/loader/javascript-url-encoding-2-expected.txt:
  • fast/loader/javascript-url-encoding-2.html:
  • Property svn:eol-style set to native
File size: 90.1 KB
Line 
1/*
2* Copyright (C) 1999-2002 Harri Porten ([email protected])
3* Copyright (C) 2001 Peter Kelly ([email protected])
4* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5* Copyright (C) 2007 Cameron Zwarich ([email protected])
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <[email protected]>
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#include "config.h"
27#include "Nodes.h"
28
29#include "CodeGenerator.h"
30#include "ExecState.h"
31#include "JSGlobalObject.h"
32#include "JSStaticScopeObject.h"
33#include "LabelScope.h"
34#include "Parser.h"
35#include "PropertyNameArray.h"
36#include "RegExpObject.h"
37#include "SamplingTool.h"
38#include "Debugger.h"
39#include "Lexer.h"
40#include "Operations.h"
41#include <math.h>
42#include <wtf/Assertions.h>
43#include <wtf/HashCountedSet.h>
44#include <wtf/HashSet.h>
45#include <wtf/MathExtras.h>
46#include <wtf/RefCountedLeakCounter.h>
47#include <wtf/Threading.h>
48
49using namespace WTF;
50
51namespace JSC {
52
53static void substitute(UString& string, const UString& substring) JSC_FAST_CALL;
54
55// ------------------------------ NodeReleaser --------------------------------
56
57class NodeReleaser : Noncopyable {
58public:
59 // Call this function inside the destructor of a class derived from Node.
60 // This will traverse the tree below this node, destroying all of those nodes,
61 // but without relying on recursion.
62 static void releaseAllNodes(ParserRefCounted* root);
63
64 // Call this on each node in a the releaseNodes virtual function.
65 // It gives the node to the NodeReleaser, which will then release the
66 // node later at the end of the releaseAllNodes process.
67 template <typename T> void release(RefPtr<T>& node) { if (node) adopt(node.release()); }
68 void release(RefPtr<FunctionBodyNode>& node) { if (node) adoptFunctionBodyNode(node); }
69
70private:
71 NodeReleaser() { }
72 ~NodeReleaser() { }
73
74 void adopt(PassRefPtr<ParserRefCounted>);
75 void adoptFunctionBodyNode(RefPtr<FunctionBodyNode>&);
76
77 typedef Vector<RefPtr<ParserRefCounted> > NodeReleaseVector;
78 OwnPtr<NodeReleaseVector> m_vector;
79};
80
81void NodeReleaser::releaseAllNodes(ParserRefCounted* root)
82{
83 ASSERT(root);
84 NodeReleaser releaser;
85 root->releaseNodes(releaser);
86 if (!releaser.m_vector)
87 return;
88 // Note: The call to release.m_vector->size() is intentionally inside
89 // the loop, since calls to releaseNodes are expected to increase the size.
90 for (size_t i = 0; i < releaser.m_vector->size(); ++i) {
91 ParserRefCounted* node = (*releaser.m_vector)[i].get();
92 if (node->hasOneRef())
93 node->releaseNodes(releaser);
94 }
95}
96
97void NodeReleaser::adopt(PassRefPtr<ParserRefCounted> node)
98{
99 ASSERT(node);
100 if (!node->hasOneRef())
101 return;
102 if (!m_vector)
103 m_vector.set(new NodeReleaseVector);
104 m_vector->append(node);
105}
106
107void NodeReleaser::adoptFunctionBodyNode(RefPtr<FunctionBodyNode>& functionBodyNode)
108{
109 // This sidesteps a problem where if you assign a PassRefPtr<FunctionBodyNode>
110 // to a PassRefPtr<Node> we leave the two reference counts (FunctionBodyNode
111 // and ParserRefCounted) unbalanced. It would be nice to fix this problem in
112 // a cleaner way -- perhaps we could remove the FunctionBodyNode reference
113 // count at some point.
114 RefPtr<Node> node = functionBodyNode;
115 functionBodyNode = 0;
116 adopt(node.release());
117}
118
119// ------------------------------ ParserRefCounted -----------------------------------------
120
121#ifndef NDEBUG
122static RefCountedLeakCounter parserRefCountedCounter("JSC::Node");
123#endif
124
125ParserRefCounted::ParserRefCounted(JSGlobalData* globalData)
126 : m_globalData(globalData)
127{
128#ifndef NDEBUG
129 parserRefCountedCounter.increment();
130#endif
131 if (!m_globalData->newParserObjects)
132 m_globalData->newParserObjects = new HashSet<ParserRefCounted*>;
133 m_globalData->newParserObjects->add(this);
134 ASSERT(m_globalData->newParserObjects->contains(this));
135}
136
137ParserRefCounted::~ParserRefCounted()
138{
139#ifndef NDEBUG
140 parserRefCountedCounter.decrement();
141#endif
142}
143
144void ParserRefCounted::releaseNodes(NodeReleaser&)
145{
146}
147
148void ParserRefCounted::ref()
149{
150 // bumping from 0 to 1 is just removing from the new nodes set
151 if (m_globalData->newParserObjects) {
152 HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this);
153 if (it != m_globalData->newParserObjects->end()) {
154 m_globalData->newParserObjects->remove(it);
155 ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
156 return;
157 }
158 }
159
160 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
161
162 if (!m_globalData->parserObjectExtraRefCounts)
163 m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
164 m_globalData->parserObjectExtraRefCounts->add(this);
165}
166
167void ParserRefCounted::deref()
168{
169 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
170
171 if (!m_globalData->parserObjectExtraRefCounts) {
172 delete this;
173 return;
174 }
175
176 HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this);
177 if (it == m_globalData->parserObjectExtraRefCounts->end())
178 delete this;
179 else
180 m_globalData->parserObjectExtraRefCounts->remove(it);
181}
182
183bool ParserRefCounted::hasOneRef()
184{
185 if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) {
186 ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
187 return false;
188 }
189
190 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
191
192 if (!m_globalData->parserObjectExtraRefCounts)
193 return true;
194
195 return !m_globalData->parserObjectExtraRefCounts->contains(this);
196}
197
198void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData)
199{
200 if (!globalData->newParserObjects)
201 return;
202
203#ifndef NDEBUG
204 HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end();
205 for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it)
206 ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it));
207#endif
208 deleteAllValues(*globalData->newParserObjects);
209 delete globalData->newParserObjects;
210 globalData->newParserObjects = 0;
211}
212
213// ------------------------------ Node --------------------------------
214
215Node::Node(JSGlobalData* globalData)
216 : ParserRefCounted(globalData)
217{
218 m_line = globalData->lexer->lineNo();
219}
220
221// ------------------------------ ThrowableExpressionData --------------------------------
222
223static void substitute(UString& string, const UString& substring)
224{
225 int position = string.find("%s");
226 ASSERT(position != -1);
227 UString newString = string.substr(0, position);
228 newString.append(substring);
229 newString.append(string.substr(position + 2));
230 string = newString;
231}
232
233RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg)
234{
235 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
236 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg));
237 generator.emitThrow(exception);
238 return exception;
239}
240
241RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
242{
243 UString message = msg;
244 substitute(message, label.ustring());
245 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
246 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message));
247 generator.emitThrow(exception);
248 return exception;
249}
250
251// ------------------------------ StatementNode --------------------------------
252
253StatementNode::StatementNode(JSGlobalData* globalData)
254 : Node(globalData)
255 , m_lastLine(-1)
256{
257}
258
259void StatementNode::setLoc(int firstLine, int lastLine)
260{
261 m_line = firstLine;
262 m_lastLine = lastLine;
263}
264
265// ------------------------------ SourceElements --------------------------------
266
267void SourceElements::append(PassRefPtr<StatementNode> statement)
268{
269 if (statement->isEmptyStatement())
270 return;
271
272 m_statements.append(statement);
273}
274
275// ------------------------------ NullNode -------------------------------------
276
277RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst)
278{
279 if (dst == ignoredResult())
280 return 0;
281 return generator.emitLoad(dst, jsNull());
282}
283
284// ------------------------------ BooleanNode ----------------------------------
285
286RegisterID* BooleanNode::emitCode(CodeGenerator& generator, RegisterID* dst)
287{
288 if (dst == ignoredResult())
289 return 0;
290 return generator.emitLoad(dst, m_value);
291}
292
293// ------------------------------ NumberNode -----------------------------------
294
295RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst)
296{
297 if (dst == ignoredResult())
298 return 0;
299 return generator.emitLoad(dst, m_double);
300}
301
302// ------------------------------ StringNode -----------------------------------
303
304RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
305{
306 if (dst == ignoredResult())
307 return 0;
308 return generator.emitLoad(dst, m_value);
309}
310
311// ------------------------------ RegExpNode -----------------------------------
312
313RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
314{
315 RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
316 if (!regExp->isValid())
317 return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
318 if (dst == ignoredResult())
319 return 0;
320 return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
321}
322
323// ------------------------------ ThisNode -------------------------------------
324
325RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
326{
327 if (dst == ignoredResult())
328 return 0;
329 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
330}
331
332// ------------------------------ ResolveNode ----------------------------------
333
334bool ResolveNode::isPure(CodeGenerator& generator) const
335{
336 return generator.isLocal(m_ident);
337}
338
339RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
340{
341 if (RegisterID* local = generator.registerFor(m_ident)) {
342 if (dst == ignoredResult())
343 return 0;
344 return generator.moveToDestinationIfNeeded(dst, local);
345 }
346
347 generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
348 return generator.emitResolve(generator.finalDestination(dst), m_ident);
349}
350
351// ------------------------------ ElementNode ------------------------------------
352
353ElementNode::~ElementNode()
354{
355 NodeReleaser::releaseAllNodes(this);
356}
357
358void ElementNode::releaseNodes(NodeReleaser& releaser)
359{
360 releaser.release(m_next);
361 releaser.release(m_node);
362}
363
364// ------------------------------ ArrayNode ------------------------------------
365
366ArrayNode::~ArrayNode()
367{
368 NodeReleaser::releaseAllNodes(this);
369}
370
371void ArrayNode::releaseNodes(NodeReleaser& releaser)
372{
373 releaser.release(m_element);
374}
375
376RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst)
377{
378 // FIXME: Should we put all of this code into emitNewArray?
379
380 unsigned length = 0;
381 ElementNode* firstPutElement;
382 for (firstPutElement = m_element.get(); firstPutElement; firstPutElement = firstPutElement->next()) {
383 if (firstPutElement->elision())
384 break;
385 ++length;
386 }
387
388 if (!firstPutElement && !m_elision)
389 return generator.emitNewArray(generator.finalDestination(dst), m_element.get());
390
391 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get());
392
393 for (ElementNode* n = firstPutElement; n; n = n->next()) {
394 RegisterID* value = generator.emitNode(n->value());
395 length += n->elision();
396 generator.emitPutByIndex(array.get(), length++, value);
397 }
398
399 if (m_elision) {
400 RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
401 generator.emitPutById(array.get(), generator.propertyNames().length, value);
402 }
403
404 return generator.moveToDestinationIfNeeded(dst, array.get());
405}
406
407// ------------------------------ PropertyNode ----------------------------
408
409PropertyNode::~PropertyNode()
410{
411 NodeReleaser::releaseAllNodes(this);
412}
413
414void PropertyNode::releaseNodes(NodeReleaser& releaser)
415{
416 releaser.release(m_assign);
417}
418
419// ------------------------------ ObjectLiteralNode ----------------------------
420
421ObjectLiteralNode::~ObjectLiteralNode()
422{
423 NodeReleaser::releaseAllNodes(this);
424}
425
426void ObjectLiteralNode::releaseNodes(NodeReleaser& releaser)
427{
428 releaser.release(m_list);
429}
430
431RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst)
432{
433 if (!m_list) {
434 if (dst == ignoredResult())
435 return 0;
436 return generator.emitNewObject(generator.finalDestination(dst));
437 }
438 return generator.emitNode(dst, m_list.get());
439}
440
441// ------------------------------ PropertyListNode -----------------------------
442
443PropertyListNode::~PropertyListNode()
444{
445 NodeReleaser::releaseAllNodes(this);
446}
447
448void PropertyListNode::releaseNodes(NodeReleaser& releaser)
449{
450 releaser.release(m_node);
451 releaser.release(m_next);
452}
453
454RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
455{
456 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
457
458 generator.emitNewObject(newObj.get());
459
460 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
461 RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
462
463 switch (p->m_node->m_type) {
464 case PropertyNode::Constant: {
465 generator.emitPutById(newObj.get(), p->m_node->name(), value);
466 break;
467 }
468 case PropertyNode::Getter: {
469 generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
470 break;
471 }
472 case PropertyNode::Setter: {
473 generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
474 break;
475 }
476 default:
477 ASSERT_NOT_REACHED();
478 }
479 }
480
481 return generator.moveToDestinationIfNeeded(dst, newObj.get());
482}
483
484// ------------------------------ BracketAccessorNode --------------------------------
485
486BracketAccessorNode::~BracketAccessorNode()
487{
488 NodeReleaser::releaseAllNodes(this);
489}
490
491void BracketAccessorNode::releaseNodes(NodeReleaser& releaser)
492{
493 releaser.release(m_base);
494 releaser.release(m_subscript);
495}
496
497RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
498{
499 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator));
500 RegisterID* property = generator.emitNode(m_subscript.get());
501 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
502 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
503}
504
505// ------------------------------ DotAccessorNode --------------------------------
506
507DotAccessorNode::~DotAccessorNode()
508{
509 NodeReleaser::releaseAllNodes(this);
510}
511
512void DotAccessorNode::releaseNodes(NodeReleaser& releaser)
513{
514 releaser.release(m_base);
515}
516
517RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
518{
519 RegisterID* base = generator.emitNode(m_base.get());
520 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
521 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
522}
523
524// ------------------------------ ArgumentListNode -----------------------------
525
526ArgumentListNode::~ArgumentListNode()
527{
528 NodeReleaser::releaseAllNodes(this);
529}
530
531void ArgumentListNode::releaseNodes(NodeReleaser& releaser)
532{
533 releaser.release(m_next);
534 releaser.release(m_expr);
535}
536
537RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
538{
539 ASSERT(m_expr);
540 return generator.emitNode(dst, m_expr.get());
541}
542
543// ------------------------------ ArgumentsNode -----------------------------
544
545ArgumentsNode::~ArgumentsNode()
546{
547 NodeReleaser::releaseAllNodes(this);
548}
549
550void ArgumentsNode::releaseNodes(NodeReleaser& releaser)
551{
552 releaser.release(m_listNode);
553}
554
555// ------------------------------ NewExprNode ----------------------------------
556
557NewExprNode::~NewExprNode()
558{
559 NodeReleaser::releaseAllNodes(this);
560}
561
562void NewExprNode::releaseNodes(NodeReleaser& releaser)
563{
564 releaser.release(m_expr);
565 releaser.release(m_args);
566}
567
568RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
569{
570 RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
571 return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
572}
573
574// ------------------------------ EvalFunctionCallNode ----------------------------------
575
576EvalFunctionCallNode::~EvalFunctionCallNode()
577{
578 NodeReleaser::releaseAllNodes(this);
579}
580
581void EvalFunctionCallNode::releaseNodes(NodeReleaser& releaser)
582{
583 releaser.release(m_args);
584}
585
586RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
587{
588 RefPtr<RegisterID> base = generator.tempDestination(dst);
589 RefPtr<RegisterID> func = generator.newTemporary();
590 generator.emitResolveWithBase(base.get(), func.get(), generator.propertyNames().eval);
591 return generator.emitCallEval(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
592}
593
594// ------------------------------ FunctionCallValueNode ----------------------------------
595
596FunctionCallValueNode::~FunctionCallValueNode()
597{
598 NodeReleaser::releaseAllNodes(this);
599}
600
601void FunctionCallValueNode::releaseNodes(NodeReleaser& releaser)
602{
603 releaser.release(m_expr);
604 releaser.release(m_args);
605}
606
607RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
608{
609 RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
610 return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
611}
612
613// ------------------------------ FunctionCallResolveNode ----------------------------------
614
615FunctionCallResolveNode::~FunctionCallResolveNode()
616{
617 NodeReleaser::releaseAllNodes(this);
618}
619
620void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser)
621{
622 releaser.release(m_args);
623}
624
625RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
626{
627 if (RefPtr<RegisterID> local = generator.registerFor(m_ident))
628 return generator.emitCall(generator.finalDestination(dst), local.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
629
630 int index = 0;
631 size_t depth = 0;
632 JSObject* globalObject = 0;
633 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
634 RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
635 return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
636 }
637
638 RefPtr<RegisterID> base = generator.tempDestination(dst);
639 RefPtr<RegisterID> func = generator.newTemporary();
640 int identifierStart = m_divot - m_startOffset;
641 generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
642 generator.emitResolveFunction(base.get(), func.get(), m_ident);
643 return generator.emitCall(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
644}
645
646// ------------------------------ FunctionCallBracketNode ----------------------------------
647
648FunctionCallBracketNode::~FunctionCallBracketNode()
649{
650 NodeReleaser::releaseAllNodes(this);
651}
652
653void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser)
654{
655 releaser.release(m_base);
656 releaser.release(m_subscript);
657 releaser.release(m_args);
658}
659
660RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
661{
662 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
663 RegisterID* property = generator.emitNode(m_subscript.get());
664 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
665 RefPtr<RegisterID> function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
666 return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
667}
668
669// ------------------------------ FunctionCallDotNode ----------------------------------
670
671FunctionCallDotNode::~FunctionCallDotNode()
672{
673 NodeReleaser::releaseAllNodes(this);
674}
675
676void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser)
677{
678 releaser.release(m_base);
679 releaser.release(m_args);
680}
681
682RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
683{
684 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
685 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
686 RefPtr<RegisterID> function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
687 return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
688}
689
690// ------------------------------ PostfixResolveNode ----------------------------------
691
692static RegisterID* emitPreIncOrDec(CodeGenerator& generator, RegisterID* srcDst, Operator oper)
693{
694 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
695}
696
697static RegisterID* emitPostIncOrDec(CodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
698{
699 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
700}
701
702RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
703{
704 if (RegisterID* local = generator.registerFor(m_ident)) {
705 if (generator.isLocalConstant(m_ident)) {
706 if (dst == ignoredResult())
707 return 0;
708 return generator.emitToJSNumber(generator.finalDestination(dst), local);
709 }
710
711 if (dst == ignoredResult())
712 return emitPreIncOrDec(generator, local, m_operator);
713 return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
714 }
715
716 int index = 0;
717 size_t depth = 0;
718 JSObject* globalObject = 0;
719 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
720 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
721 RegisterID* oldValue;
722 if (dst == ignoredResult()) {
723 oldValue = 0;
724 emitPreIncOrDec(generator, value.get(), m_operator);
725 } else {
726 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
727 }
728 generator.emitPutScopedVar(depth, index, value.get(), globalObject);
729 return oldValue;
730 }
731
732 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
733 RefPtr<RegisterID> value = generator.newTemporary();
734 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
735 RegisterID* oldValue;
736 if (dst == ignoredResult()) {
737 oldValue = 0;
738 emitPreIncOrDec(generator, value.get(), m_operator);
739 } else {
740 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
741 }
742 generator.emitPutById(base.get(), m_ident, value.get());
743 return oldValue;
744}
745
746// ------------------------------ PostfixBracketNode ----------------------------------
747
748PostfixBracketNode::~PostfixBracketNode()
749{
750 NodeReleaser::releaseAllNodes(this);
751}
752
753void PostfixBracketNode::releaseNodes(NodeReleaser& releaser)
754{
755 releaser.release(m_base);
756 releaser.release(m_subscript);
757}
758
759RegisterID* PostfixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
760{
761 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
762 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
763
764 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
765 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
766 RegisterID* oldValue;
767 if (dst == ignoredResult()) {
768 oldValue = 0;
769 if (m_operator == OpPlusPlus)
770 generator.emitPreInc(value.get());
771 else
772 generator.emitPreDec(value.get());
773 } else {
774 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
775 }
776 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
777 generator.emitPutByVal(base.get(), property.get(), value.get());
778 return oldValue;
779}
780
781// ------------------------------ PostfixDotNode ----------------------------------
782
783PostfixDotNode::~PostfixDotNode()
784{
785 NodeReleaser::releaseAllNodes(this);
786}
787
788void PostfixDotNode::releaseNodes(NodeReleaser& releaser)
789{
790 releaser.release(m_base);
791}
792
793RegisterID* PostfixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
794{
795 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
796
797 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
798 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
799 RegisterID* oldValue;
800 if (dst == ignoredResult()) {
801 oldValue = 0;
802 if (m_operator == OpPlusPlus)
803 generator.emitPreInc(value.get());
804 else
805 generator.emitPreDec(value.get());
806 } else {
807 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
808 }
809 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
810 generator.emitPutById(base.get(), m_ident, value.get());
811 return oldValue;
812}
813
814// ------------------------------ PostfixErrorNode -----------------------------------
815
816PostfixErrorNode::~PostfixErrorNode()
817{
818 NodeReleaser::releaseAllNodes(this);
819}
820
821void PostfixErrorNode::releaseNodes(NodeReleaser& releaser)
822{
823 releaser.release(m_expr);
824}
825
826RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
827{
828 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference.");
829}
830
831// ------------------------------ DeleteResolveNode -----------------------------------
832
833RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
834{
835 if (generator.registerFor(m_ident))
836 return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
837
838 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
839 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
840 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
841}
842
843// ------------------------------ DeleteBracketNode -----------------------------------
844
845DeleteBracketNode::~DeleteBracketNode()
846{
847 NodeReleaser::releaseAllNodes(this);
848}
849
850void DeleteBracketNode::releaseNodes(NodeReleaser& releaser)
851{
852 releaser.release(m_base);
853 releaser.release(m_subscript);
854}
855
856RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
857{
858 RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
859 RegisterID* r1 = generator.emitNode(m_subscript.get());
860
861 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
862 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
863}
864
865// ------------------------------ DeleteDotNode -----------------------------------
866
867DeleteDotNode::~DeleteDotNode()
868{
869 NodeReleaser::releaseAllNodes(this);
870}
871
872void DeleteDotNode::releaseNodes(NodeReleaser& releaser)
873{
874 releaser.release(m_base);
875}
876
877RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
878{
879 RegisterID* r0 = generator.emitNode(m_base.get());
880
881 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
882 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
883}
884
885// ------------------------------ DeleteValueNode -----------------------------------
886
887DeleteValueNode::~DeleteValueNode()
888{
889 NodeReleaser::releaseAllNodes(this);
890}
891
892void DeleteValueNode::releaseNodes(NodeReleaser& releaser)
893{
894 releaser.release(m_expr);
895}
896
897RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
898{
899 generator.emitNode(ignoredResult(), m_expr.get());
900
901 // delete on a non-location expression ignores the value and returns true
902 return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
903}
904
905// ------------------------------ VoidNode -------------------------------------
906
907VoidNode::~VoidNode()
908{
909 NodeReleaser::releaseAllNodes(this);
910}
911
912void VoidNode::releaseNodes(NodeReleaser& releaser)
913{
914 releaser.release(m_expr);
915}
916
917RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
918{
919 if (dst == ignoredResult()) {
920 generator.emitNode(ignoredResult(), m_expr.get());
921 return 0;
922 }
923 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
924 return generator.emitLoad(dst, jsUndefined());
925}
926
927// ------------------------------ TypeOfValueNode -----------------------------------
928
929RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
930{
931 if (RegisterID* local = generator.registerFor(m_ident)) {
932 if (dst == ignoredResult())
933 return 0;
934 return generator.emitTypeOf(generator.finalDestination(dst), local);
935 }
936
937 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
938 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
939 if (dst == ignoredResult())
940 return 0;
941 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
942}
943
944// ------------------------------ TypeOfValueNode -----------------------------------
945
946TypeOfValueNode::~TypeOfValueNode()
947{
948 NodeReleaser::releaseAllNodes(this);
949}
950
951void TypeOfValueNode::releaseNodes(NodeReleaser& releaser)
952{
953 releaser.release(m_expr);
954}
955
956RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
957{
958 if (dst == ignoredResult()) {
959 generator.emitNode(ignoredResult(), m_expr.get());
960 return 0;
961 }
962 RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
963 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
964}
965
966// ------------------------------ PrefixResolveNode ----------------------------------
967
968RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
969{
970 if (RegisterID* local = generator.registerFor(m_ident)) {
971 if (generator.isLocalConstant(m_ident)) {
972 if (dst == ignoredResult())
973 return 0;
974 RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
975 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
976 }
977
978 emitPreIncOrDec(generator, local, m_operator);
979 return generator.moveToDestinationIfNeeded(dst, local);
980 }
981
982 int index = 0;
983 size_t depth = 0;
984 JSObject* globalObject = 0;
985 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
986 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
987 emitPreIncOrDec(generator, propDst.get(), m_operator);
988 generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
989 return generator.moveToDestinationIfNeeded(dst, propDst.get());
990 }
991
992 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
993 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
994 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
995 emitPreIncOrDec(generator, propDst.get(), m_operator);
996 generator.emitPutById(base.get(), m_ident, propDst.get());
997 return generator.moveToDestinationIfNeeded(dst, propDst.get());
998}
999
1000// ------------------------------ PrefixBracketNode ----------------------------------
1001
1002PrefixBracketNode::~PrefixBracketNode()
1003{
1004 NodeReleaser::releaseAllNodes(this);
1005}
1006
1007void PrefixBracketNode::releaseNodes(NodeReleaser& releaser)
1008{
1009 releaser.release(m_base);
1010 releaser.release(m_subscript);
1011}
1012
1013RegisterID* PrefixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1014{
1015 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1016 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
1017 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1018
1019 generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_endOffset - m_subexpressionDivotOffset);
1020 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
1021 if (m_operator == OpPlusPlus)
1022 generator.emitPreInc(value);
1023 else
1024 generator.emitPreDec(value);
1025 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1026 generator.emitPutByVal(base.get(), property.get(), value);
1027 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1028}
1029
1030// ------------------------------ PrefixDotNode ----------------------------------
1031
1032PrefixDotNode::~PrefixDotNode()
1033{
1034 NodeReleaser::releaseAllNodes(this);
1035}
1036
1037void PrefixDotNode::releaseNodes(NodeReleaser& releaser)
1038{
1039 releaser.release(m_base);
1040}
1041
1042RegisterID* PrefixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1043{
1044 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1045 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1046
1047 generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_endOffset - m_subexpressionDivotOffset);
1048 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
1049 if (m_operator == OpPlusPlus)
1050 generator.emitPreInc(value);
1051 else
1052 generator.emitPreDec(value);
1053 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1054 generator.emitPutById(base.get(), m_ident, value);
1055 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1056}
1057
1058// ------------------------------ PrefixErrorNode -----------------------------------
1059
1060PrefixErrorNode::~PrefixErrorNode()
1061{
1062 NodeReleaser::releaseAllNodes(this);
1063}
1064
1065void PrefixErrorNode::releaseNodes(NodeReleaser& releaser)
1066{
1067 releaser.release(m_expr);
1068}
1069
1070RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
1071{
1072 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference.");
1073}
1074
1075// ------------------------------ Unary Operation Nodes -----------------------------------
1076
1077UnaryOpNode::~UnaryOpNode()
1078{
1079 NodeReleaser::releaseAllNodes(this);
1080}
1081
1082void UnaryOpNode::releaseNodes(NodeReleaser& releaser)
1083{
1084 releaser.release(m_expr);
1085}
1086
1087RegisterID* UnaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1088{
1089 RegisterID* src = generator.emitNode(m_expr.get());
1090 return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src, m_expr->resultDescriptor());
1091}
1092
1093// ------------------------------ Binary Operation Nodes -----------------------------------
1094
1095BinaryOpNode::~BinaryOpNode()
1096{
1097 NodeReleaser::releaseAllNodes(this);
1098}
1099
1100void BinaryOpNode::releaseNodes(NodeReleaser& releaser)
1101{
1102 releaser.release(m_expr1);
1103 releaser.release(m_expr2);
1104}
1105
1106RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1107{
1108 OpcodeID opcode = this->opcode();
1109 if (opcode == op_neq) {
1110 if (m_expr1->isNull() || m_expr2->isNull()) {
1111 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
1112 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown());
1113 }
1114 }
1115
1116 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1117 RegisterID* src2 = generator.emitNode(m_expr2.get());
1118 return generator.emitBinaryOp(opcode, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1119}
1120
1121RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1122{
1123 if (m_expr1->isNull() || m_expr2->isNull()) {
1124 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
1125 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown());
1126 }
1127
1128 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1129 RegisterID* src2 = generator.emitNode(m_expr2.get());
1130 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1131}
1132
1133RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1134{
1135 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1136 RegisterID* src2 = generator.emitNode(m_expr2.get());
1137 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1138}
1139
1140RegisterID* ReverseBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1141{
1142 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1143 RegisterID* src2 = generator.emitNode(m_expr2.get());
1144 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
1145}
1146
1147RegisterID* ThrowableBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1148{
1149 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1150 RegisterID* src2 = generator.emitNode(m_expr2.get());
1151 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1152 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1153}
1154
1155RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1156{
1157 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1158 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
1159
1160 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1161 RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
1162
1163 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1164 return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
1165}
1166
1167// ------------------------------ LogicalOpNode ----------------------------
1168
1169LogicalOpNode::~LogicalOpNode()
1170{
1171 NodeReleaser::releaseAllNodes(this);
1172}
1173
1174void LogicalOpNode::releaseNodes(NodeReleaser& releaser)
1175{
1176 releaser.release(m_expr1);
1177 releaser.release(m_expr2);
1178}
1179
1180RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1181{
1182 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1183 RefPtr<LabelID> target = generator.newLabel();
1184
1185 generator.emitNode(temp.get(), m_expr1.get());
1186 if (m_operator == OpLogicalAnd)
1187 generator.emitJumpIfFalse(temp.get(), target.get());
1188 else
1189 generator.emitJumpIfTrue(temp.get(), target.get());
1190 generator.emitNode(temp.get(), m_expr2.get());
1191 generator.emitLabel(target.get());
1192
1193 return generator.moveToDestinationIfNeeded(dst, temp.get());
1194}
1195
1196// ------------------------------ ConditionalNode ------------------------------
1197
1198ConditionalNode::~ConditionalNode()
1199{
1200 NodeReleaser::releaseAllNodes(this);
1201}
1202
1203void ConditionalNode::releaseNodes(NodeReleaser& releaser)
1204{
1205 releaser.release(m_logical);
1206 releaser.release(m_expr1);
1207 releaser.release(m_expr2);
1208}
1209
1210RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1211{
1212 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1213 RefPtr<LabelID> beforeElse = generator.newLabel();
1214 RefPtr<LabelID> afterElse = generator.newLabel();
1215
1216 RegisterID* cond = generator.emitNode(m_logical.get());
1217 generator.emitJumpIfFalse(cond, beforeElse.get());
1218
1219 generator.emitNode(newDst.get(), m_expr1.get());
1220 generator.emitJump(afterElse.get());
1221
1222 generator.emitLabel(beforeElse.get());
1223 generator.emitNode(newDst.get(), m_expr2.get());
1224
1225 generator.emitLabel(afterElse.get());
1226
1227 return newDst.get();
1228}
1229
1230// ------------------------------ ReadModifyResolveNode -----------------------------------
1231
1232ReadModifyResolveNode::~ReadModifyResolveNode()
1233{
1234 NodeReleaser::releaseAllNodes(this);
1235}
1236
1237void ReadModifyResolveNode::releaseNodes(NodeReleaser& releaser)
1238{
1239 releaser.release(m_right);
1240}
1241
1242// FIXME: should this be moved to be a method on CodeGenerator?
1243static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types)
1244{
1245 OpcodeID opcode;
1246 switch (oper) {
1247 case OpMultEq:
1248 opcode = op_mul;
1249 break;
1250 case OpDivEq:
1251 opcode = op_div;
1252 break;
1253 case OpPlusEq:
1254 opcode = op_add;
1255 break;
1256 case OpMinusEq:
1257 opcode = op_sub;
1258 break;
1259 case OpLShift:
1260 opcode = op_lshift;
1261 break;
1262 case OpRShift:
1263 opcode = op_rshift;
1264 break;
1265 case OpURShift:
1266 opcode = op_urshift;
1267 break;
1268 case OpAndEq:
1269 opcode = op_bitand;
1270 break;
1271 case OpXOrEq:
1272 opcode = op_bitxor;
1273 break;
1274 case OpOrEq:
1275 opcode = op_bitor;
1276 break;
1277 case OpModEq:
1278 opcode = op_mod;
1279 break;
1280 default:
1281 ASSERT_NOT_REACHED();
1282 return dst;
1283 }
1284
1285 return generator.emitBinaryOp(opcode, dst, src1, src2, types);
1286}
1287
1288RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1289{
1290 if (RegisterID* local = generator.registerFor(m_ident)) {
1291 if (generator.isLocalConstant(m_ident)) {
1292 RegisterID* src2 = generator.emitNode(m_right.get());
1293 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1294 }
1295
1296 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
1297 RefPtr<RegisterID> result = generator.newTemporary();
1298 generator.emitMove(result.get(), local);
1299 RegisterID* src2 = generator.emitNode(m_right.get());
1300 emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1301 generator.emitMove(local, result.get());
1302 return generator.moveToDestinationIfNeeded(dst, result.get());
1303 }
1304
1305 RegisterID* src2 = generator.emitNode(m_right.get());
1306 RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1307 return generator.moveToDestinationIfNeeded(dst, result);
1308 }
1309
1310 int index = 0;
1311 size_t depth = 0;
1312 JSObject* globalObject = 0;
1313 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1314 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
1315 RegisterID* src2 = generator.emitNode(m_right.get());
1316 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1317 generator.emitPutScopedVar(depth, index, result, globalObject);
1318 return result;
1319 }
1320
1321 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
1322 generator.emitExpressionInfo(m_divot - m_startOffset + m_ident.size(), m_ident.size(), 0);
1323 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
1324 RegisterID* src2 = generator.emitNode(m_right.get());
1325 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1326 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1327 return generator.emitPutById(base.get(), m_ident, result);
1328}
1329
1330// ------------------------------ AssignResolveNode -----------------------------------
1331
1332AssignResolveNode::~AssignResolveNode()
1333{
1334 NodeReleaser::releaseAllNodes(this);
1335}
1336
1337void AssignResolveNode::releaseNodes(NodeReleaser& releaser)
1338{
1339 releaser.release(m_right);
1340}
1341
1342RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1343{
1344 if (RegisterID* local = generator.registerFor(m_ident)) {
1345 if (generator.isLocalConstant(m_ident))
1346 return generator.emitNode(dst, m_right.get());
1347
1348 RegisterID* result = generator.emitNode(local, m_right.get());
1349 return generator.moveToDestinationIfNeeded(dst, result);
1350 }
1351
1352 int index = 0;
1353 size_t depth = 0;
1354 JSObject* globalObject = 0;
1355 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1356 if (dst == ignoredResult())
1357 dst = 0;
1358 RegisterID* value = generator.emitNode(dst, m_right.get());
1359 generator.emitPutScopedVar(depth, index, value, globalObject);
1360 return value;
1361 }
1362
1363 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1364 if (dst == ignoredResult())
1365 dst = 0;
1366 RegisterID* value = generator.emitNode(dst, m_right.get());
1367 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1368 return generator.emitPutById(base.get(), m_ident, value);
1369}
1370
1371// ------------------------------ AssignDotNode -----------------------------------
1372
1373AssignDotNode::~AssignDotNode()
1374{
1375 NodeReleaser::releaseAllNodes(this);
1376}
1377
1378void AssignDotNode::releaseNodes(NodeReleaser& releaser)
1379{
1380 releaser.release(m_base);
1381 releaser.release(m_right);
1382}
1383
1384RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1385{
1386 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
1387 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1388 RegisterID* result = generator.emitNode(value.get(), m_right.get());
1389 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1390 generator.emitPutById(base.get(), m_ident, result);
1391 return generator.moveToDestinationIfNeeded(dst, result);
1392}
1393
1394// ------------------------------ ReadModifyDotNode -----------------------------------
1395
1396ReadModifyDotNode::~ReadModifyDotNode()
1397{
1398 NodeReleaser::releaseAllNodes(this);
1399}
1400
1401void ReadModifyDotNode::releaseNodes(NodeReleaser& releaser)
1402{
1403 releaser.release(m_base);
1404 releaser.release(m_right);
1405}
1406
1407RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1408{
1409 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
1410
1411 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1412 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
1413 RegisterID* change = generator.emitNode(m_right.get());
1414 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1415
1416 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1417 return generator.emitPutById(base.get(), m_ident, updatedValue);
1418}
1419
1420// ------------------------------ AssignErrorNode -----------------------------------
1421
1422AssignErrorNode::~AssignErrorNode()
1423{
1424 NodeReleaser::releaseAllNodes(this);
1425}
1426
1427void AssignErrorNode::releaseNodes(NodeReleaser& releaser)
1428{
1429 releaser.release(m_left);
1430 releaser.release(m_right);
1431}
1432
1433RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
1434{
1435 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
1436}
1437
1438// ------------------------------ AssignBracketNode -----------------------------------
1439
1440AssignBracketNode::~AssignBracketNode()
1441{
1442 NodeReleaser::releaseAllNodes(this);
1443}
1444
1445void AssignBracketNode::releaseNodes(NodeReleaser& releaser)
1446{
1447 releaser.release(m_base);
1448 releaser.release(m_subscript);
1449 releaser.release(m_right);
1450}
1451
1452RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1453{
1454 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1455 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1456 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1457 RegisterID* result = generator.emitNode(value.get(), m_right.get());
1458
1459 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1460 generator.emitPutByVal(base.get(), property.get(), result);
1461 return generator.moveToDestinationIfNeeded(dst, result);
1462}
1463
1464// ------------------------------ ReadModifyBracketNode -----------------------------------
1465
1466ReadModifyBracketNode::~ReadModifyBracketNode()
1467{
1468 NodeReleaser::releaseAllNodes(this);
1469}
1470
1471void ReadModifyBracketNode::releaseNodes(NodeReleaser& releaser)
1472{
1473 releaser.release(m_base);
1474 releaser.release(m_subscript);
1475 releaser.release(m_right);
1476}
1477
1478RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1479{
1480 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1481 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1482
1483 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1484 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1485 RegisterID* change = generator.emitNode(m_right.get());
1486 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1487
1488 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1489 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1490
1491 return updatedValue;
1492}
1493
1494// ------------------------------ CommaNode ------------------------------------
1495
1496CommaNode::~CommaNode()
1497{
1498 NodeReleaser::releaseAllNodes(this);
1499}
1500
1501void CommaNode::releaseNodes(NodeReleaser& releaser)
1502{
1503 releaser.release(m_expr1);
1504 releaser.release(m_expr2);
1505}
1506
1507RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1508{
1509 generator.emitNode(ignoredResult(), m_expr1.get());
1510 return generator.emitNode(dst, m_expr2.get());
1511}
1512
1513// ------------------------------ ConstDeclNode ------------------------------------
1514
1515ConstDeclNode::~ConstDeclNode()
1516{
1517 NodeReleaser::releaseAllNodes(this);
1518}
1519
1520void ConstDeclNode::releaseNodes(NodeReleaser& releaser)
1521{
1522 releaser.release(m_next);
1523 releaser.release(m_init);
1524}
1525
1526ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
1527 : ExpressionNode(globalData)
1528 , m_ident(ident)
1529 , m_init(init)
1530{
1531}
1532
1533RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
1534{
1535 if (RegisterID* local = generator.constRegisterFor(m_ident)) {
1536 if (!m_init)
1537 return local;
1538
1539 return generator.emitNode(local, m_init.get());
1540 }
1541
1542 // FIXME: While this code should only be hit in eval code, it will potentially
1543 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1544 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1545 RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined());
1546 return generator.emitPutById(base.get(), m_ident, value);
1547}
1548
1549RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
1550{
1551 RegisterID* result = 0;
1552 for (ConstDeclNode* n = this; n; n = n->m_next.get())
1553 result = n->emitCodeSingle(generator);
1554
1555 return result;
1556}
1557
1558// ------------------------------ ConstStatementNode -----------------------------
1559
1560ConstStatementNode::~ConstStatementNode()
1561{
1562 NodeReleaser::releaseAllNodes(this);
1563}
1564
1565void ConstStatementNode::releaseNodes(NodeReleaser& releaser)
1566{
1567 releaser.release(m_next);
1568}
1569
1570RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1571{
1572 return generator.emitNode(m_next.get());
1573}
1574
1575// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
1576
1577static inline RegisterID* statementListEmitCode(StatementVector& statements, CodeGenerator& generator, RegisterID* dst)
1578{
1579 StatementVector::iterator end = statements.end();
1580 for (StatementVector::iterator it = statements.begin(); it != end; ++it) {
1581 StatementNode* n = it->get();
1582 if (!n->isLoop())
1583 generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
1584 generator.emitNode(dst, n);
1585 }
1586 return 0;
1587}
1588
1589static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
1590{
1591 StatementVector::iterator it = statements.end();
1592 StatementVector::iterator begin = statements.begin();
1593 while (it != begin) {
1594 --it;
1595 stack.append((*it).get());
1596 }
1597}
1598
1599// ------------------------------ BlockNode ------------------------------------
1600
1601BlockNode::~BlockNode()
1602{
1603 NodeReleaser::releaseAllNodes(this);
1604}
1605
1606void BlockNode::releaseNodes(NodeReleaser& releaser)
1607{
1608 size_t size = m_children.size();
1609 for (size_t i = 0; i < size; ++i)
1610 releaser.release(m_children[i]);
1611}
1612
1613BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
1614 : StatementNode(globalData)
1615{
1616 if (children)
1617 children->releaseContentsIntoVector(m_children);
1618}
1619
1620RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1621{
1622 return statementListEmitCode(m_children, generator, dst);
1623}
1624
1625// ------------------------------ EmptyStatementNode ---------------------------
1626
1627RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
1628{
1629 return dst;
1630}
1631
1632// ------------------------------ DebuggerStatementNode ---------------------------
1633
1634RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1635{
1636 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1637 return dst;
1638}
1639
1640// ------------------------------ ExprStatementNode ----------------------------
1641
1642RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1643{
1644 ASSERT(m_expr);
1645 return generator.emitNode(dst, m_expr.get());
1646}
1647
1648// ------------------------------ VarStatementNode ----------------------------
1649
1650VarStatementNode::~VarStatementNode()
1651{
1652 NodeReleaser::releaseAllNodes(this);
1653}
1654
1655void VarStatementNode::releaseNodes(NodeReleaser& releaser)
1656{
1657 releaser.release(m_expr);
1658}
1659
1660RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1661{
1662 ASSERT(m_expr);
1663 return generator.emitNode(m_expr.get());
1664}
1665
1666// ------------------------------ IfNode ---------------------------------------
1667
1668IfNode::~IfNode()
1669{
1670 NodeReleaser::releaseAllNodes(this);
1671}
1672
1673void IfNode::releaseNodes(NodeReleaser& releaser)
1674{
1675 releaser.release(m_condition);
1676 releaser.release(m_ifBlock);
1677}
1678
1679RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1680{
1681 RefPtr<LabelID> afterThen = generator.newLabel();
1682
1683 RegisterID* cond = generator.emitNode(m_condition.get());
1684 generator.emitJumpIfFalse(cond, afterThen.get());
1685
1686 if (!m_ifBlock->isBlock())
1687 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1688
1689 generator.emitNode(dst, m_ifBlock.get());
1690 generator.emitLabel(afterThen.get());
1691
1692 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1693 return 0;
1694}
1695
1696// ------------------------------ IfElseNode ---------------------------------------
1697
1698IfElseNode::~IfElseNode()
1699{
1700 NodeReleaser::releaseAllNodes(this);
1701}
1702
1703void IfElseNode::releaseNodes(NodeReleaser& releaser)
1704{
1705 releaser.release(m_elseBlock);
1706 IfNode::releaseNodes(releaser);
1707}
1708
1709RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1710{
1711 RefPtr<LabelID> beforeElse = generator.newLabel();
1712 RefPtr<LabelID> afterElse = generator.newLabel();
1713
1714 RegisterID* cond = generator.emitNode(m_condition.get());
1715 generator.emitJumpIfFalse(cond, beforeElse.get());
1716
1717 if (!m_ifBlock->isBlock())
1718 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1719
1720 generator.emitNode(dst, m_ifBlock.get());
1721 generator.emitJump(afterElse.get());
1722
1723 generator.emitLabel(beforeElse.get());
1724
1725 if (!m_elseBlock->isBlock())
1726 generator.emitDebugHook(WillExecuteStatement, m_elseBlock->firstLine(), m_elseBlock->lastLine());
1727
1728 generator.emitNode(dst, m_elseBlock.get());
1729
1730 generator.emitLabel(afterElse.get());
1731
1732 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1733 return 0;
1734}
1735
1736// ------------------------------ DoWhileNode ----------------------------------
1737
1738DoWhileNode::~DoWhileNode()
1739{
1740 NodeReleaser::releaseAllNodes(this);
1741}
1742
1743void DoWhileNode::releaseNodes(NodeReleaser& releaser)
1744{
1745 releaser.release(m_statement);
1746 releaser.release(m_expr);
1747}
1748
1749RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1750{
1751 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1752
1753 RefPtr<LabelID> topOfLoop = generator.newLabel();
1754 generator.emitLabel(topOfLoop.get());
1755
1756 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1757
1758 if (!m_statement->isBlock())
1759 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1760
1761 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1762
1763 generator.emitLabel(scope->continueTarget());
1764 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1765 RegisterID* cond = generator.emitNode(m_expr.get());
1766 generator.emitJumpIfTrue(cond, topOfLoop.get());
1767
1768 generator.emitLabel(scope->breakTarget());
1769 return result.get();
1770}
1771
1772// ------------------------------ WhileNode ------------------------------------
1773
1774WhileNode::~WhileNode()
1775{
1776 NodeReleaser::releaseAllNodes(this);
1777}
1778
1779void WhileNode::releaseNodes(NodeReleaser& releaser)
1780{
1781 releaser.release(m_expr);
1782 releaser.release(m_statement);
1783}
1784
1785RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1786{
1787 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1788
1789 generator.emitJump(scope->continueTarget());
1790
1791 RefPtr<LabelID> topOfLoop = generator.newLabel();
1792 generator.emitLabel(topOfLoop.get());
1793
1794 if (!m_statement->isBlock())
1795 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1796
1797 generator.emitNode(dst, m_statement.get());
1798
1799 generator.emitLabel(scope->continueTarget());
1800 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1801 RegisterID* cond = generator.emitNode(m_expr.get());
1802 generator.emitJumpIfTrue(cond, topOfLoop.get());
1803
1804 generator.emitLabel(scope->breakTarget());
1805
1806 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1807 return 0;
1808}
1809
1810// ------------------------------ ForNode --------------------------------------
1811
1812ForNode::~ForNode()
1813{
1814 NodeReleaser::releaseAllNodes(this);
1815}
1816
1817void ForNode::releaseNodes(NodeReleaser& releaser)
1818{
1819 releaser.release(m_expr1);
1820 releaser.release(m_expr2);
1821 releaser.release(m_expr3);
1822 releaser.release(m_statement);
1823}
1824
1825RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1826{
1827 if (dst == ignoredResult())
1828 dst = 0;
1829
1830 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1831
1832 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1833
1834 if (m_expr1)
1835 generator.emitNode(ignoredResult(), m_expr1.get());
1836
1837 RefPtr<LabelID> condition = generator.newLabel();
1838 generator.emitJump(condition.get());
1839
1840 RefPtr<LabelID> topOfLoop = generator.newLabel();
1841 generator.emitLabel(topOfLoop.get());
1842
1843 if (!m_statement->isBlock())
1844 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1845 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1846
1847 generator.emitLabel(scope->continueTarget());
1848 if (m_expr3)
1849 generator.emitNode(ignoredResult(), m_expr3.get());
1850
1851 generator.emitLabel(condition.get());
1852 if (m_expr2) {
1853 RegisterID* cond = generator.emitNode(m_expr2.get());
1854 generator.emitJumpIfTrue(cond, topOfLoop.get());
1855 } else
1856 generator.emitJump(topOfLoop.get());
1857
1858 generator.emitLabel(scope->breakTarget());
1859 return result.get();
1860}
1861
1862// ------------------------------ ForInNode ------------------------------------
1863
1864ForInNode::~ForInNode()
1865{
1866 NodeReleaser::releaseAllNodes(this);
1867}
1868
1869void ForInNode::releaseNodes(NodeReleaser& releaser)
1870{
1871 releaser.release(m_init);
1872 releaser.release(m_lexpr);
1873 releaser.release(m_expr);
1874 releaser.release(m_statement);
1875}
1876
1877ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
1878 : StatementNode(globalData)
1879 , m_init(0L)
1880 , m_lexpr(l)
1881 , m_expr(expr)
1882 , m_statement(statement)
1883 , m_identIsVarDecl(false)
1884{
1885}
1886
1887ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
1888 : StatementNode(globalData)
1889 , m_ident(ident)
1890 , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset))
1891 , m_expr(expr)
1892 , m_statement(statement)
1893 , m_identIsVarDecl(true)
1894{
1895 if (in) {
1896 AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true);
1897 node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot);
1898 m_init = node;
1899 }
1900 // for( var foo = bar in baz )
1901}
1902
1903RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1904{
1905 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1906
1907 if (!m_lexpr->isLocation())
1908 return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
1909
1910 RefPtr<LabelID> continueTarget = generator.newLabel();
1911
1912 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1913
1914 if (m_init)
1915 generator.emitNode(ignoredResult(), m_init.get());
1916 RegisterID* forInBase = generator.emitNode(m_expr.get());
1917 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
1918 generator.emitJump(scope->continueTarget());
1919
1920 RefPtr<LabelID> loopStart = generator.newLabel();
1921 generator.emitLabel(loopStart.get());
1922
1923 RegisterID* propertyName;
1924 if (m_lexpr->isResolveNode()) {
1925 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
1926 propertyName = generator.registerFor(ident);
1927 if (!propertyName) {
1928 propertyName = generator.newTemporary();
1929 RefPtr<RegisterID> protect = propertyName;
1930 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
1931
1932 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1933 generator.emitPutById(base, ident, propertyName);
1934 }
1935 } else if (m_lexpr->isDotAccessorNode()) {
1936 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
1937 const Identifier& ident = assignNode->identifier();
1938 propertyName = generator.newTemporary();
1939 RefPtr<RegisterID> protect = propertyName;
1940 RegisterID* base = generator.emitNode(assignNode->base());
1941
1942 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1943 generator.emitPutById(base, ident, propertyName);
1944 } else {
1945 ASSERT(m_lexpr->isBracketAccessorNode());
1946 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
1947 propertyName = generator.newTemporary();
1948 RefPtr<RegisterID> protect = propertyName;
1949 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1950 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1951
1952 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1953 generator.emitPutByVal(base.get(), subscript, propertyName);
1954 }
1955
1956 if (!m_statement->isBlock())
1957 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1958 generator.emitNode(dst, m_statement.get());
1959
1960 generator.emitLabel(scope->continueTarget());
1961 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
1962 generator.emitLabel(scope->breakTarget());
1963 return dst;
1964}
1965
1966// ------------------------------ ContinueNode ---------------------------------
1967
1968// ECMA 12.7
1969RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1970{
1971 LabelScope* scope = generator.continueTarget(m_ident);
1972
1973 if (!scope)
1974 return m_ident.isEmpty()
1975 ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
1976 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1977
1978 generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
1979 return dst;
1980}
1981
1982// ------------------------------ BreakNode ------------------------------------
1983
1984// ECMA 12.8
1985RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1986{
1987 LabelScope* scope = generator.breakTarget(m_ident);
1988
1989 if (!scope)
1990 return m_ident.isEmpty()
1991 ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
1992 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1993
1994 generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
1995 return dst;
1996}
1997
1998// ------------------------------ ReturnNode -----------------------------------
1999
2000ReturnNode::~ReturnNode()
2001{
2002 NodeReleaser::releaseAllNodes(this);
2003}
2004
2005void ReturnNode::releaseNodes(NodeReleaser& releaser)
2006{
2007 releaser.release(m_value);
2008}
2009
2010RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2011{
2012 if (generator.codeType() != FunctionCode)
2013 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
2014
2015 if (dst == ignoredResult())
2016 dst = 0;
2017 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined());
2018 if (generator.scopeDepth()) {
2019 RefPtr<LabelID> l0 = generator.newLabel();
2020 generator.emitJumpScopes(l0.get(), 0);
2021 generator.emitLabel(l0.get());
2022 }
2023 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2024 return generator.emitReturn(r0);
2025}
2026
2027// ------------------------------ WithNode -------------------------------------
2028
2029WithNode::~WithNode()
2030{
2031 NodeReleaser::releaseAllNodes(this);
2032}
2033
2034void WithNode::releaseNodes(NodeReleaser& releaser)
2035{
2036 releaser.release(m_expr);
2037 releaser.release(m_statement);
2038}
2039
2040RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2041{
2042 RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
2043 generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
2044 generator.emitPushScope(scope.get());
2045 RegisterID* result = generator.emitNode(dst, m_statement.get());
2046 generator.emitPopScope();
2047 return result;
2048}
2049
2050// ------------------------------ CaseClauseNode --------------------------------
2051
2052CaseClauseNode::~CaseClauseNode()
2053{
2054 NodeReleaser::releaseAllNodes(this);
2055}
2056
2057void CaseClauseNode::releaseNodes(NodeReleaser& releaser)
2058{
2059 releaser.release(m_expr);
2060}
2061
2062// ------------------------------ ClauseListNode --------------------------------
2063
2064ClauseListNode::~ClauseListNode()
2065{
2066 NodeReleaser::releaseAllNodes(this);
2067}
2068
2069void ClauseListNode::releaseNodes(NodeReleaser& releaser)
2070{
2071 releaser.release(m_clause);
2072 releaser.release(m_next);
2073}
2074
2075// ------------------------------ CaseBlockNode --------------------------------
2076
2077CaseBlockNode::~CaseBlockNode()
2078{
2079 NodeReleaser::releaseAllNodes(this);
2080}
2081
2082void CaseBlockNode::releaseNodes(NodeReleaser& releaser)
2083{
2084 releaser.release(m_list1);
2085 releaser.release(m_defaultClause);
2086 releaser.release(m_list2);
2087}
2088
2089enum SwitchKind {
2090 SwitchUnset = 0,
2091 SwitchNumber = 1,
2092 SwitchString = 2,
2093 SwitchNeither = 3
2094};
2095
2096static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2097{
2098 for (; list; list = list->getNext()) {
2099 ExpressionNode* clauseExpression = list->getClause()->expr();
2100 literalVector.append(clauseExpression);
2101 if (clauseExpression->isNumber()) {
2102 double value = static_cast<NumberNode*>(clauseExpression)->value();
2103 if ((typeForTable & ~SwitchNumber) || !JSImmediate::from(value)) {
2104 typeForTable = SwitchNeither;
2105 break;
2106 }
2107 int32_t intVal = static_cast<int32_t>(value);
2108 ASSERT(intVal == value);
2109 if (intVal < min_num)
2110 min_num = intVal;
2111 if (intVal > max_num)
2112 max_num = intVal;
2113 typeForTable = SwitchNumber;
2114 continue;
2115 }
2116 if (clauseExpression->isString()) {
2117 if (typeForTable & ~SwitchString) {
2118 typeForTable = SwitchNeither;
2119 break;
2120 }
2121 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
2122 if (singleCharacterSwitch &= value.size() == 1) {
2123 int32_t intVal = value.rep()->data()[0];
2124 if (intVal < min_num)
2125 min_num = intVal;
2126 if (intVal > max_num)
2127 max_num = intVal;
2128 }
2129 typeForTable = SwitchString;
2130 continue;
2131 }
2132 typeForTable = SwitchNeither;
2133 break;
2134 }
2135}
2136
2137SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2138{
2139 SwitchKind typeForTable = SwitchUnset;
2140 bool singleCharacterSwitch = true;
2141
2142 processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2143 processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2144
2145 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2146 return SwitchInfo::SwitchNone;
2147
2148 if (typeForTable == SwitchNumber) {
2149 int32_t range = max_num - min_num;
2150 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2151 return SwitchInfo::SwitchImmediate;
2152 return SwitchInfo::SwitchNone;
2153 }
2154
2155 ASSERT(typeForTable == SwitchString);
2156
2157 if (singleCharacterSwitch) {
2158 int32_t range = max_num - min_num;
2159 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2160 return SwitchInfo::SwitchCharacter;
2161 }
2162
2163 return SwitchInfo::SwitchString;
2164}
2165
2166RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
2167{
2168 RefPtr<LabelID> defaultLabel;
2169 Vector<RefPtr<LabelID>, 8> labelVector;
2170 Vector<ExpressionNode*, 8> literalVector;
2171 int32_t min_num = std::numeric_limits<int32_t>::max();
2172 int32_t max_num = std::numeric_limits<int32_t>::min();
2173 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
2174
2175 if (switchType != SwitchInfo::SwitchNone) {
2176 // Prepare the various labels
2177 for (uint32_t i = 0; i < literalVector.size(); i++)
2178 labelVector.append(generator.newLabel());
2179 defaultLabel = generator.newLabel();
2180 generator.beginSwitch(switchExpression, switchType);
2181 } else {
2182 // Setup jumps
2183 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
2184 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2185 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2186 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2187 labelVector.append(generator.newLabel());
2188 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2189 }
2190
2191 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
2192 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2193 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2194 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2195 labelVector.append(generator.newLabel());
2196 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2197 }
2198 defaultLabel = generator.newLabel();
2199 generator.emitJump(defaultLabel.get());
2200 }
2201
2202 RegisterID* result = 0;
2203
2204 size_t i = 0;
2205 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
2206 generator.emitLabel(labelVector[i++].get());
2207 result = statementListEmitCode(list->getClause()->children(), generator, dst);
2208 }
2209
2210 if (m_defaultClause) {
2211 generator.emitLabel(defaultLabel.get());
2212 result = statementListEmitCode(m_defaultClause->children(), generator, dst);
2213 }
2214
2215 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
2216 generator.emitLabel(labelVector[i++].get());
2217 result = statementListEmitCode(list->getClause()->children(), generator, dst);
2218 }
2219 if (!m_defaultClause)
2220 generator.emitLabel(defaultLabel.get());
2221
2222 ASSERT(i == labelVector.size());
2223 if (switchType != SwitchInfo::SwitchNone) {
2224 ASSERT(labelVector.size() == literalVector.size());
2225 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2226 }
2227 return result;
2228}
2229
2230// ------------------------------ SwitchNode -----------------------------------
2231
2232SwitchNode::~SwitchNode()
2233{
2234 NodeReleaser::releaseAllNodes(this);
2235}
2236
2237void SwitchNode::releaseNodes(NodeReleaser& releaser)
2238{
2239 releaser.release(m_expr);
2240 releaser.release(m_block);
2241}
2242
2243RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2244{
2245 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
2246
2247 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
2248 RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
2249
2250 generator.emitLabel(scope->breakTarget());
2251 return r1;
2252}
2253
2254// ------------------------------ LabelNode ------------------------------------
2255
2256LabelNode::~LabelNode()
2257{
2258 NodeReleaser::releaseAllNodes(this);
2259}
2260
2261void LabelNode::releaseNodes(NodeReleaser& releaser)
2262{
2263 releaser.release(m_statement);
2264}
2265
2266RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2267{
2268 if (generator.breakTarget(m_name))
2269 return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
2270
2271 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
2272 RegisterID* r0 = generator.emitNode(dst, m_statement.get());
2273
2274 generator.emitLabel(scope->breakTarget());
2275 return r0;
2276}
2277
2278// ------------------------------ ThrowNode ------------------------------------
2279
2280ThrowNode::~ThrowNode()
2281{
2282 NodeReleaser::releaseAllNodes(this);
2283}
2284
2285void ThrowNode::releaseNodes(NodeReleaser& releaser)
2286{
2287 releaser.release(m_expr);
2288}
2289
2290RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2291{
2292 if (dst == ignoredResult())
2293 dst = 0;
2294 RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get());
2295 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
2296 generator.emitThrow(expr.get());
2297 return dst;
2298}
2299
2300// ------------------------------ TryNode --------------------------------------
2301
2302TryNode::~TryNode()
2303{
2304 NodeReleaser::releaseAllNodes(this);
2305}
2306
2307void TryNode::releaseNodes(NodeReleaser& releaser)
2308{
2309 releaser.release(m_tryBlock);
2310 releaser.release(m_catchBlock);
2311 releaser.release(m_finallyBlock);
2312}
2313
2314RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2315{
2316 RefPtr<LabelID> tryStartLabel = generator.newLabel();
2317 RefPtr<LabelID> tryEndLabel = generator.newLabel();
2318 RefPtr<LabelID> finallyStart;
2319 RefPtr<RegisterID> finallyReturnAddr;
2320 if (m_finallyBlock) {
2321 finallyStart = generator.newLabel();
2322 finallyReturnAddr = generator.newTemporary();
2323 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
2324 }
2325 generator.emitLabel(tryStartLabel.get());
2326 generator.emitNode(dst, m_tryBlock.get());
2327 generator.emitLabel(tryEndLabel.get());
2328
2329 if (m_catchBlock) {
2330 RefPtr<LabelID> handlerEndLabel = generator.newLabel();
2331 generator.emitJump(handlerEndLabel.get());
2332 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
2333 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
2334 generator.emitNode(dst, m_catchBlock.get());
2335 generator.emitPopScope();
2336 generator.emitLabel(handlerEndLabel.get());
2337 }
2338
2339 if (m_finallyBlock) {
2340 generator.popFinallyContext();
2341 // there may be important registers live at the time we jump
2342 // to a finally block (such as for a return or throw) so we
2343 // ref the highest register ever used as a conservative
2344 // approach to not clobbering anything important
2345 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
2346 RefPtr<LabelID> finallyEndLabel = generator.newLabel();
2347 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
2348 // Use a label to record the subtle fact that sret will return to the
2349 // next instruction. sret is the only way to jump without an explicit label.
2350 generator.emitLabel(generator.newLabel().get());
2351 generator.emitJump(finallyEndLabel.get());
2352
2353 // Finally block for exception path
2354 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
2355 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
2356 // Use a label to record the subtle fact that sret will return to the
2357 // next instruction. sret is the only way to jump without an explicit label.
2358 generator.emitLabel(generator.newLabel().get());
2359 generator.emitThrow(tempExceptionRegister.get());
2360
2361 // emit the finally block itself
2362 generator.emitLabel(finallyStart.get());
2363 generator.emitNode(dst, m_finallyBlock.get());
2364 generator.emitSubroutineReturn(finallyReturnAddr.get());
2365
2366 generator.emitLabel(finallyEndLabel.get());
2367 }
2368
2369 return dst;
2370}
2371
2372// ------------------------------ ParameterNode -----------------------------
2373
2374ParameterNode::~ParameterNode()
2375{
2376 NodeReleaser::releaseAllNodes(this);
2377}
2378
2379void ParameterNode::releaseNodes(NodeReleaser& releaser)
2380{
2381 releaser.release(m_next);
2382}
2383
2384// ------------------------------ ScopeNode -----------------------------
2385
2386ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
2387 : BlockNode(globalData, children)
2388 , m_source(source)
2389 , m_features(features)
2390 , m_numConstants(numConstants)
2391{
2392 if (varStack)
2393 m_varStack = *varStack;
2394 if (funcStack)
2395 m_functionStack = *funcStack;
2396#if ENABLE(OPCODE_SAMPLING)
2397 globalData->machine->sampler()->notifyOfScope(this);
2398#endif
2399}
2400
2401// ------------------------------ ProgramNode -----------------------------
2402
2403ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2404 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
2405{
2406}
2407
2408ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2409{
2410 return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
2411}
2412
2413// ------------------------------ EvalNode -----------------------------
2414
2415EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2416 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
2417{
2418}
2419
2420RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
2421{
2422 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
2423
2424 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2425 generator.emitLoad(dstRegister.get(), jsUndefined());
2426 statementListEmitCode(m_children, generator, dstRegister.get());
2427
2428 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
2429 generator.emitEnd(dstRegister.get());
2430 return 0;
2431}
2432
2433void EvalNode::generateCode(ScopeChainNode* scopeChainNode)
2434{
2435 ScopeChain scopeChain(scopeChainNode);
2436 JSGlobalObject* globalObject = scopeChain.globalObject();
2437
2438 SymbolTable symbolTable;
2439 m_code.set(new EvalCodeBlock(this, globalObject, source().provider()));
2440
2441 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &symbolTable, m_code.get());
2442 generator.generate();
2443}
2444
2445EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2446{
2447 return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
2448}
2449
2450// ------------------------------ FunctionBodyNode -----------------------------
2451
2452FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2453 : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
2454 , m_parameters(0)
2455 , m_parameterCount(0)
2456 , m_refCount(0)
2457{
2458}
2459
2460FunctionBodyNode::~FunctionBodyNode()
2461{
2462 ASSERT(!m_refCount);
2463 fastFree(m_parameters);
2464}
2465
2466void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
2467{
2468 Vector<Identifier> parameters;
2469 for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
2470 parameters.append(parameter->ident());
2471 size_t count = parameters.size();
2472
2473 setSource(source);
2474 finishParsing(parameters.releaseBuffer(), count);
2475}
2476
2477void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
2478{
2479 ASSERT(!source().isNull());
2480 m_parameters = parameters;
2481 m_parameterCount = parameterCount;
2482}
2483
2484void FunctionBodyNode::mark()
2485{
2486 if (m_code)
2487 m_code->mark();
2488}
2489
2490FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
2491{
2492 return new FunctionBodyNode(globalData, children, varStack, funcStack, SourceCode(), features, numConstants);
2493}
2494
2495FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2496{
2497 return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
2498}
2499
2500void FunctionBodyNode::generateCode(ScopeChainNode* scopeChainNode)
2501{
2502 ScopeChain scopeChain(scopeChainNode);
2503 JSGlobalObject* globalObject = scopeChain.globalObject();
2504
2505 m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
2506
2507 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get());
2508 generator.generate();
2509}
2510
2511RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
2512{
2513 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
2514 statementListEmitCode(m_children, generator, ignoredResult());
2515 if (!m_children.size() || !m_children.last()->isReturnNode()) {
2516 RegisterID* r0 = generator.emitLoad(0, jsUndefined());
2517 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2518 generator.emitReturn(r0);
2519 }
2520 return 0;
2521}
2522
2523RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
2524{
2525 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
2526
2527 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2528 generator.emitLoad(dstRegister.get(), jsUndefined());
2529 statementListEmitCode(m_children, generator, dstRegister.get());
2530
2531 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
2532 generator.emitEnd(dstRegister.get());
2533 return 0;
2534}
2535
2536void ProgramNode::generateCode(ScopeChainNode* scopeChainNode)
2537{
2538 ScopeChain scopeChain(scopeChainNode);
2539 JSGlobalObject* globalObject = scopeChain.globalObject();
2540
2541 m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
2542
2543 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack);
2544 generator.generate();
2545}
2546
2547UString FunctionBodyNode::paramString() const
2548{
2549 UString s("");
2550 for (size_t pos = 0; pos < m_parameterCount; ++pos) {
2551 if (!s.isEmpty())
2552 s += ", ";
2553 s += parameters()[pos].ustring();
2554 }
2555
2556 return s;
2557}
2558
2559Identifier* FunctionBodyNode::copyParameters()
2560{
2561 Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
2562 VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
2563 return parameters;
2564}
2565
2566// ------------------------------ FuncDeclNode ---------------------------------
2567
2568FuncDeclNode::~FuncDeclNode()
2569{
2570 NodeReleaser::releaseAllNodes(this);
2571}
2572
2573void FuncDeclNode::releaseNodes(NodeReleaser& releaser)
2574{
2575 releaser.release(m_parameter);
2576 releaser.release(m_body);
2577}
2578
2579JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2580{
2581 return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2582}
2583
2584RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
2585{
2586 return dst;
2587}
2588
2589// ------------------------------ FuncExprNode ---------------------------------
2590
2591FuncExprNode::~FuncExprNode()
2592{
2593 NodeReleaser::releaseAllNodes(this);
2594}
2595
2596void FuncExprNode::releaseNodes(NodeReleaser& releaser)
2597{
2598 releaser.release(m_parameter);
2599 releaser.release(m_body);
2600}
2601
2602RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2603{
2604 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2605}
2606
2607JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2608{
2609 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2610
2611 /*
2612 The Identifier in a FunctionExpression can be referenced from inside
2613 the FunctionExpression's FunctionBody to allow the function to call
2614 itself recursively. However, unlike in a FunctionDeclaration, the
2615 Identifier in a FunctionExpression cannot be referenced from and
2616 does not affect the scope enclosing the FunctionExpression.
2617 */
2618
2619 if (!m_ident.isNull()) {
2620 JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
2621 func->scope().push(functionScopeObject);
2622 }
2623
2624 return func;
2625}
2626
2627} // namespace JSC
Note: See TracBrowser for help on using the repository browser.