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

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

2009-05-02 Darin Adler <Darin Adler>

Reviewed by Maciej Stachowiak.

Bug 25519: streamline lexer by handling BOMs differently
https://bugs.webkit.org/show_bug.cgi?id=25519

Roughly 1% faster SunSpider.

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