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

Last change on this file since 43259 was 43259, checked in by Darin Adler, 16 years ago

2009-05-05 Darin Adler <Darin Adler>

Reviewed by Sam Weinig.

Bug 25569: make ParserRefCounted use conventional reference counting
https://bugs.webkit.org/show_bug.cgi?id=25569

SunSpider speedup of about 1.6%.

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