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

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

2008-11-09 Darin Adler <Darin Adler>

Reviewed by Tim Hatcher.

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