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

Last change on this file since 38420 was 38420, checked in by [email protected], 17 years ago

2008-11-15 Maciej Stachowiak <[email protected]>

Reviewed by Sam Weinig.


  • Remove SymbolTable from FunctionBodyNode and move it to CodeBlock


It's not needed for functions that have never been executed, so no
need to waste the memory. Saves ~4M on membuster after 30 pages.

  • VM/CodeBlock.h:
  • VM/Machine.cpp: (JSC::Machine::retrieveArguments):
  • parser/Nodes.cpp: (JSC::EvalNode::generateCode): (JSC::FunctionBodyNode::generateCode):
  • parser/Nodes.h:
  • runtime/JSActivation.h: (JSC::JSActivation::JSActivationData::JSActivationData):
  • Property svn:eol-style set to native
File size: 90.4 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(divot(), startOffset(), 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(divot(), startOffset(), 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(divot(), startOffset(), 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(divot(), startOffset(), 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(), divot(), startOffset(), 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> func = generator.tempDestination(dst);
589 RefPtr<RegisterID> thisRegister = generator.newTemporary();
590 generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
591 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), 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 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
611 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
612}
613
614// ------------------------------ FunctionCallResolveNode ----------------------------------
615
616FunctionCallResolveNode::~FunctionCallResolveNode()
617{
618 NodeReleaser::releaseAllNodes(this);
619}
620
621void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser)
622{
623 releaser.release(m_args);
624}
625
626RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
627{
628 if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
629 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
630 return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
631 }
632
633 int index = 0;
634 size_t depth = 0;
635 JSObject* globalObject = 0;
636 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
637 RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
638 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
639 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
640 }
641
642 RefPtr<RegisterID> func = generator.tempDestination(dst);
643 RefPtr<RegisterID> thisRegister = generator.newTemporary();
644 int identifierStart = divot() - startOffset();
645 generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
646 generator.emitResolveFunction(thisRegister.get(), func.get(), m_ident);
647 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
648}
649
650// ------------------------------ FunctionCallBracketNode ----------------------------------
651
652FunctionCallBracketNode::~FunctionCallBracketNode()
653{
654 NodeReleaser::releaseAllNodes(this);
655}
656
657void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser)
658{
659 releaser.release(m_base);
660 releaser.release(m_subscript);
661 releaser.release(m_args);
662}
663
664RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
665{
666 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
667 RegisterID* property = generator.emitNode(m_subscript.get());
668 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
669 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
670 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
671 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
672}
673
674// ------------------------------ FunctionCallDotNode ----------------------------------
675
676FunctionCallDotNode::~FunctionCallDotNode()
677{
678 NodeReleaser::releaseAllNodes(this);
679}
680
681void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser)
682{
683 releaser.release(m_base);
684 releaser.release(m_args);
685}
686
687RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
688{
689 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
690 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
691 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
692 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
693 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
694}
695
696// ------------------------------ PostfixResolveNode ----------------------------------
697
698static RegisterID* emitPreIncOrDec(CodeGenerator& generator, RegisterID* srcDst, Operator oper)
699{
700 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
701}
702
703static RegisterID* emitPostIncOrDec(CodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
704{
705 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
706}
707
708RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
709{
710 if (RegisterID* local = generator.registerFor(m_ident)) {
711 if (generator.isLocalConstant(m_ident)) {
712 if (dst == ignoredResult())
713 return 0;
714 return generator.emitToJSNumber(generator.finalDestination(dst), local);
715 }
716
717 if (dst == ignoredResult())
718 return emitPreIncOrDec(generator, local, m_operator);
719 return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
720 }
721
722 int index = 0;
723 size_t depth = 0;
724 JSObject* globalObject = 0;
725 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
726 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
727 RegisterID* oldValue;
728 if (dst == ignoredResult()) {
729 oldValue = 0;
730 emitPreIncOrDec(generator, value.get(), m_operator);
731 } else {
732 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
733 }
734 generator.emitPutScopedVar(depth, index, value.get(), globalObject);
735 return oldValue;
736 }
737
738 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
739 RefPtr<RegisterID> value = generator.newTemporary();
740 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
741 RegisterID* oldValue;
742 if (dst == ignoredResult()) {
743 oldValue = 0;
744 emitPreIncOrDec(generator, value.get(), m_operator);
745 } else {
746 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
747 }
748 generator.emitPutById(base.get(), m_ident, value.get());
749 return oldValue;
750}
751
752// ------------------------------ PostfixBracketNode ----------------------------------
753
754PostfixBracketNode::~PostfixBracketNode()
755{
756 NodeReleaser::releaseAllNodes(this);
757}
758
759void PostfixBracketNode::releaseNodes(NodeReleaser& releaser)
760{
761 releaser.release(m_base);
762 releaser.release(m_subscript);
763}
764
765RegisterID* PostfixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
766{
767 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
768 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
769
770 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
771 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
772 RegisterID* oldValue;
773 if (dst == ignoredResult()) {
774 oldValue = 0;
775 if (m_operator == OpPlusPlus)
776 generator.emitPreInc(value.get());
777 else
778 generator.emitPreDec(value.get());
779 } else {
780 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
781 }
782 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
783 generator.emitPutByVal(base.get(), property.get(), value.get());
784 return oldValue;
785}
786
787// ------------------------------ PostfixDotNode ----------------------------------
788
789PostfixDotNode::~PostfixDotNode()
790{
791 NodeReleaser::releaseAllNodes(this);
792}
793
794void PostfixDotNode::releaseNodes(NodeReleaser& releaser)
795{
796 releaser.release(m_base);
797}
798
799RegisterID* PostfixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
800{
801 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
802
803 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
804 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
805 RegisterID* oldValue;
806 if (dst == ignoredResult()) {
807 oldValue = 0;
808 if (m_operator == OpPlusPlus)
809 generator.emitPreInc(value.get());
810 else
811 generator.emitPreDec(value.get());
812 } else {
813 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
814 }
815 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
816 generator.emitPutById(base.get(), m_ident, value.get());
817 return oldValue;
818}
819
820// ------------------------------ PostfixErrorNode -----------------------------------
821
822PostfixErrorNode::~PostfixErrorNode()
823{
824 NodeReleaser::releaseAllNodes(this);
825}
826
827void PostfixErrorNode::releaseNodes(NodeReleaser& releaser)
828{
829 releaser.release(m_expr);
830}
831
832RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
833{
834 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.");
835}
836
837// ------------------------------ DeleteResolveNode -----------------------------------
838
839RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
840{
841 if (generator.registerFor(m_ident))
842 return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
843
844 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
845 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
846 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
847}
848
849// ------------------------------ DeleteBracketNode -----------------------------------
850
851DeleteBracketNode::~DeleteBracketNode()
852{
853 NodeReleaser::releaseAllNodes(this);
854}
855
856void DeleteBracketNode::releaseNodes(NodeReleaser& releaser)
857{
858 releaser.release(m_base);
859 releaser.release(m_subscript);
860}
861
862RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
863{
864 RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
865 RegisterID* r1 = generator.emitNode(m_subscript.get());
866
867 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
868 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
869}
870
871// ------------------------------ DeleteDotNode -----------------------------------
872
873DeleteDotNode::~DeleteDotNode()
874{
875 NodeReleaser::releaseAllNodes(this);
876}
877
878void DeleteDotNode::releaseNodes(NodeReleaser& releaser)
879{
880 releaser.release(m_base);
881}
882
883RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
884{
885 RegisterID* r0 = generator.emitNode(m_base.get());
886
887 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
888 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
889}
890
891// ------------------------------ DeleteValueNode -----------------------------------
892
893DeleteValueNode::~DeleteValueNode()
894{
895 NodeReleaser::releaseAllNodes(this);
896}
897
898void DeleteValueNode::releaseNodes(NodeReleaser& releaser)
899{
900 releaser.release(m_expr);
901}
902
903RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
904{
905 generator.emitNode(ignoredResult(), m_expr.get());
906
907 // delete on a non-location expression ignores the value and returns true
908 return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
909}
910
911// ------------------------------ VoidNode -------------------------------------
912
913VoidNode::~VoidNode()
914{
915 NodeReleaser::releaseAllNodes(this);
916}
917
918void VoidNode::releaseNodes(NodeReleaser& releaser)
919{
920 releaser.release(m_expr);
921}
922
923RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
924{
925 if (dst == ignoredResult()) {
926 generator.emitNode(ignoredResult(), m_expr.get());
927 return 0;
928 }
929 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
930 return generator.emitLoad(dst, jsUndefined());
931}
932
933// ------------------------------ TypeOfValueNode -----------------------------------
934
935RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
936{
937 if (RegisterID* local = generator.registerFor(m_ident)) {
938 if (dst == ignoredResult())
939 return 0;
940 return generator.emitTypeOf(generator.finalDestination(dst), local);
941 }
942
943 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
944 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
945 if (dst == ignoredResult())
946 return 0;
947 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
948}
949
950// ------------------------------ TypeOfValueNode -----------------------------------
951
952TypeOfValueNode::~TypeOfValueNode()
953{
954 NodeReleaser::releaseAllNodes(this);
955}
956
957void TypeOfValueNode::releaseNodes(NodeReleaser& releaser)
958{
959 releaser.release(m_expr);
960}
961
962RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
963{
964 if (dst == ignoredResult()) {
965 generator.emitNode(ignoredResult(), m_expr.get());
966 return 0;
967 }
968 RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
969 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
970}
971
972// ------------------------------ PrefixResolveNode ----------------------------------
973
974RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
975{
976 if (RegisterID* local = generator.registerFor(m_ident)) {
977 if (generator.isLocalConstant(m_ident)) {
978 if (dst == ignoredResult())
979 return 0;
980 RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
981 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
982 }
983
984 emitPreIncOrDec(generator, local, m_operator);
985 return generator.moveToDestinationIfNeeded(dst, local);
986 }
987
988 int index = 0;
989 size_t depth = 0;
990 JSObject* globalObject = 0;
991 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
992 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
993 emitPreIncOrDec(generator, propDst.get(), m_operator);
994 generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
995 return generator.moveToDestinationIfNeeded(dst, propDst.get());
996 }
997
998 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
999 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1000 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
1001 emitPreIncOrDec(generator, propDst.get(), m_operator);
1002 generator.emitPutById(base.get(), m_ident, propDst.get());
1003 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1004}
1005
1006// ------------------------------ PrefixBracketNode ----------------------------------
1007
1008PrefixBracketNode::~PrefixBracketNode()
1009{
1010 NodeReleaser::releaseAllNodes(this);
1011}
1012
1013void PrefixBracketNode::releaseNodes(NodeReleaser& releaser)
1014{
1015 releaser.release(m_base);
1016 releaser.release(m_subscript);
1017}
1018
1019RegisterID* PrefixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1020{
1021 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1022 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
1023 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1024
1025 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
1026 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
1027 if (m_operator == OpPlusPlus)
1028 generator.emitPreInc(value);
1029 else
1030 generator.emitPreDec(value);
1031 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1032 generator.emitPutByVal(base.get(), property.get(), value);
1033 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1034}
1035
1036// ------------------------------ PrefixDotNode ----------------------------------
1037
1038PrefixDotNode::~PrefixDotNode()
1039{
1040 NodeReleaser::releaseAllNodes(this);
1041}
1042
1043void PrefixDotNode::releaseNodes(NodeReleaser& releaser)
1044{
1045 releaser.release(m_base);
1046}
1047
1048RegisterID* PrefixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1049{
1050 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1051 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1052
1053 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
1054 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
1055 if (m_operator == OpPlusPlus)
1056 generator.emitPreInc(value);
1057 else
1058 generator.emitPreDec(value);
1059 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1060 generator.emitPutById(base.get(), m_ident, value);
1061 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1062}
1063
1064// ------------------------------ PrefixErrorNode -----------------------------------
1065
1066PrefixErrorNode::~PrefixErrorNode()
1067{
1068 NodeReleaser::releaseAllNodes(this);
1069}
1070
1071void PrefixErrorNode::releaseNodes(NodeReleaser& releaser)
1072{
1073 releaser.release(m_expr);
1074}
1075
1076RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
1077{
1078 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.");
1079}
1080
1081// ------------------------------ Unary Operation Nodes -----------------------------------
1082
1083UnaryOpNode::~UnaryOpNode()
1084{
1085 NodeReleaser::releaseAllNodes(this);
1086}
1087
1088void UnaryOpNode::releaseNodes(NodeReleaser& releaser)
1089{
1090 releaser.release(m_expr);
1091}
1092
1093RegisterID* UnaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1094{
1095 RegisterID* src = generator.emitNode(m_expr.get());
1096 return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src, m_expr->resultDescriptor());
1097}
1098
1099// ------------------------------ Binary Operation Nodes -----------------------------------
1100
1101BinaryOpNode::~BinaryOpNode()
1102{
1103 NodeReleaser::releaseAllNodes(this);
1104}
1105
1106void BinaryOpNode::releaseNodes(NodeReleaser& releaser)
1107{
1108 releaser.release(m_expr1);
1109 releaser.release(m_expr2);
1110}
1111
1112RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1113{
1114 OpcodeID opcode = this->opcode();
1115 if (opcode == op_neq) {
1116 if (m_expr1->isNull() || m_expr2->isNull()) {
1117 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
1118 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown());
1119 }
1120 }
1121
1122 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1123 RegisterID* src2 = generator.emitNode(m_expr2.get());
1124 return generator.emitBinaryOp(opcode, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1125}
1126
1127RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1128{
1129 if (m_expr1->isNull() || m_expr2->isNull()) {
1130 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
1131 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown());
1132 }
1133
1134 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1135 RegisterID* src2 = generator.emitNode(m_expr2.get());
1136 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1137}
1138
1139RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1140{
1141 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1142 RegisterID* src2 = generator.emitNode(m_expr2.get());
1143 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1144}
1145
1146RegisterID* ReverseBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1147{
1148 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1149 RegisterID* src2 = generator.emitNode(m_expr2.get());
1150 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
1151}
1152
1153RegisterID* ThrowableBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1154{
1155 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1156 RegisterID* src2 = generator.emitNode(m_expr2.get());
1157 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1158 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1159}
1160
1161RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1162{
1163 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1164 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
1165
1166 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1167 RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
1168
1169 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1170 return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
1171}
1172
1173// ------------------------------ LogicalOpNode ----------------------------
1174
1175LogicalOpNode::~LogicalOpNode()
1176{
1177 NodeReleaser::releaseAllNodes(this);
1178}
1179
1180void LogicalOpNode::releaseNodes(NodeReleaser& releaser)
1181{
1182 releaser.release(m_expr1);
1183 releaser.release(m_expr2);
1184}
1185
1186RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1187{
1188 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1189 RefPtr<LabelID> target = generator.newLabel();
1190
1191 generator.emitNode(temp.get(), m_expr1.get());
1192 if (m_operator == OpLogicalAnd)
1193 generator.emitJumpIfFalse(temp.get(), target.get());
1194 else
1195 generator.emitJumpIfTrue(temp.get(), target.get());
1196 generator.emitNode(temp.get(), m_expr2.get());
1197 generator.emitLabel(target.get());
1198
1199 return generator.moveToDestinationIfNeeded(dst, temp.get());
1200}
1201
1202// ------------------------------ ConditionalNode ------------------------------
1203
1204ConditionalNode::~ConditionalNode()
1205{
1206 NodeReleaser::releaseAllNodes(this);
1207}
1208
1209void ConditionalNode::releaseNodes(NodeReleaser& releaser)
1210{
1211 releaser.release(m_logical);
1212 releaser.release(m_expr1);
1213 releaser.release(m_expr2);
1214}
1215
1216RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1217{
1218 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1219 RefPtr<LabelID> beforeElse = generator.newLabel();
1220 RefPtr<LabelID> afterElse = generator.newLabel();
1221
1222 RegisterID* cond = generator.emitNode(m_logical.get());
1223 generator.emitJumpIfFalse(cond, beforeElse.get());
1224
1225 generator.emitNode(newDst.get(), m_expr1.get());
1226 generator.emitJump(afterElse.get());
1227
1228 generator.emitLabel(beforeElse.get());
1229 generator.emitNode(newDst.get(), m_expr2.get());
1230
1231 generator.emitLabel(afterElse.get());
1232
1233 return newDst.get();
1234}
1235
1236// ------------------------------ ReadModifyResolveNode -----------------------------------
1237
1238ReadModifyResolveNode::~ReadModifyResolveNode()
1239{
1240 NodeReleaser::releaseAllNodes(this);
1241}
1242
1243void ReadModifyResolveNode::releaseNodes(NodeReleaser& releaser)
1244{
1245 releaser.release(m_right);
1246}
1247
1248// FIXME: should this be moved to be a method on CodeGenerator?
1249static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types)
1250{
1251 OpcodeID opcode;
1252 switch (oper) {
1253 case OpMultEq:
1254 opcode = op_mul;
1255 break;
1256 case OpDivEq:
1257 opcode = op_div;
1258 break;
1259 case OpPlusEq:
1260 opcode = op_add;
1261 break;
1262 case OpMinusEq:
1263 opcode = op_sub;
1264 break;
1265 case OpLShift:
1266 opcode = op_lshift;
1267 break;
1268 case OpRShift:
1269 opcode = op_rshift;
1270 break;
1271 case OpURShift:
1272 opcode = op_urshift;
1273 break;
1274 case OpAndEq:
1275 opcode = op_bitand;
1276 break;
1277 case OpXOrEq:
1278 opcode = op_bitxor;
1279 break;
1280 case OpOrEq:
1281 opcode = op_bitor;
1282 break;
1283 case OpModEq:
1284 opcode = op_mod;
1285 break;
1286 default:
1287 ASSERT_NOT_REACHED();
1288 return dst;
1289 }
1290
1291 return generator.emitBinaryOp(opcode, dst, src1, src2, types);
1292}
1293
1294RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1295{
1296 if (RegisterID* local = generator.registerFor(m_ident)) {
1297 if (generator.isLocalConstant(m_ident)) {
1298 RegisterID* src2 = generator.emitNode(m_right.get());
1299 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1300 }
1301
1302 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
1303 RefPtr<RegisterID> result = generator.newTemporary();
1304 generator.emitMove(result.get(), local);
1305 RegisterID* src2 = generator.emitNode(m_right.get());
1306 emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1307 generator.emitMove(local, result.get());
1308 return generator.moveToDestinationIfNeeded(dst, result.get());
1309 }
1310
1311 RegisterID* src2 = generator.emitNode(m_right.get());
1312 RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1313 return generator.moveToDestinationIfNeeded(dst, result);
1314 }
1315
1316 int index = 0;
1317 size_t depth = 0;
1318 JSObject* globalObject = 0;
1319 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1320 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
1321 RegisterID* src2 = generator.emitNode(m_right.get());
1322 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1323 generator.emitPutScopedVar(depth, index, result, globalObject);
1324 return result;
1325 }
1326
1327 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
1328 generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
1329 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
1330 RegisterID* src2 = generator.emitNode(m_right.get());
1331 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1332 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1333 return generator.emitPutById(base.get(), m_ident, result);
1334}
1335
1336// ------------------------------ AssignResolveNode -----------------------------------
1337
1338AssignResolveNode::~AssignResolveNode()
1339{
1340 NodeReleaser::releaseAllNodes(this);
1341}
1342
1343void AssignResolveNode::releaseNodes(NodeReleaser& releaser)
1344{
1345 releaser.release(m_right);
1346}
1347
1348RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1349{
1350 if (RegisterID* local = generator.registerFor(m_ident)) {
1351 if (generator.isLocalConstant(m_ident))
1352 return generator.emitNode(dst, m_right.get());
1353
1354 RegisterID* result = generator.emitNode(local, m_right.get());
1355 return generator.moveToDestinationIfNeeded(dst, result);
1356 }
1357
1358 int index = 0;
1359 size_t depth = 0;
1360 JSObject* globalObject = 0;
1361 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1362 if (dst == ignoredResult())
1363 dst = 0;
1364 RegisterID* value = generator.emitNode(dst, m_right.get());
1365 generator.emitPutScopedVar(depth, index, value, globalObject);
1366 return value;
1367 }
1368
1369 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1370 if (dst == ignoredResult())
1371 dst = 0;
1372 RegisterID* value = generator.emitNode(dst, m_right.get());
1373 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1374 return generator.emitPutById(base.get(), m_ident, value);
1375}
1376
1377// ------------------------------ AssignDotNode -----------------------------------
1378
1379AssignDotNode::~AssignDotNode()
1380{
1381 NodeReleaser::releaseAllNodes(this);
1382}
1383
1384void AssignDotNode::releaseNodes(NodeReleaser& releaser)
1385{
1386 releaser.release(m_base);
1387 releaser.release(m_right);
1388}
1389
1390RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1391{
1392 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
1393 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1394 RegisterID* result = generator.emitNode(value.get(), m_right.get());
1395 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1396 generator.emitPutById(base.get(), m_ident, result);
1397 return generator.moveToDestinationIfNeeded(dst, result);
1398}
1399
1400// ------------------------------ ReadModifyDotNode -----------------------------------
1401
1402ReadModifyDotNode::~ReadModifyDotNode()
1403{
1404 NodeReleaser::releaseAllNodes(this);
1405}
1406
1407void ReadModifyDotNode::releaseNodes(NodeReleaser& releaser)
1408{
1409 releaser.release(m_base);
1410 releaser.release(m_right);
1411}
1412
1413RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1414{
1415 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
1416
1417 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1418 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
1419 RegisterID* change = generator.emitNode(m_right.get());
1420 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1421
1422 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1423 return generator.emitPutById(base.get(), m_ident, updatedValue);
1424}
1425
1426// ------------------------------ AssignErrorNode -----------------------------------
1427
1428AssignErrorNode::~AssignErrorNode()
1429{
1430 NodeReleaser::releaseAllNodes(this);
1431}
1432
1433void AssignErrorNode::releaseNodes(NodeReleaser& releaser)
1434{
1435 releaser.release(m_left);
1436 releaser.release(m_right);
1437}
1438
1439RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
1440{
1441 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
1442}
1443
1444// ------------------------------ AssignBracketNode -----------------------------------
1445
1446AssignBracketNode::~AssignBracketNode()
1447{
1448 NodeReleaser::releaseAllNodes(this);
1449}
1450
1451void AssignBracketNode::releaseNodes(NodeReleaser& releaser)
1452{
1453 releaser.release(m_base);
1454 releaser.release(m_subscript);
1455 releaser.release(m_right);
1456}
1457
1458RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1459{
1460 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1461 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1462 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1463 RegisterID* result = generator.emitNode(value.get(), m_right.get());
1464
1465 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1466 generator.emitPutByVal(base.get(), property.get(), result);
1467 return generator.moveToDestinationIfNeeded(dst, result);
1468}
1469
1470// ------------------------------ ReadModifyBracketNode -----------------------------------
1471
1472ReadModifyBracketNode::~ReadModifyBracketNode()
1473{
1474 NodeReleaser::releaseAllNodes(this);
1475}
1476
1477void ReadModifyBracketNode::releaseNodes(NodeReleaser& releaser)
1478{
1479 releaser.release(m_base);
1480 releaser.release(m_subscript);
1481 releaser.release(m_right);
1482}
1483
1484RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1485{
1486 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1487 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1488
1489 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1490 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1491 RegisterID* change = generator.emitNode(m_right.get());
1492 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1493
1494 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1495 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1496
1497 return updatedValue;
1498}
1499
1500// ------------------------------ CommaNode ------------------------------------
1501
1502CommaNode::~CommaNode()
1503{
1504 NodeReleaser::releaseAllNodes(this);
1505}
1506
1507void CommaNode::releaseNodes(NodeReleaser& releaser)
1508{
1509 releaser.release(m_expr1);
1510 releaser.release(m_expr2);
1511}
1512
1513RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1514{
1515 generator.emitNode(ignoredResult(), m_expr1.get());
1516 return generator.emitNode(dst, m_expr2.get());
1517}
1518
1519// ------------------------------ ConstDeclNode ------------------------------------
1520
1521ConstDeclNode::~ConstDeclNode()
1522{
1523 NodeReleaser::releaseAllNodes(this);
1524}
1525
1526void ConstDeclNode::releaseNodes(NodeReleaser& releaser)
1527{
1528 releaser.release(m_next);
1529 releaser.release(m_init);
1530}
1531
1532ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
1533 : ExpressionNode(globalData)
1534 , m_ident(ident)
1535 , m_init(init)
1536{
1537}
1538
1539RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
1540{
1541 if (RegisterID* local = generator.constRegisterFor(m_ident)) {
1542 if (!m_init)
1543 return local;
1544
1545 return generator.emitNode(local, m_init.get());
1546 }
1547
1548 // FIXME: While this code should only be hit in eval code, it will potentially
1549 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1550 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1551 RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined());
1552 return generator.emitPutById(base.get(), m_ident, value);
1553}
1554
1555RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
1556{
1557 RegisterID* result = 0;
1558 for (ConstDeclNode* n = this; n; n = n->m_next.get())
1559 result = n->emitCodeSingle(generator);
1560
1561 return result;
1562}
1563
1564// ------------------------------ ConstStatementNode -----------------------------
1565
1566ConstStatementNode::~ConstStatementNode()
1567{
1568 NodeReleaser::releaseAllNodes(this);
1569}
1570
1571void ConstStatementNode::releaseNodes(NodeReleaser& releaser)
1572{
1573 releaser.release(m_next);
1574}
1575
1576RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1577{
1578 return generator.emitNode(m_next.get());
1579}
1580
1581// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
1582
1583static inline RegisterID* statementListEmitCode(const StatementVector& statements, CodeGenerator& generator, RegisterID* dst)
1584{
1585 StatementVector::const_iterator end = statements.end();
1586 for (StatementVector::const_iterator it = statements.begin(); it != end; ++it) {
1587 StatementNode* n = it->get();
1588 if (!n->isLoop())
1589 generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
1590 generator.emitNode(dst, n);
1591 }
1592 return 0;
1593}
1594
1595// ------------------------------ BlockNode ------------------------------------
1596
1597BlockNode::~BlockNode()
1598{
1599 NodeReleaser::releaseAllNodes(this);
1600}
1601
1602void BlockNode::releaseNodes(NodeReleaser& releaser)
1603{
1604 size_t size = m_children.size();
1605 for (size_t i = 0; i < size; ++i)
1606 releaser.release(m_children[i]);
1607}
1608
1609BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
1610 : StatementNode(globalData)
1611{
1612 if (children)
1613 children->releaseContentsIntoVector(m_children);
1614}
1615
1616RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1617{
1618 return statementListEmitCode(m_children, generator, dst);
1619}
1620
1621// ------------------------------ EmptyStatementNode ---------------------------
1622
1623RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
1624{
1625 return dst;
1626}
1627
1628// ------------------------------ DebuggerStatementNode ---------------------------
1629
1630RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1631{
1632 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1633 return dst;
1634}
1635
1636// ------------------------------ ExprStatementNode ----------------------------
1637
1638RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1639{
1640 ASSERT(m_expr);
1641 return generator.emitNode(dst, m_expr.get());
1642}
1643
1644// ------------------------------ VarStatementNode ----------------------------
1645
1646VarStatementNode::~VarStatementNode()
1647{
1648 NodeReleaser::releaseAllNodes(this);
1649}
1650
1651void VarStatementNode::releaseNodes(NodeReleaser& releaser)
1652{
1653 releaser.release(m_expr);
1654}
1655
1656RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1657{
1658 ASSERT(m_expr);
1659 return generator.emitNode(m_expr.get());
1660}
1661
1662// ------------------------------ IfNode ---------------------------------------
1663
1664IfNode::~IfNode()
1665{
1666 NodeReleaser::releaseAllNodes(this);
1667}
1668
1669void IfNode::releaseNodes(NodeReleaser& releaser)
1670{
1671 releaser.release(m_condition);
1672 releaser.release(m_ifBlock);
1673}
1674
1675RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1676{
1677 RefPtr<LabelID> afterThen = generator.newLabel();
1678
1679 RegisterID* cond = generator.emitNode(m_condition.get());
1680 generator.emitJumpIfFalse(cond, afterThen.get());
1681
1682 if (!m_ifBlock->isBlock())
1683 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1684
1685 generator.emitNode(dst, m_ifBlock.get());
1686 generator.emitLabel(afterThen.get());
1687
1688 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1689 return 0;
1690}
1691
1692// ------------------------------ IfElseNode ---------------------------------------
1693
1694IfElseNode::~IfElseNode()
1695{
1696 NodeReleaser::releaseAllNodes(this);
1697}
1698
1699void IfElseNode::releaseNodes(NodeReleaser& releaser)
1700{
1701 releaser.release(m_elseBlock);
1702 IfNode::releaseNodes(releaser);
1703}
1704
1705RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1706{
1707 RefPtr<LabelID> beforeElse = generator.newLabel();
1708 RefPtr<LabelID> afterElse = generator.newLabel();
1709
1710 RegisterID* cond = generator.emitNode(m_condition.get());
1711 generator.emitJumpIfFalse(cond, beforeElse.get());
1712
1713 if (!m_ifBlock->isBlock())
1714 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1715
1716 generator.emitNode(dst, m_ifBlock.get());
1717 generator.emitJump(afterElse.get());
1718
1719 generator.emitLabel(beforeElse.get());
1720
1721 if (!m_elseBlock->isBlock())
1722 generator.emitDebugHook(WillExecuteStatement, m_elseBlock->firstLine(), m_elseBlock->lastLine());
1723
1724 generator.emitNode(dst, m_elseBlock.get());
1725
1726 generator.emitLabel(afterElse.get());
1727
1728 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1729 return 0;
1730}
1731
1732// ------------------------------ DoWhileNode ----------------------------------
1733
1734DoWhileNode::~DoWhileNode()
1735{
1736 NodeReleaser::releaseAllNodes(this);
1737}
1738
1739void DoWhileNode::releaseNodes(NodeReleaser& releaser)
1740{
1741 releaser.release(m_statement);
1742 releaser.release(m_expr);
1743}
1744
1745RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1746{
1747 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1748
1749 RefPtr<LabelID> topOfLoop = generator.newLabel();
1750 generator.emitLabel(topOfLoop.get());
1751
1752 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1753
1754 if (!m_statement->isBlock())
1755 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1756
1757 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1758
1759 generator.emitLabel(scope->continueTarget());
1760 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1761 RegisterID* cond = generator.emitNode(m_expr.get());
1762 generator.emitJumpIfTrue(cond, topOfLoop.get());
1763
1764 generator.emitLabel(scope->breakTarget());
1765 return result.get();
1766}
1767
1768// ------------------------------ WhileNode ------------------------------------
1769
1770WhileNode::~WhileNode()
1771{
1772 NodeReleaser::releaseAllNodes(this);
1773}
1774
1775void WhileNode::releaseNodes(NodeReleaser& releaser)
1776{
1777 releaser.release(m_expr);
1778 releaser.release(m_statement);
1779}
1780
1781RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1782{
1783 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1784
1785 generator.emitJump(scope->continueTarget());
1786
1787 RefPtr<LabelID> topOfLoop = generator.newLabel();
1788 generator.emitLabel(topOfLoop.get());
1789
1790 if (!m_statement->isBlock())
1791 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1792
1793 generator.emitNode(dst, m_statement.get());
1794
1795 generator.emitLabel(scope->continueTarget());
1796 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1797 RegisterID* cond = generator.emitNode(m_expr.get());
1798 generator.emitJumpIfTrue(cond, topOfLoop.get());
1799
1800 generator.emitLabel(scope->breakTarget());
1801
1802 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1803 return 0;
1804}
1805
1806// ------------------------------ ForNode --------------------------------------
1807
1808ForNode::~ForNode()
1809{
1810 NodeReleaser::releaseAllNodes(this);
1811}
1812
1813void ForNode::releaseNodes(NodeReleaser& releaser)
1814{
1815 releaser.release(m_expr1);
1816 releaser.release(m_expr2);
1817 releaser.release(m_expr3);
1818 releaser.release(m_statement);
1819}
1820
1821RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1822{
1823 if (dst == ignoredResult())
1824 dst = 0;
1825
1826 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1827
1828 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1829
1830 if (m_expr1)
1831 generator.emitNode(ignoredResult(), m_expr1.get());
1832
1833 RefPtr<LabelID> condition = generator.newLabel();
1834 generator.emitJump(condition.get());
1835
1836 RefPtr<LabelID> topOfLoop = generator.newLabel();
1837 generator.emitLabel(topOfLoop.get());
1838
1839 if (!m_statement->isBlock())
1840 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1841 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1842
1843 generator.emitLabel(scope->continueTarget());
1844 if (m_expr3)
1845 generator.emitNode(ignoredResult(), m_expr3.get());
1846
1847 generator.emitLabel(condition.get());
1848 if (m_expr2) {
1849 RegisterID* cond = generator.emitNode(m_expr2.get());
1850 generator.emitJumpIfTrue(cond, topOfLoop.get());
1851 } else
1852 generator.emitJump(topOfLoop.get());
1853
1854 generator.emitLabel(scope->breakTarget());
1855 return result.get();
1856}
1857
1858// ------------------------------ ForInNode ------------------------------------
1859
1860ForInNode::~ForInNode()
1861{
1862 NodeReleaser::releaseAllNodes(this);
1863}
1864
1865void ForInNode::releaseNodes(NodeReleaser& releaser)
1866{
1867 releaser.release(m_init);
1868 releaser.release(m_lexpr);
1869 releaser.release(m_expr);
1870 releaser.release(m_statement);
1871}
1872
1873ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
1874 : StatementNode(globalData)
1875 , m_init(0L)
1876 , m_lexpr(l)
1877 , m_expr(expr)
1878 , m_statement(statement)
1879 , m_identIsVarDecl(false)
1880{
1881}
1882
1883ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
1884 : StatementNode(globalData)
1885 , m_ident(ident)
1886 , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset))
1887 , m_expr(expr)
1888 , m_statement(statement)
1889 , m_identIsVarDecl(true)
1890{
1891 if (in) {
1892 AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true);
1893 node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot);
1894 m_init = node;
1895 }
1896 // for( var foo = bar in baz )
1897}
1898
1899RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1900{
1901 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1902
1903 if (!m_lexpr->isLocation())
1904 return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
1905
1906 RefPtr<LabelID> continueTarget = generator.newLabel();
1907
1908 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1909
1910 if (m_init)
1911 generator.emitNode(ignoredResult(), m_init.get());
1912 RegisterID* forInBase = generator.emitNode(m_expr.get());
1913 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
1914 generator.emitJump(scope->continueTarget());
1915
1916 RefPtr<LabelID> loopStart = generator.newLabel();
1917 generator.emitLabel(loopStart.get());
1918
1919 RegisterID* propertyName;
1920 if (m_lexpr->isResolveNode()) {
1921 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
1922 propertyName = generator.registerFor(ident);
1923 if (!propertyName) {
1924 propertyName = generator.newTemporary();
1925 RefPtr<RegisterID> protect = propertyName;
1926 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
1927
1928 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1929 generator.emitPutById(base, ident, propertyName);
1930 }
1931 } else if (m_lexpr->isDotAccessorNode()) {
1932 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
1933 const Identifier& ident = assignNode->identifier();
1934 propertyName = generator.newTemporary();
1935 RefPtr<RegisterID> protect = propertyName;
1936 RegisterID* base = generator.emitNode(assignNode->base());
1937
1938 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1939 generator.emitPutById(base, ident, propertyName);
1940 } else {
1941 ASSERT(m_lexpr->isBracketAccessorNode());
1942 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
1943 propertyName = generator.newTemporary();
1944 RefPtr<RegisterID> protect = propertyName;
1945 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1946 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1947
1948 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1949 generator.emitPutByVal(base.get(), subscript, propertyName);
1950 }
1951
1952 if (!m_statement->isBlock())
1953 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1954 generator.emitNode(dst, m_statement.get());
1955
1956 generator.emitLabel(scope->continueTarget());
1957 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
1958 generator.emitLabel(scope->breakTarget());
1959 return dst;
1960}
1961
1962// ------------------------------ ContinueNode ---------------------------------
1963
1964// ECMA 12.7
1965RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1966{
1967 LabelScope* scope = generator.continueTarget(m_ident);
1968
1969 if (!scope)
1970 return m_ident.isEmpty()
1971 ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
1972 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1973
1974 generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
1975 return dst;
1976}
1977
1978// ------------------------------ BreakNode ------------------------------------
1979
1980// ECMA 12.8
1981RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1982{
1983 LabelScope* scope = generator.breakTarget(m_ident);
1984
1985 if (!scope)
1986 return m_ident.isEmpty()
1987 ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
1988 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1989
1990 generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
1991 return dst;
1992}
1993
1994// ------------------------------ ReturnNode -----------------------------------
1995
1996ReturnNode::~ReturnNode()
1997{
1998 NodeReleaser::releaseAllNodes(this);
1999}
2000
2001void ReturnNode::releaseNodes(NodeReleaser& releaser)
2002{
2003 releaser.release(m_value);
2004}
2005
2006RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2007{
2008 if (generator.codeType() != FunctionCode)
2009 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
2010
2011 if (dst == ignoredResult())
2012 dst = 0;
2013 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined());
2014 if (generator.scopeDepth()) {
2015 RefPtr<LabelID> l0 = generator.newLabel();
2016 generator.emitJumpScopes(l0.get(), 0);
2017 generator.emitLabel(l0.get());
2018 }
2019 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2020 return generator.emitReturn(r0);
2021}
2022
2023// ------------------------------ WithNode -------------------------------------
2024
2025WithNode::~WithNode()
2026{
2027 NodeReleaser::releaseAllNodes(this);
2028}
2029
2030void WithNode::releaseNodes(NodeReleaser& releaser)
2031{
2032 releaser.release(m_expr);
2033 releaser.release(m_statement);
2034}
2035
2036RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2037{
2038 RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
2039 generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
2040 generator.emitPushScope(scope.get());
2041 RegisterID* result = generator.emitNode(dst, m_statement.get());
2042 generator.emitPopScope();
2043 return result;
2044}
2045
2046// ------------------------------ CaseClauseNode --------------------------------
2047
2048CaseClauseNode::~CaseClauseNode()
2049{
2050 NodeReleaser::releaseAllNodes(this);
2051}
2052
2053void CaseClauseNode::releaseNodes(NodeReleaser& releaser)
2054{
2055 releaser.release(m_expr);
2056}
2057
2058// ------------------------------ ClauseListNode --------------------------------
2059
2060ClauseListNode::~ClauseListNode()
2061{
2062 NodeReleaser::releaseAllNodes(this);
2063}
2064
2065void ClauseListNode::releaseNodes(NodeReleaser& releaser)
2066{
2067 releaser.release(m_clause);
2068 releaser.release(m_next);
2069}
2070
2071// ------------------------------ CaseBlockNode --------------------------------
2072
2073CaseBlockNode::~CaseBlockNode()
2074{
2075 NodeReleaser::releaseAllNodes(this);
2076}
2077
2078void CaseBlockNode::releaseNodes(NodeReleaser& releaser)
2079{
2080 releaser.release(m_list1);
2081 releaser.release(m_defaultClause);
2082 releaser.release(m_list2);
2083}
2084
2085enum SwitchKind {
2086 SwitchUnset = 0,
2087 SwitchNumber = 1,
2088 SwitchString = 2,
2089 SwitchNeither = 3
2090};
2091
2092static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2093{
2094 for (; list; list = list->getNext()) {
2095 ExpressionNode* clauseExpression = list->getClause()->expr();
2096 literalVector.append(clauseExpression);
2097 if (clauseExpression->isNumber()) {
2098 double value = static_cast<NumberNode*>(clauseExpression)->value();
2099 if ((typeForTable & ~SwitchNumber) || !JSImmediate::from(value)) {
2100 typeForTable = SwitchNeither;
2101 break;
2102 }
2103 int32_t intVal = static_cast<int32_t>(value);
2104 ASSERT(intVal == value);
2105 if (intVal < min_num)
2106 min_num = intVal;
2107 if (intVal > max_num)
2108 max_num = intVal;
2109 typeForTable = SwitchNumber;
2110 continue;
2111 }
2112 if (clauseExpression->isString()) {
2113 if (typeForTable & ~SwitchString) {
2114 typeForTable = SwitchNeither;
2115 break;
2116 }
2117 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
2118 if (singleCharacterSwitch &= value.size() == 1) {
2119 int32_t intVal = value.rep()->data()[0];
2120 if (intVal < min_num)
2121 min_num = intVal;
2122 if (intVal > max_num)
2123 max_num = intVal;
2124 }
2125 typeForTable = SwitchString;
2126 continue;
2127 }
2128 typeForTable = SwitchNeither;
2129 break;
2130 }
2131}
2132
2133SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2134{
2135 SwitchKind typeForTable = SwitchUnset;
2136 bool singleCharacterSwitch = true;
2137
2138 processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2139 processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2140
2141 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2142 return SwitchInfo::SwitchNone;
2143
2144 if (typeForTable == SwitchNumber) {
2145 int32_t range = max_num - min_num;
2146 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2147 return SwitchInfo::SwitchImmediate;
2148 return SwitchInfo::SwitchNone;
2149 }
2150
2151 ASSERT(typeForTable == SwitchString);
2152
2153 if (singleCharacterSwitch) {
2154 int32_t range = max_num - min_num;
2155 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2156 return SwitchInfo::SwitchCharacter;
2157 }
2158
2159 return SwitchInfo::SwitchString;
2160}
2161
2162RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
2163{
2164 RefPtr<LabelID> defaultLabel;
2165 Vector<RefPtr<LabelID>, 8> labelVector;
2166 Vector<ExpressionNode*, 8> literalVector;
2167 int32_t min_num = std::numeric_limits<int32_t>::max();
2168 int32_t max_num = std::numeric_limits<int32_t>::min();
2169 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
2170
2171 if (switchType != SwitchInfo::SwitchNone) {
2172 // Prepare the various labels
2173 for (uint32_t i = 0; i < literalVector.size(); i++)
2174 labelVector.append(generator.newLabel());
2175 defaultLabel = generator.newLabel();
2176 generator.beginSwitch(switchExpression, switchType);
2177 } else {
2178 // Setup jumps
2179 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
2180 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2181 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2182 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2183 labelVector.append(generator.newLabel());
2184 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2185 }
2186
2187 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
2188 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2189 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2190 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2191 labelVector.append(generator.newLabel());
2192 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2193 }
2194 defaultLabel = generator.newLabel();
2195 generator.emitJump(defaultLabel.get());
2196 }
2197
2198 RegisterID* result = 0;
2199
2200 size_t i = 0;
2201 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
2202 generator.emitLabel(labelVector[i++].get());
2203 result = statementListEmitCode(list->getClause()->children(), generator, dst);
2204 }
2205
2206 if (m_defaultClause) {
2207 generator.emitLabel(defaultLabel.get());
2208 result = statementListEmitCode(m_defaultClause->children(), generator, dst);
2209 }
2210
2211 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
2212 generator.emitLabel(labelVector[i++].get());
2213 result = statementListEmitCode(list->getClause()->children(), generator, dst);
2214 }
2215 if (!m_defaultClause)
2216 generator.emitLabel(defaultLabel.get());
2217
2218 ASSERT(i == labelVector.size());
2219 if (switchType != SwitchInfo::SwitchNone) {
2220 ASSERT(labelVector.size() == literalVector.size());
2221 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2222 }
2223 return result;
2224}
2225
2226// ------------------------------ SwitchNode -----------------------------------
2227
2228SwitchNode::~SwitchNode()
2229{
2230 NodeReleaser::releaseAllNodes(this);
2231}
2232
2233void SwitchNode::releaseNodes(NodeReleaser& releaser)
2234{
2235 releaser.release(m_expr);
2236 releaser.release(m_block);
2237}
2238
2239RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2240{
2241 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
2242
2243 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
2244 RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
2245
2246 generator.emitLabel(scope->breakTarget());
2247 return r1;
2248}
2249
2250// ------------------------------ LabelNode ------------------------------------
2251
2252LabelNode::~LabelNode()
2253{
2254 NodeReleaser::releaseAllNodes(this);
2255}
2256
2257void LabelNode::releaseNodes(NodeReleaser& releaser)
2258{
2259 releaser.release(m_statement);
2260}
2261
2262RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2263{
2264 if (generator.breakTarget(m_name))
2265 return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
2266
2267 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
2268 RegisterID* r0 = generator.emitNode(dst, m_statement.get());
2269
2270 generator.emitLabel(scope->breakTarget());
2271 return r0;
2272}
2273
2274// ------------------------------ ThrowNode ------------------------------------
2275
2276ThrowNode::~ThrowNode()
2277{
2278 NodeReleaser::releaseAllNodes(this);
2279}
2280
2281void ThrowNode::releaseNodes(NodeReleaser& releaser)
2282{
2283 releaser.release(m_expr);
2284}
2285
2286RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2287{
2288 if (dst == ignoredResult())
2289 dst = 0;
2290 RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get());
2291 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
2292 generator.emitThrow(expr.get());
2293 return dst;
2294}
2295
2296// ------------------------------ TryNode --------------------------------------
2297
2298TryNode::~TryNode()
2299{
2300 NodeReleaser::releaseAllNodes(this);
2301}
2302
2303void TryNode::releaseNodes(NodeReleaser& releaser)
2304{
2305 releaser.release(m_tryBlock);
2306 releaser.release(m_catchBlock);
2307 releaser.release(m_finallyBlock);
2308}
2309
2310RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2311{
2312 RefPtr<LabelID> tryStartLabel = generator.newLabel();
2313 RefPtr<LabelID> tryEndLabel = generator.newLabel();
2314 RefPtr<LabelID> finallyStart;
2315 RefPtr<RegisterID> finallyReturnAddr;
2316 if (m_finallyBlock) {
2317 finallyStart = generator.newLabel();
2318 finallyReturnAddr = generator.newTemporary();
2319 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
2320 }
2321 generator.emitLabel(tryStartLabel.get());
2322 generator.emitNode(dst, m_tryBlock.get());
2323 generator.emitLabel(tryEndLabel.get());
2324
2325 if (m_catchBlock) {
2326 RefPtr<LabelID> handlerEndLabel = generator.newLabel();
2327 generator.emitJump(handlerEndLabel.get());
2328 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
2329 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
2330 generator.emitNode(dst, m_catchBlock.get());
2331 generator.emitPopScope();
2332 generator.emitLabel(handlerEndLabel.get());
2333 }
2334
2335 if (m_finallyBlock) {
2336 generator.popFinallyContext();
2337 // there may be important registers live at the time we jump
2338 // to a finally block (such as for a return or throw) so we
2339 // ref the highest register ever used as a conservative
2340 // approach to not clobbering anything important
2341 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
2342 RefPtr<LabelID> finallyEndLabel = generator.newLabel();
2343 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
2344 // Use a label to record the subtle fact that sret will return to the
2345 // next instruction. sret is the only way to jump without an explicit label.
2346 generator.emitLabel(generator.newLabel().get());
2347 generator.emitJump(finallyEndLabel.get());
2348
2349 // Finally block for exception path
2350 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
2351 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
2352 // Use a label to record the subtle fact that sret will return to the
2353 // next instruction. sret is the only way to jump without an explicit label.
2354 generator.emitLabel(generator.newLabel().get());
2355 generator.emitThrow(tempExceptionRegister.get());
2356
2357 // emit the finally block itself
2358 generator.emitLabel(finallyStart.get());
2359 generator.emitNode(dst, m_finallyBlock.get());
2360 generator.emitSubroutineReturn(finallyReturnAddr.get());
2361
2362 generator.emitLabel(finallyEndLabel.get());
2363 }
2364
2365 return dst;
2366}
2367
2368// ------------------------------ ParameterNode -----------------------------
2369
2370ParameterNode::~ParameterNode()
2371{
2372 NodeReleaser::releaseAllNodes(this);
2373}
2374
2375void ParameterNode::releaseNodes(NodeReleaser& releaser)
2376{
2377 releaser.release(m_next);
2378}
2379
2380// ------------------------------ ScopeNode -----------------------------
2381
2382ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
2383 : BlockNode(globalData, children)
2384 , m_source(source)
2385 , m_features(features)
2386 , m_numConstants(numConstants)
2387{
2388 if (varStack)
2389 m_varStack = *varStack;
2390 if (funcStack)
2391 m_functionStack = *funcStack;
2392#if ENABLE(OPCODE_SAMPLING)
2393 globalData->machine->sampler()->notifyOfScope(this);
2394#endif
2395}
2396
2397// ------------------------------ ProgramNode -----------------------------
2398
2399ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2400 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
2401{
2402}
2403
2404ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2405{
2406 return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
2407}
2408
2409// ------------------------------ EvalNode -----------------------------
2410
2411EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2412 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
2413{
2414}
2415
2416RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
2417{
2418 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
2419
2420 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2421 generator.emitLoad(dstRegister.get(), jsUndefined());
2422 statementListEmitCode(children(), generator, dstRegister.get());
2423
2424 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
2425 generator.emitEnd(dstRegister.get());
2426 return 0;
2427}
2428
2429void EvalNode::generateCode(ScopeChainNode* scopeChainNode)
2430{
2431 ScopeChain scopeChain(scopeChainNode);
2432 JSGlobalObject* globalObject = scopeChain.globalObject();
2433
2434 m_code.set(new EvalCodeBlock(this, globalObject, source().provider()));
2435
2436 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable, m_code.get());
2437 generator.generate();
2438}
2439
2440EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2441{
2442 return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
2443}
2444
2445// ------------------------------ FunctionBodyNode -----------------------------
2446
2447FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2448 : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
2449 , m_parameters(0)
2450 , m_parameterCount(0)
2451 , m_refCount(0)
2452{
2453}
2454
2455FunctionBodyNode::~FunctionBodyNode()
2456{
2457 ASSERT(!m_refCount);
2458 fastFree(m_parameters);
2459}
2460
2461void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
2462{
2463 Vector<Identifier> parameters;
2464 for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
2465 parameters.append(parameter->ident());
2466 size_t count = parameters.size();
2467
2468 setSource(source);
2469 finishParsing(parameters.releaseBuffer(), count);
2470}
2471
2472void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
2473{
2474 ASSERT(!source().isNull());
2475 m_parameters = parameters;
2476 m_parameterCount = parameterCount;
2477}
2478
2479void FunctionBodyNode::mark()
2480{
2481 if (m_code)
2482 m_code->mark();
2483}
2484
2485FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
2486{
2487 return new FunctionBodyNode(globalData, children, varStack, funcStack, SourceCode(), features, numConstants);
2488}
2489
2490FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2491{
2492 return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
2493}
2494
2495void FunctionBodyNode::generateCode(ScopeChainNode* scopeChainNode)
2496{
2497 ScopeChain scopeChain(scopeChainNode);
2498 JSGlobalObject* globalObject = scopeChain.globalObject();
2499
2500 m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
2501
2502 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable, m_code.get());
2503 generator.generate();
2504}
2505
2506RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
2507{
2508 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
2509 statementListEmitCode(children(), generator, ignoredResult());
2510 if (!children().size() || !children().last()->isReturnNode()) {
2511 RegisterID* r0 = generator.emitLoad(0, jsUndefined());
2512 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2513 generator.emitReturn(r0);
2514 }
2515 return 0;
2516}
2517
2518RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
2519{
2520 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
2521
2522 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2523 generator.emitLoad(dstRegister.get(), jsUndefined());
2524 statementListEmitCode(children(), generator, dstRegister.get());
2525
2526 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
2527 generator.emitEnd(dstRegister.get());
2528 return 0;
2529}
2530
2531void ProgramNode::generateCode(ScopeChainNode* scopeChainNode)
2532{
2533 ScopeChain scopeChain(scopeChainNode);
2534 JSGlobalObject* globalObject = scopeChain.globalObject();
2535
2536 m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
2537
2538 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack);
2539 generator.generate();
2540}
2541
2542UString FunctionBodyNode::paramString() const
2543{
2544 UString s("");
2545 for (size_t pos = 0; pos < m_parameterCount; ++pos) {
2546 if (!s.isEmpty())
2547 s += ", ";
2548 s += parameters()[pos].ustring();
2549 }
2550
2551 return s;
2552}
2553
2554Identifier* FunctionBodyNode::copyParameters()
2555{
2556 Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
2557 VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
2558 return parameters;
2559}
2560
2561// ------------------------------ FuncDeclNode ---------------------------------
2562
2563FuncDeclNode::~FuncDeclNode()
2564{
2565 NodeReleaser::releaseAllNodes(this);
2566}
2567
2568void FuncDeclNode::releaseNodes(NodeReleaser& releaser)
2569{
2570 releaser.release(m_parameter);
2571 releaser.release(m_body);
2572}
2573
2574JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2575{
2576 return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2577}
2578
2579RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
2580{
2581 return dst;
2582}
2583
2584// ------------------------------ FuncExprNode ---------------------------------
2585
2586FuncExprNode::~FuncExprNode()
2587{
2588 NodeReleaser::releaseAllNodes(this);
2589}
2590
2591void FuncExprNode::releaseNodes(NodeReleaser& releaser)
2592{
2593 releaser.release(m_parameter);
2594 releaser.release(m_body);
2595}
2596
2597RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2598{
2599 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2600}
2601
2602JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2603{
2604 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2605
2606 /*
2607 The Identifier in a FunctionExpression can be referenced from inside
2608 the FunctionExpression's FunctionBody to allow the function to call
2609 itself recursively. However, unlike in a FunctionDeclaration, the
2610 Identifier in a FunctionExpression cannot be referenced from and
2611 does not affect the scope enclosing the FunctionExpression.
2612 */
2613
2614 if (!m_ident.isNull()) {
2615 JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
2616 func->scope().push(functionScopeObject);
2617 }
2618
2619 return func;
2620}
2621
2622} // namespace JSC
Note: See TracBrowser for help on using the repository browser.