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

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

More windows build fixes.

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