source: webkit/trunk/JavaScriptCore/kjs/nodes.cpp@ 34562

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

2008-06-15 Cameron Zwarich <[email protected]>

Reviewed by Maciej.

Bug 19484: More instructions needs to use temporary registers
<https://bugs.webkit.org/show_bug.cgi?id=19484>

Fix codegen for all binary operations so that temporaries are used if
necessary. This was done by making BinaryOpNode and ReverseBinaryOpNode
subclasses of ExpressionNode, and eliminating the custom emitCode()
methods for the individual node classes.

This only adds 3 new instructions to SunSpider code, and there is no
difference in SunSpider execution time.

JavaScriptCore:

  • VM/CodeGenerator.cpp: (KJS::CodeGenerator::emitBitNot): (KJS::CodeGenerator::emitBinaryOp):
  • VM/CodeGenerator.h:
  • kjs/grammar.y:
  • kjs/nodes.cpp: (KJS::PreIncResolveNode::emitCode): (KJS::PreDecResolveNode::emitCode): (KJS::BinaryOpNode::emitCode): (KJS::ReverseBinaryOpNode::emitCode): (KJS::emitReadModifyAssignment): (KJS::CaseBlockNode::emitCodeForBlock):
  • kjs/nodes.h: (KJS::BinaryOpNode::BinaryOpNode): (KJS::ReverseBinaryOpNode::ReverseBinaryOpNode): (KJS::MultNode::): (KJS::DivNode::): (KJS::DivNode::precedence): (KJS::ModNode::): (KJS::ModNode::precedence): (KJS::AddNode::): (KJS::AddNode::precedence): (KJS::SubNode::): (KJS::SubNode::precedence): (KJS::LeftShiftNode::): (KJS::LeftShiftNode::precedence): (KJS::RightShiftNode::): (KJS::RightShiftNode::precedence): (KJS::UnsignedRightShiftNode::): (KJS::UnsignedRightShiftNode::precedence): (KJS::LessNode::): (KJS::LessNode::precedence): (KJS::GreaterNode::): (KJS::GreaterNode::precedence): (KJS::LessEqNode::): (KJS::LessEqNode::precedence): (KJS::GreaterEqNode::): (KJS::GreaterEqNode::precedence): (KJS::InstanceOfNode::): (KJS::InstanceOfNode::precedence): (KJS::InNode::): (KJS::InNode::precedence): (KJS::EqualNode::): (KJS::EqualNode::precedence): (KJS::NotEqualNode::): (KJS::NotEqualNode::precedence): (KJS::StrictEqualNode::): (KJS::StrictEqualNode::precedence): (KJS::NotStrictEqualNode::): (KJS::NotStrictEqualNode::precedence): (KJS::BitAndNode::): (KJS::BitAndNode::precedence): (KJS::BitOrNode::): (KJS::BitOrNode::precedence): (KJS::BitXOrNode::): (KJS::BitXOrNode::precedence):
  • kjs/nodes2string.cpp: (KJS::LessNode::streamTo): (KJS::GreaterNode::streamTo): (KJS::LessEqNode::streamTo): (KJS::GreaterEqNode::streamTo): (KJS::InstanceOfNode::streamTo): (KJS::InNode::streamTo): (KJS::EqualNode::streamTo): (KJS::NotEqualNode::streamTo): (KJS::StrictEqualNode::streamTo): (KJS::NotStrictEqualNode::streamTo): (KJS::BitAndNode::streamTo): (KJS::BitXOrNode::streamTo): (KJS::BitOrNode::streamTo):

LayoutTests:

  • fast/js/codegen-temporaries-expected.txt:
  • fast/js/resources/codegen-temporaries.js:
  • Property svn:eol-style set to native
File size: 66.7 KB
Line 
1/*
2* Copyright (C) 1999-2002 Harri Porten ([email protected])
3* Copyright (C) 2001 Peter Kelly ([email protected])
4* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5* Copyright (C) 2007 Cameron Zwarich ([email protected])
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <[email protected]>
8*
9* This library is free software; you can redistribute it and/or
10* modify it under the terms of the GNU Library General Public
11* License as published by the Free Software Foundation; either
12* version 2 of the License, or (at your option) any later version.
13*
14* This library is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17* Library General Public License for more details.
18*
19* You should have received a copy of the GNU Library General Public License
20* along with this library; see the file COPYING.LIB. If not, write to
21* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22* Boston, MA 02110-1301, USA.
23*
24*/
25
26#include "config.h"
27#include "nodes.h"
28
29#include "CodeGenerator.h"
30#include "ExecState.h"
31#include "JSGlobalObject.h"
32#include "Parser.h"
33#include "PropertyNameArray.h"
34#include "array_object.h"
35#include "debugger.h"
36#include "function_object.h"
37#include "lexer.h"
38#include "operations.h"
39#include "regexp_object.h"
40#include <math.h>
41#include <wtf/Assertions.h>
42#include <wtf/HashCountedSet.h>
43#include <wtf/HashSet.h>
44#include <wtf/MathExtras.h>
45
46namespace KJS {
47
48#define KJS_CHECKEXCEPTION \
49if (UNLIKELY(exec->hadException())) \
50 return rethrowException(exec);
51
52#define KJS_CHECKEXCEPTIONVALUE \
53if (UNLIKELY(exec->hadException())) { \
54 handleException(exec); \
55 return jsUndefined(); \
56}
57
58#define KJS_CHECKEXCEPTIONNUMBER \
59if (UNLIKELY(exec->hadException())) { \
60 handleException(exec); \
61 return 0; \
62}
63
64#define KJS_CHECKEXCEPTIONBOOLEAN \
65if (UNLIKELY(exec->hadException())) { \
66 handleException(exec); \
67 return false; \
68}
69
70#define KJS_CHECKEXCEPTIONVOID \
71if (UNLIKELY(exec->hadException())) { \
72 handleException(exec); \
73 return; \
74}
75
76static inline bool isConstant(const LocalStorage& localStorage, size_t index)
77{
78 ASSERT(index < localStorage.size());
79 return localStorage[index].attributes & ReadOnly;
80}
81
82static inline UString::Rep* rep(const Identifier& ident)
83{
84 return ident.ustring().rep();
85}
86
87// ------------------------------ Node -----------------------------------------
88
89#ifndef NDEBUG
90#ifndef LOG_CHANNEL_PREFIX
91#define LOG_CHANNEL_PREFIX Log
92#endif
93static WTFLogChannel LogKJSNodeLeaks = { 0x00000000, "", WTFLogChannelOn };
94
95struct ParserRefCountedCounter {
96 static unsigned count;
97 ParserRefCountedCounter()
98 {
99 if (count)
100 LOG(KJSNodeLeaks, "LEAK: %u KJS::Node\n", count);
101 }
102};
103unsigned ParserRefCountedCounter::count = 0;
104static ParserRefCountedCounter parserRefCountedCounter;
105#endif
106
107static HashSet<ParserRefCounted*>* newTrackedObjects;
108static HashCountedSet<ParserRefCounted*>* trackedObjectExtraRefCounts;
109
110ParserRefCounted::ParserRefCounted()
111{
112#ifndef NDEBUG
113 ++ParserRefCountedCounter::count;
114#endif
115 if (!newTrackedObjects)
116 newTrackedObjects = new HashSet<ParserRefCounted*>;
117 newTrackedObjects->add(this);
118 ASSERT(newTrackedObjects->contains(this));
119}
120
121ParserRefCounted::~ParserRefCounted()
122{
123#ifndef NDEBUG
124 --ParserRefCountedCounter::count;
125#endif
126}
127
128void ParserRefCounted::ref()
129{
130 // bumping from 0 to 1 is just removing from the new nodes set
131 if (newTrackedObjects) {
132 HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->find(this);
133 if (it != newTrackedObjects->end()) {
134 newTrackedObjects->remove(it);
135 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
136 return;
137 }
138 }
139
140 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
141
142 if (!trackedObjectExtraRefCounts)
143 trackedObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
144 trackedObjectExtraRefCounts->add(this);
145}
146
147void ParserRefCounted::deref()
148{
149 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
150
151 if (!trackedObjectExtraRefCounts) {
152 delete this;
153 return;
154 }
155
156 HashCountedSet<ParserRefCounted*>::iterator it = trackedObjectExtraRefCounts->find(this);
157 if (it == trackedObjectExtraRefCounts->end())
158 delete this;
159 else
160 trackedObjectExtraRefCounts->remove(it);
161}
162
163bool ParserRefCounted::hasOneRef()
164{
165 if (newTrackedObjects && newTrackedObjects->contains(this)) {
166 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
167 return false;
168 }
169
170 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
171
172 if (!trackedObjectExtraRefCounts)
173 return true;
174
175 return !trackedObjectExtraRefCounts->contains(this);
176}
177
178void ParserRefCounted::deleteNewObjects()
179{
180 if (!newTrackedObjects)
181 return;
182
183#ifndef NDEBUG
184 HashSet<ParserRefCounted*>::iterator end = newTrackedObjects->end();
185 for (HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->begin(); it != end; ++it)
186 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(*it));
187#endif
188 deleteAllValues(*newTrackedObjects);
189 delete newTrackedObjects;
190 newTrackedObjects = 0;
191}
192
193Node::Node()
194 : m_expectedReturnType(ObjectType)
195{
196 m_line = JSGlobalData::threadInstance().lexer->lineNo();
197}
198
199Node::Node(JSType expectedReturn)
200 : m_expectedReturnType(expectedReturn)
201{
202 m_line = JSGlobalData::threadInstance().lexer->lineNo();
203}
204
205static void substitute(UString& string, const UString& substring) KJS_FAST_CALL;
206static void substitute(UString& string, const UString& substring)
207{
208 int position = string.find("%s");
209 ASSERT(position != -1);
210 UString newString = string.substr(0, position);
211 newString.append(substring);
212 newString.append(string.substr(position + 2));
213 string = newString;
214}
215
216static inline int currentSourceId(ExecState* exec) KJS_FAST_CALL;
217static inline int currentSourceId(ExecState*)
218{
219 ASSERT_NOT_REACHED();
220 return 0;
221}
222
223static inline const UString currentSourceURL(ExecState* exec) KJS_FAST_CALL;
224static inline const UString currentSourceURL(ExecState*)
225{
226 ASSERT_NOT_REACHED();
227 return UString();
228}
229
230RegisterID* Node::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg)
231{
232 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(msg));
233 generator.emitThrow(exception);
234 return exception;
235}
236
237RegisterID* Node::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
238{
239 UString message = msg;
240 substitute(message, label.ustring());
241 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(message));
242 generator.emitThrow(exception);
243 return exception;
244}
245
246// ------------------------------ StatementNode --------------------------------
247
248StatementNode::StatementNode()
249 : m_lastLine(-1)
250{
251 m_line = -1;
252}
253
254void StatementNode::setLoc(int firstLine, int lastLine)
255{
256 m_line = firstLine;
257 m_lastLine = lastLine;
258}
259
260// ------------------------------ SourceElements --------------------------------
261
262void SourceElements::append(PassRefPtr<StatementNode> statement)
263{
264 if (statement->isEmptyStatement())
265 return;
266
267 m_statements.append(statement);
268}
269
270// ------------------------------ BreakpointCheckStatement --------------------------------
271
272BreakpointCheckStatement::BreakpointCheckStatement(PassRefPtr<StatementNode> statement)
273 : m_statement(statement)
274{
275 ASSERT(m_statement);
276}
277
278void BreakpointCheckStatement::streamTo(SourceStream& stream) const
279{
280 m_statement->streamTo(stream);
281}
282
283// ------------------------------ NullNode -------------------------------------
284
285RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst)
286{
287 return generator.emitLoad(generator.finalDestination(dst), jsNull());
288}
289
290// ------------------------------ BooleanNode ----------------------------------
291
292RegisterID* BooleanNode::emitCode(CodeGenerator& generator, RegisterID* dst)
293{
294 return generator.emitLoad(generator.finalDestination(dst), m_value);
295}
296
297// ------------------------------ NumberNode -----------------------------------
298
299RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst)
300{
301 return generator.emitLoad(generator.finalDestination(dst), m_double);
302}
303
304// ------------------------------ StringNode -----------------------------------
305
306RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
307{
308 // FIXME: should we try to atomize constant strings?
309 return generator.emitLoad(generator.finalDestination(dst), jsOwnedString(m_value));
310}
311
312// ------------------------------ RegExpNode -----------------------------------
313
314RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
315{
316 if (!m_regExp->isValid())
317 return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", m_regExp->errorMessage());
318 return generator.emitNewRegExp(generator.finalDestination(dst), m_regExp.get());
319}
320
321// ------------------------------ ThisNode -------------------------------------
322
323RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
324{
325 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
326}
327
328// ------------------------------ ResolveNode ----------------------------------
329
330bool ResolveNode::isPure(CodeGenerator& generator) const
331{
332 return generator.isLocal(m_ident);
333}
334
335RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
336{
337 if (RegisterID* local = generator.registerForLocal(m_ident))
338 return generator.moveToDestinationIfNeeded(dst, local);
339
340 return generator.emitResolve(generator.finalDestination(dst), m_ident);
341}
342
343// ------------------------------ ArrayNode ------------------------------------
344
345
346RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst)
347{
348 RefPtr<RegisterID> newArray = generator.emitNewArray(generator.tempDestination(dst));
349 unsigned length = 0;
350
351 RegisterID* value;
352 for (ElementNode* n = m_element.get(); n; n = n->m_next.get()) {
353 value = generator.emitNode(n->m_node.get());
354 length += n->m_elision;
355 generator.emitPutByIndex(newArray.get(), length++, value);
356 }
357
358 value = generator.emitLoad(generator.newTemporary(), jsNumber(m_elision + length));
359 generator.emitPutById(newArray.get(), generator.propertyNames().length, value);
360
361 return generator.moveToDestinationIfNeeded(dst, newArray.get());
362}
363
364// ------------------------------ ObjectLiteralNode ----------------------------
365
366RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst)
367{
368 if (m_list)
369 return generator.emitNode(dst, m_list.get());
370 else
371 return generator.emitNewObject(generator.finalDestination(dst));
372}
373
374// ------------------------------ PropertyListNode -----------------------------
375
376RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
377{
378 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
379
380 generator.emitNewObject(newObj.get());
381
382 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
383 RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
384
385 switch (p->m_node->m_type) {
386 case PropertyNode::Constant: {
387 generator.emitPutById(newObj.get(), p->m_node->name(), value);
388 break;
389 }
390 case PropertyNode::Getter: {
391 generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
392 break;
393 }
394 case PropertyNode::Setter: {
395 generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
396 break;
397 }
398 default:
399 ASSERT_NOT_REACHED();
400 }
401 }
402
403 return generator.moveToDestinationIfNeeded(dst, newObj.get());
404}
405
406// ------------------------------ BracketAccessorNode --------------------------------
407
408RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
409{
410 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator));
411 RegisterID* property = generator.emitNode(m_subscript.get());
412
413 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
414}
415
416// ------------------------------ DotAccessorNode --------------------------------
417
418RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
419{
420 RegisterID* base = generator.emitNode(m_base.get());
421 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
422}
423
424// ------------------------------ ArgumentListNode -----------------------------
425
426RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
427{
428 ASSERT(m_expr);
429 return generator.emitNode(dst, m_expr.get());
430}
431
432// ------------------------------ NewExprNode ----------------------------------
433
434RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
435{
436 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
437 return generator.emitConstruct(generator.finalDestination(dst), r0.get(), m_args.get());
438}
439
440RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
441{
442 RefPtr<RegisterID> base = generator.tempDestination(dst);
443 RegisterID* func = generator.newTemporary();
444 generator.emitResolveWithBase(base.get(), func, generator.propertyNames().eval);
445 return generator.emitCallEval(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get());
446}
447
448RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
449{
450 RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
451 return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get());
452}
453
454RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
455{
456 if (RegisterID* local = generator.registerForLocal(m_ident))
457 return generator.emitCall(generator.finalDestination(dst), local, 0, m_args.get());
458
459 int index = 0;
460 size_t depth = 0;
461 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
462 RegisterID* func = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
463 return generator.emitCall(generator.finalDestination(dst), func, 0, m_args.get());
464 }
465
466 RefPtr<RegisterID> base = generator.tempDestination(dst);
467 RegisterID* func = generator.newTemporary();
468 generator.emitResolveFunction(base.get(), func, m_ident);
469 return generator.emitCall(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get());
470}
471
472RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
473{
474 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
475 RegisterID* property = generator.emitNode(m_subscript.get());
476 RegisterID* function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
477 return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get());
478}
479
480RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
481{
482 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
483 RegisterID* function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
484 return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get());
485}
486
487// ------------------------------ PostfixResolveNode ----------------------------------
488
489RegisterID* PostIncResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
490{
491 // FIXME: I think we can detect the absense of dependent expressions here,
492 // and emit a PreInc instead of a PostInc. A post-pass to eliminate dead
493 // code would work, too.
494 if (RegisterID* local = generator.registerForLocal(m_ident)) {
495 if (generator.isLocalConstant(m_ident))
496 return generator.emitToJSNumber(generator.finalDestination(dst), local);
497
498 return generator.emitPostInc(generator.finalDestination(dst), local);
499 }
500
501 int index = 0;
502 size_t depth = 0;
503 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
504 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
505 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
506 generator.emitPutScopedVar(depth, index, value.get());
507 return oldValue;
508 }
509
510 RefPtr<RegisterID> value = generator.newTemporary();
511 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
512 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
513 generator.emitPutById(base.get(), m_ident, value.get());
514 return oldValue;
515}
516
517RegisterID* PostDecResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
518{
519 // FIXME: I think we can detect the absense of dependent expressions here,
520 // and emit a PreDec instead of a PostDec. A post-pass to eliminate dead
521 // code would work, too.
522 if (RegisterID* local = generator.registerForLocal(m_ident)) {
523 if (generator.isLocalConstant(m_ident))
524 return generator.emitToJSNumber(generator.finalDestination(dst), local);
525
526 return generator.emitPostDec(generator.finalDestination(dst), local);
527 }
528
529 int index = 0;
530 size_t depth = 0;
531 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
532 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
533 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
534 generator.emitPutScopedVar(depth, index, value.get());
535 return oldValue;
536 }
537
538 RefPtr<RegisterID> value = generator.newTemporary();
539 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
540 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
541 generator.emitPutById(base.get(), m_ident, value.get());
542 return oldValue;
543}
544
545// ------------------------------ PostfixBracketNode ----------------------------------
546
547RegisterID* PostIncBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
548{
549 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
550 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
551 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
552 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
553 generator.emitPutByVal(base.get(), property.get(), value.get());
554 return oldValue;
555}
556
557RegisterID* PostDecBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
558{
559 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
560 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
561 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
562 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
563 generator.emitPutByVal(base.get(), property.get(), value.get());
564 return oldValue;
565}
566
567// ------------------------------ PostfixDotNode ----------------------------------
568
569RegisterID* PostIncDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
570{
571 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
572 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
573 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
574 generator.emitPutById(base.get(), m_ident, value.get());
575 return oldValue;
576}
577
578RegisterID* PostDecDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
579{
580 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
581 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
582 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
583 generator.emitPutById(base.get(), m_ident, value.get());
584 return oldValue;
585}
586
587// ------------------------------ PostfixErrorNode -----------------------------------
588
589RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
590{
591 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.");
592}
593
594// ------------------------------ DeleteResolveNode -----------------------------------
595
596RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
597{
598 if (generator.registerForLocal(m_ident))
599 return generator.emitLoad(generator.finalDestination(dst), false);
600
601 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
602 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
603}
604
605// ------------------------------ DeleteBracketNode -----------------------------------
606
607RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
608{
609 RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
610 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript.get());
611 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
612}
613
614// ------------------------------ DeleteDotNode -----------------------------------
615
616RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
617{
618 RegisterID* r0 = generator.emitNode(m_base.get());
619 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
620}
621
622// ------------------------------ DeleteValueNode -----------------------------------
623
624RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
625{
626 generator.emitNode(m_expr.get());
627
628 // delete on a non-location expression ignores the value and returns true
629 return generator.emitLoad(generator.finalDestination(dst), true);
630}
631
632// ------------------------------ VoidNode -------------------------------------
633
634RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
635{
636 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
637 return generator.emitLoad(generator.finalDestination(dst, r0.get()), jsUndefined());
638}
639
640// ------------------------------ TypeOfValueNode -----------------------------------
641
642RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
643{
644 if (RegisterID* local = generator.registerForLocal(m_ident))
645 return generator.emitTypeOf(generator.finalDestination(dst), local);
646
647 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
648 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
649 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
650}
651
652// ------------------------------ TypeOfValueNode -----------------------------------
653
654RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
655{
656 RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
657 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
658}
659
660// ------------------------------ PrefixResolveNode ----------------------------------
661
662RegisterID* PreIncResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
663{
664 if (RegisterID* local = generator.registerForLocal(m_ident)) {
665 if (generator.isLocalConstant(m_ident)) {
666 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), 1.0);
667 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get());
668 }
669
670 generator.emitPreInc(local);
671 return generator.moveToDestinationIfNeeded(dst, local);
672 }
673
674 int index = 0;
675 size_t depth = 0;
676 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
677 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
678 generator.emitPreInc(propDst.get());
679 generator.emitPutScopedVar(depth, index, propDst.get());
680 return generator.moveToDestinationIfNeeded(dst, propDst.get());;
681 }
682
683 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
684 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
685 generator.emitPreInc(propDst.get());
686 generator.emitPutById(base.get(), m_ident, propDst.get());
687 return generator.moveToDestinationIfNeeded(dst, propDst.get());
688}
689
690RegisterID* PreDecResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
691{
692 if (RegisterID* local = generator.registerForLocal(m_ident)) {
693 if (generator.isLocalConstant(m_ident)) {
694 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), -1.0);
695 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get());
696 }
697
698 generator.emitPreDec(local);
699 return generator.moveToDestinationIfNeeded(dst, local);
700 }
701
702 int index = 0;
703 size_t depth = 0;
704 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
705 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
706 generator.emitPreDec(propDst.get());
707 generator.emitPutScopedVar(depth, index, propDst.get());
708 return generator.moveToDestinationIfNeeded(dst, propDst.get());;
709 }
710
711 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
712 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
713 generator.emitPreDec(propDst.get());
714 generator.emitPutById(base.get(), m_ident, propDst.get());
715 return generator.moveToDestinationIfNeeded(dst, propDst.get());
716}
717
718// ------------------------------ PrefixBracketNode ----------------------------------
719
720RegisterID* PreIncBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
721{
722 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
723 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
724 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
725 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
726 generator.emitPreInc(value);
727 generator.emitPutByVal(base.get(), property.get(), value);
728 return generator.moveToDestinationIfNeeded(dst, propDst.get());
729}
730
731RegisterID* PreDecBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
732{
733
734 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
735 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
736 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
737 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
738 generator.emitPreDec(value);
739 generator.emitPutByVal(base.get(), property.get(), value);
740 return generator.moveToDestinationIfNeeded(dst, propDst.get());
741}
742
743// ------------------------------ PrefixDotNode ----------------------------------
744
745RegisterID* PreIncDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
746{
747 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
748 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
749 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
750 generator.emitPreInc(value);
751 generator.emitPutById(base.get(), m_ident, value);
752 return generator.moveToDestinationIfNeeded(dst, propDst.get());
753}
754
755RegisterID* PreDecDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
756{
757 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
758 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
759 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
760 generator.emitPreDec(value);
761 generator.emitPutById(base.get(), m_ident, value);
762 return generator.moveToDestinationIfNeeded(dst, propDst.get());
763}
764
765// ------------------------------ PrefixErrorNode -----------------------------------
766
767RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
768{
769 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.");
770}
771
772// ------------------------------ UnaryPlusNode --------------------------------
773
774RegisterID* UnaryPlusNode::emitCode(CodeGenerator& generator, RegisterID* dst)
775{
776 RegisterID* src = generator.emitNode(m_expr.get());
777 return generator.emitToJSNumber(generator.finalDestination(dst), src);
778}
779
780// ------------------------------ NegateNode -----------------------------------
781
782RegisterID* NegateNode::emitCode(CodeGenerator& generator, RegisterID* dst)
783{
784 RegisterID* src = generator.emitNode(m_expr.get());
785 return generator.emitNegate(generator.finalDestination(dst), src);
786}
787
788// ------------------------------ BitwiseNotNode -------------------------------
789
790RegisterID* BitwiseNotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
791{
792 RegisterID* src = generator.emitNode(m_expr.get());
793 return generator.emitBitNot(generator.finalDestination(dst), src);
794}
795
796// ------------------------------ LogicalNotNode -------------------------------
797
798RegisterID* LogicalNotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
799{
800 RegisterID* src = generator.emitNode(m_expr.get());
801 return generator.emitNot(generator.finalDestination(dst), src);
802}
803
804// ------------------------------ Binary Operation Nodes -----------------------------------
805
806RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
807{
808 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2->isPure(generator));
809 RegisterID* src2 = generator.emitNode(m_term2.get());
810 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2);
811}
812
813RegisterID* ReverseBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
814{
815 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2->isPure(generator));
816 RegisterID* src2 = generator.emitNode(m_term2.get());
817 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get());
818}
819
820// ------------------------------ Binary Logical Nodes ----------------------------
821
822RegisterID* LogicalAndNode::emitCode(CodeGenerator& generator, RegisterID* dst)
823{
824 RefPtr<RegisterID> temp = generator.tempDestination(dst);
825 RefPtr<LabelID> target = generator.newLabel();
826
827 generator.emitNode(temp.get(), m_expr1.get());
828 generator.emitJumpIfFalse(temp.get(), target.get());
829 generator.emitNode(temp.get(), m_expr2.get());
830 generator.emitLabel(target.get());
831
832 return generator.moveToDestinationIfNeeded(dst, temp.get());
833}
834
835RegisterID* LogicalOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
836{
837 RefPtr<RegisterID> temp = generator.tempDestination(dst);
838 RefPtr<LabelID> target = generator.newLabel();
839
840 generator.emitNode(temp.get(), m_expr1.get());
841 generator.emitJumpIfTrue(temp.get(), target.get());
842 generator.emitNode(temp.get(), m_expr2.get());
843 generator.emitLabel(target.get());
844
845 return generator.moveToDestinationIfNeeded(dst, temp.get());
846}
847
848// ------------------------------ ConditionalNode ------------------------------
849
850RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
851{
852 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
853 RefPtr<LabelID> beforeElse = generator.newLabel();
854 RefPtr<LabelID> afterElse = generator.newLabel();
855
856 RegisterID* cond = generator.emitNode(m_logical.get());
857 generator.emitJumpIfFalse(cond, beforeElse.get());
858
859 generator.emitNode(newDst.get(), m_expr1.get());
860 generator.emitJump(afterElse.get());
861
862 generator.emitLabel(beforeElse.get());
863 generator.emitNode(newDst.get(), m_expr2.get());
864
865 generator.emitLabel(afterElse.get());
866
867 return newDst.get();
868}
869
870// ------------------------------ ReadModifyResolveNode -----------------------------------
871
872// FIXME: should this be moved to be a method on CodeGenerator?
873static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper)
874{
875 switch (oper) {
876 case OpMultEq:
877 return generator.emitBinaryOp(op_mul, dst, src1, src2);
878 case OpDivEq:
879 return generator.emitBinaryOp(op_div, dst, src1, src2);
880 case OpPlusEq:
881 return generator.emitBinaryOp(op_add, dst, src1, src2);
882 case OpMinusEq:
883 return generator.emitBinaryOp(op_sub, dst, src1, src2);
884 case OpLShift:
885 return generator.emitBinaryOp(op_lshift, dst, src1, src2);
886 case OpRShift:
887 return generator.emitBinaryOp(op_rshift, dst, src1, src2);
888 case OpURShift:
889 return generator.emitBinaryOp(op_urshift, dst, src1, src2);
890 case OpAndEq:
891 return generator.emitBinaryOp(op_bitand, dst, src1, src2);
892 case OpXOrEq:
893 return generator.emitBinaryOp(op_bitxor, dst, src1, src2);
894 case OpOrEq:
895 return generator.emitBinaryOp(op_bitor, dst, src1, src2);
896 case OpModEq:
897 return generator.emitBinaryOp(op_mod, dst, src1, src2);
898 default:
899 ASSERT_NOT_REACHED();
900 }
901
902 return dst;
903}
904
905RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
906{
907 if (RegisterID* local = generator.registerForLocal(m_ident)) {
908 if (generator.isLocalConstant(m_ident)) {
909 RegisterID* src2 = generator.emitNode(m_right.get());
910 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator);
911 }
912
913 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
914 RefPtr<RegisterID> result = generator.newTemporary();
915 generator.emitMove(result.get(), local);
916 RegisterID* src2 = generator.emitNode(m_right.get());
917 emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator);
918 generator.emitMove(local, result.get());
919 return generator.moveToDestinationIfNeeded(dst, result.get());
920 }
921
922 RegisterID* src2 = generator.emitNode(m_right.get());
923 RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator);
924 return generator.moveToDestinationIfNeeded(dst, result);
925 }
926
927 int index = 0;
928 size_t depth = 0;
929 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
930 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
931 RegisterID* src2 = generator.emitNode(m_right.get());
932 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
933 generator.emitPutScopedVar(depth, index, result);
934 return result;
935 }
936
937 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
938 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
939 RegisterID* src2 = generator.emitNode(m_right.get());
940 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
941 return generator.emitPutById(base.get(), m_ident, result);
942}
943
944// ------------------------------ AssignResolveNode -----------------------------------
945
946RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
947{
948 if (RegisterID* local = generator.registerForLocal(m_ident)) {
949 if (generator.isLocalConstant(m_ident))
950 return generator.emitNode(dst, m_right.get());
951
952 RegisterID* result = generator.emitNode(local, m_right.get());
953 return generator.moveToDestinationIfNeeded(dst, result);
954 }
955
956 int index = 0;
957 size_t depth = 0;
958 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
959 RegisterID* value = generator.emitNode(dst, m_right.get());
960 generator.emitPutScopedVar(depth, index, value);
961 return value;
962 }
963
964 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
965 RegisterID* value = generator.emitNode(dst, m_right.get());
966 return generator.emitPutById(base.get(), m_ident, value);
967}
968
969// ------------------------------ AssignDotNode -----------------------------------
970
971RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
972{
973 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
974 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
975 RegisterID* result = generator.emitNode(value.get(), m_right.get());
976 generator.emitPutById(base.get(), m_ident, result);
977 return generator.moveToDestinationIfNeeded(dst, result);
978}
979
980// ------------------------------ ReadModifyDotNode -----------------------------------
981
982RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
983{
984 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
985 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
986 RegisterID* change = generator.emitNode(m_right.get());
987 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
988 return generator.emitPutById(base.get(), m_ident, updatedValue);
989}
990
991// ------------------------------ AssignErrorNode -----------------------------------
992
993RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
994{
995 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
996}
997
998// ------------------------------ AssignBracketNode -----------------------------------
999
1000RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1001{
1002 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1003 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1004 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1005 RegisterID* result = generator.emitNode(value.get(), m_right.get());
1006 generator.emitPutByVal(base.get(), property.get(), result);
1007 return generator.moveToDestinationIfNeeded(dst, result);
1008}
1009
1010RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1011{
1012 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1013 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1014
1015 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1016 RegisterID* change = generator.emitNode(m_right.get());
1017 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
1018
1019 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1020
1021 return updatedValue;
1022}
1023
1024// ------------------------------ CommaNode ------------------------------------
1025
1026RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1027{
1028 generator.emitNode(m_expr1.get());
1029 return generator.emitNode(dst, m_expr2.get());
1030}
1031
1032// ------------------------------ ConstDeclNode ----------------------------------
1033
1034ConstDeclNode::ConstDeclNode(const Identifier& ident, ExpressionNode* init)
1035 : m_ident(ident)
1036 , m_init(init)
1037{
1038}
1039
1040RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
1041{
1042 if (RegisterID* local = generator.registerForLocalConstInit(m_ident)) {
1043 if (!m_init)
1044 return local;
1045
1046 return generator.emitNode(local, m_init.get());
1047 }
1048
1049 // FIXME: While this code should only be hit in eval code, it will potentially
1050 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1051 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1052 RegisterID* value = generator.emitNode(m_init.get());
1053 return generator.emitPutById(base.get(), m_ident, value);
1054}
1055
1056RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
1057{
1058 RegisterID* result = 0;
1059 for (ConstDeclNode* n = this; n; n = n->m_next.get())
1060 result = n->emitCodeSingle(generator);
1061
1062 return result;
1063}
1064
1065// ------------------------------ ConstStatementNode -----------------------------
1066
1067RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1068{
1069 return generator.emitNode(m_next.get());
1070}
1071
1072// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
1073
1074static inline RegisterID* statementListEmitCode(StatementVector& statements, CodeGenerator& generator, RegisterID* dst = 0)
1075{
1076 RefPtr<RegisterID> r0 = dst;
1077
1078 StatementVector::iterator end = statements.end();
1079 for (StatementVector::iterator it = statements.begin(); it != end; ++it) {
1080 StatementNode* n = it->get();
1081 generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
1082 if (RegisterID* r1 = generator.emitNode(dst, n))
1083 r0 = r1;
1084 }
1085
1086 return r0.get();
1087}
1088
1089static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
1090{
1091 StatementVector::iterator it = statements.end();
1092 StatementVector::iterator begin = statements.begin();
1093 while (it != begin) {
1094 --it;
1095 stack.append((*it).get());
1096 }
1097}
1098
1099static inline Node* statementListInitializeVariableAccessStack(StatementVector& statements, DeclarationStacks::NodeStack& stack)
1100{
1101 if (statements.isEmpty())
1102 return 0;
1103
1104 StatementVector::iterator it = statements.end();
1105 StatementVector::iterator begin = statements.begin();
1106 StatementVector::iterator beginPlusOne = begin + 1;
1107
1108 while (it != beginPlusOne) {
1109 --it;
1110 stack.append((*it).get());
1111 }
1112
1113 return (*begin).get();
1114}
1115
1116// ------------------------------ BlockNode ------------------------------------
1117
1118BlockNode::BlockNode(SourceElements* children)
1119{
1120 if (children)
1121 children->releaseContentsIntoVector(m_children);
1122}
1123
1124RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1125{
1126 return statementListEmitCode(m_children, generator, dst);
1127}
1128
1129// ------------------------------ EmptyStatementNode ---------------------------
1130
1131RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
1132{
1133 return dst;
1134}
1135
1136// ------------------------------ DebuggerStatementNode ---------------------------
1137
1138RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1139{
1140 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1141 return dst;
1142}
1143
1144// ------------------------------ ExprStatementNode ----------------------------
1145
1146RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1147{
1148 ASSERT(m_expr);
1149 return generator.emitNode(dst, m_expr.get());
1150}
1151
1152// ------------------------------ VarStatementNode ----------------------------
1153
1154RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1155{
1156 ASSERT(m_expr);
1157 return generator.emitNode(m_expr.get());
1158}
1159
1160// ------------------------------ IfNode ---------------------------------------
1161
1162RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1163{
1164 RefPtr<LabelID> afterThen = generator.newLabel();
1165
1166 RegisterID* cond = generator.emitNode(m_condition.get());
1167 generator.emitJumpIfFalse(cond, afterThen.get());
1168
1169 generator.emitNode(dst, m_ifBlock.get());
1170 generator.emitLabel(afterThen.get());
1171
1172 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
1173 return 0;
1174}
1175
1176RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1177{
1178 RefPtr<LabelID> beforeElse = generator.newLabel();
1179 RefPtr<LabelID> afterElse = generator.newLabel();
1180
1181 RegisterID* cond = generator.emitNode(m_condition.get());
1182 generator.emitJumpIfFalse(cond, beforeElse.get());
1183
1184 generator.emitNode(dst, m_ifBlock.get());
1185 generator.emitJump(afterElse.get());
1186
1187 generator.emitLabel(beforeElse.get());
1188 generator.emitNode(dst, m_elseBlock.get());
1189
1190 generator.emitLabel(afterElse.get());
1191
1192 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
1193 return 0;
1194}
1195
1196// ------------------------------ DoWhileNode ----------------------------------
1197
1198RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1199{
1200 RefPtr<LabelID> topOfLoop = generator.newLabel();
1201 generator.emitLabel(topOfLoop.get());
1202
1203 RefPtr<LabelID> continueTarget = generator.newLabel();
1204 RefPtr<LabelID> breakTarget = generator.newLabel();
1205
1206 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1207 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1208 generator.popJumpContext();
1209
1210 generator.emitLabel(continueTarget.get());
1211 RegisterID* cond = generator.emitNode(m_expr.get());
1212 generator.emitJumpIfTrueMayCombine(cond, topOfLoop.get());
1213 generator.emitLabel(breakTarget.get());
1214 return result.get();
1215}
1216
1217// ------------------------------ WhileNode ------------------------------------
1218
1219RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1220{
1221 RefPtr<LabelID> topOfLoop = generator.newLabel();
1222 RefPtr<LabelID> continueTarget = generator.newLabel();
1223 RefPtr<LabelID> breakTarget = generator.newLabel();
1224
1225 generator.emitJump(continueTarget.get());
1226 generator.emitLabel(topOfLoop.get());
1227
1228 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1229 generator.emitNode(dst, m_statement.get());
1230 generator.popJumpContext();
1231
1232 generator.emitLabel(continueTarget.get());
1233 RegisterID* cond = generator.emitNode(m_expr.get());
1234 generator.emitJumpIfTrueMayCombine(cond, topOfLoop.get());
1235
1236 generator.emitLabel(breakTarget.get());
1237
1238 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1239 return 0;
1240}
1241
1242// ------------------------------ ForNode --------------------------------------
1243
1244RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1245{
1246 if (m_expr1)
1247 generator.emitNode(m_expr1.get());
1248
1249 RefPtr<LabelID> topOfLoop = generator.newLabel();
1250 RefPtr<LabelID> beforeCondition = generator.newLabel();
1251 RefPtr<LabelID> continueTarget = generator.newLabel();
1252 RefPtr<LabelID> breakTarget = generator.newLabel();
1253 generator.emitJump(beforeCondition.get());
1254
1255 generator.emitLabel(topOfLoop.get());
1256 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1257 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1258 generator.popJumpContext();
1259 generator.emitLabel(continueTarget.get());
1260 if (m_expr3)
1261 generator.emitNode(m_expr3.get());
1262
1263 generator.emitLabel(beforeCondition.get());
1264 if (m_expr2) {
1265 RegisterID* cond = generator.emitNode(m_expr2.get());
1266 generator.emitJumpIfTrueMayCombine(cond, topOfLoop.get());
1267 } else {
1268 generator.emitJump(topOfLoop.get());
1269 }
1270 generator.emitLabel(breakTarget.get());
1271 return result.get();
1272}
1273
1274// ------------------------------ ForInNode ------------------------------------
1275
1276ForInNode::ForInNode(ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
1277 : m_init(0L)
1278 , m_lexpr(l)
1279 , m_expr(expr)
1280 , m_statement(statement)
1281 , m_identIsVarDecl(false)
1282{
1283}
1284
1285ForInNode::ForInNode(const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement)
1286 : m_ident(ident)
1287 , m_lexpr(new ResolveNode(ident))
1288 , m_expr(expr)
1289 , m_statement(statement)
1290 , m_identIsVarDecl(true)
1291{
1292 if (in)
1293 m_init = new AssignResolveNode(ident, in, true);
1294 // for( var foo = bar in baz )
1295}
1296
1297RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1298{
1299 RefPtr<LabelID> loopStart = generator.newLabel();
1300 RefPtr<LabelID> continueTarget = generator.newLabel();
1301 RefPtr<LabelID> breakTarget = generator.newLabel();
1302
1303 if (m_init)
1304 generator.emitNode(m_init.get());
1305 RegisterID* forInBase = generator.emitNode(m_expr.get());
1306 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
1307 generator.emitJump(continueTarget.get());
1308 generator.emitLabel(loopStart.get());
1309 RegisterID* propertyName;
1310 if (m_lexpr->isResolveNode()) {
1311 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
1312 propertyName = generator.registerForLocal(ident);
1313 if (!propertyName) {
1314 propertyName = generator.newTemporary();
1315 RefPtr<RegisterID> protect = propertyName;
1316 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
1317 generator.emitPutById(base, ident, propertyName);
1318 }
1319 } else if (m_lexpr->isDotAccessorNode()) {
1320 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
1321 const Identifier& ident = assignNode->identifier();
1322 propertyName = generator.newTemporary();
1323 RefPtr<RegisterID> protect = propertyName;
1324 RegisterID* base = generator.emitNode(assignNode->base());
1325 generator.emitPutById(base, ident, propertyName);
1326 } else {
1327 ASSERT(m_lexpr->isBracketAccessorNode());
1328 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
1329 propertyName = generator.newTemporary();
1330 RefPtr<RegisterID> protect = propertyName;
1331 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1332 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1333 generator.emitPutByVal(base.get(), subscript, propertyName);
1334 }
1335
1336 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1337 generator.emitNode(dst, m_statement.get());
1338 generator.popJumpContext();
1339
1340 generator.emitLabel(continueTarget.get());
1341 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
1342 generator.emitLabel(breakTarget.get());
1343 return dst;
1344}
1345
1346// ------------------------------ ContinueNode ---------------------------------
1347
1348// ECMA 12.7
1349RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1350{
1351 if (!generator.inContinueContext())
1352 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1353
1354 JumpContext* targetContext = generator.jumpContextForContinue(m_ident);
1355
1356 if (!targetContext) {
1357 if (m_ident.isEmpty())
1358 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1359 else
1360 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
1361 }
1362
1363 if (!targetContext->continueTarget)
1364 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1365
1366 generator.emitJumpScopes(targetContext->continueTarget, targetContext->scopeDepth);
1367
1368 return dst;
1369}
1370
1371// ------------------------------ BreakNode ------------------------------------
1372
1373// ECMA 12.8
1374RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1375{
1376 if (!generator.inJumpContext())
1377 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
1378
1379 JumpContext* targetContext = generator.jumpContextForBreak(m_ident);
1380
1381 if (!targetContext) {
1382 if (m_ident.isEmpty())
1383 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
1384 else
1385 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
1386 }
1387
1388 ASSERT(targetContext->breakTarget);
1389
1390 generator.emitJumpScopes(targetContext->breakTarget, targetContext->scopeDepth);
1391
1392 return dst;
1393}
1394
1395// ------------------------------ ReturnNode -----------------------------------
1396
1397RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1398{
1399 if (generator.codeType() != FunctionCode)
1400 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
1401
1402 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(generator.finalDestination(dst), jsUndefined());
1403 if (generator.scopeDepth()) {
1404 RefPtr<LabelID> l0 = generator.newLabel();
1405 generator.emitJumpScopes(l0.get(), 0);
1406 generator.emitLabel(l0.get());
1407 }
1408 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1409 return generator.emitReturn(r0);
1410}
1411
1412// ------------------------------ WithNode -------------------------------------
1413
1414RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1415{
1416 RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
1417 generator.emitPushScope(scope.get());
1418 RegisterID* result = generator.emitNode(dst, m_statement.get());
1419 generator.emitPopScope();
1420 return result;
1421}
1422
1423// ------------------------------ CaseBlockNode --------------------------------
1424
1425RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
1426{
1427 Vector<RefPtr<LabelID>, 8> labelVector;
1428
1429 // Setup jumps
1430 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
1431 RegisterID* clauseVal = generator.emitNode(list->getClause()->expr());
1432 generator.emitBinaryOp(op_stricteq, clauseVal, clauseVal, switchExpression);
1433 labelVector.append(generator.newLabel());
1434 generator.emitJumpIfTrueMayCombine(clauseVal, labelVector[labelVector.size() - 1].get());
1435 }
1436
1437 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
1438 RegisterID* clauseVal = generator.emitNode(list->getClause()->expr());
1439 generator.emitBinaryOp(op_stricteq, clauseVal, clauseVal, switchExpression);
1440 labelVector.append(generator.newLabel());
1441 generator.emitJumpIfTrueMayCombine(clauseVal, labelVector[labelVector.size() - 1].get());
1442 }
1443
1444 RefPtr<LabelID> defaultLabel;
1445 defaultLabel = generator.newLabel();
1446 generator.emitJump(defaultLabel.get());
1447
1448 RegisterID* result = 0;
1449
1450 size_t i = 0;
1451 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
1452 generator.emitLabel(labelVector[i++].get());
1453 result = statementListEmitCode(list->getClause()->children(), generator, dst);
1454 }
1455
1456 if (m_defaultClause) {
1457 generator.emitLabel(defaultLabel.get());
1458 result = statementListEmitCode(m_defaultClause->children(), generator, dst);
1459 }
1460
1461 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
1462 generator.emitLabel(labelVector[i++].get());
1463 result = statementListEmitCode(list->getClause()->children(), generator, dst);
1464 }
1465 if (!m_defaultClause)
1466 generator.emitLabel(defaultLabel.get());
1467
1468 ASSERT(i == labelVector.size());
1469
1470 return result;
1471}
1472
1473// ------------------------------ SwitchNode -----------------------------------
1474
1475RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1476{
1477 RefPtr<LabelID> breakTarget = generator.newLabel();
1478
1479 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
1480 generator.pushJumpContext(&m_labelStack, 0, breakTarget.get(), true);
1481 RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
1482 generator.popJumpContext();
1483
1484 generator.emitLabel(breakTarget.get());
1485
1486 return r1;
1487}
1488
1489// ------------------------------ LabelNode ------------------------------------
1490
1491RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1492{
1493 if (generator.jumpContextForBreak(m_label))
1494 return emitThrowError(generator, SyntaxError, "Duplicated label %s found.", m_label);
1495
1496 RefPtr<LabelID> l0 = generator.newLabel();
1497 m_labelStack.push(m_label);
1498 generator.pushJumpContext(&m_labelStack, 0, l0.get(), false);
1499
1500 RegisterID* r0 = generator.emitNode(dst, m_statement.get());
1501
1502 generator.popJumpContext();
1503 m_labelStack.pop();
1504
1505 generator.emitLabel(l0.get());
1506 return r0;
1507}
1508
1509// ------------------------------ ThrowNode ------------------------------------
1510
1511RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1512{
1513 generator.emitThrow(generator.emitNode(dst, m_expr.get()));
1514 return dst;
1515}
1516
1517// ------------------------------ TryNode --------------------------------------
1518
1519RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1520{
1521 RefPtr<LabelID> tryStartLabel = generator.newLabel();
1522 RefPtr<LabelID> tryEndLabel = generator.newLabel();
1523 RefPtr<LabelID> finallyStart;
1524 RefPtr<RegisterID> finallyReturnAddr;
1525 if (m_finallyBlock) {
1526 finallyStart = generator.newLabel();
1527 finallyReturnAddr = generator.newTemporary();
1528 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
1529 }
1530 generator.emitLabel(tryStartLabel.get());
1531 generator.emitNode(dst, m_tryBlock.get());
1532 generator.emitLabel(tryEndLabel.get());
1533
1534 if (m_catchBlock) {
1535 RefPtr<LabelID> handlerEndLabel = generator.newLabel();
1536 generator.emitJump(handlerEndLabel.get());
1537 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
1538 RefPtr<RegisterID> newScope = generator.emitNewObject(generator.newTemporary()); // scope must be protected until popped
1539 generator.emitPutById(newScope.get(), m_exceptionIdent, exceptionRegister.get());
1540 exceptionRegister = 0; // Release register used for temporaries
1541 generator.emitPushScope(newScope.get());
1542 generator.emitNode(dst, m_catchBlock.get());
1543 generator.emitPopScope();
1544 generator.emitLabel(handlerEndLabel.get());
1545 }
1546
1547 if (m_finallyBlock) {
1548 generator.popFinallyContext();
1549 // there may be important registers live at the time we jump
1550 // to a finally block (such as for a return or throw) so we
1551 // ref the highest register ever used as a conservative
1552 // approach to not clobbering anything important
1553 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
1554 RefPtr<LabelID> finallyEndLabel = generator.newLabel();
1555 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1556 generator.emitJump(finallyEndLabel.get());
1557
1558 // Finally block for exception path
1559 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
1560 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1561 generator.emitThrow(tempExceptionRegister.get());
1562
1563 // emit the finally block itself
1564 generator.emitLabel(finallyStart.get());
1565 generator.emitNode(dst, m_finallyBlock.get());
1566 generator.emitSubroutineReturn(finallyReturnAddr.get());
1567
1568 generator.emitLabel(finallyEndLabel.get());
1569 }
1570
1571 return dst;
1572}
1573
1574
1575// ------------------------------ FunctionBodyNode -----------------------------
1576
1577ScopeNode::ScopeNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1578 : BlockNode(children)
1579 , m_sourceURL(JSGlobalData::threadInstance().parser->sourceURL())
1580 , m_sourceId(JSGlobalData::threadInstance().parser->sourceId())
1581 , m_usesEval(usesEval)
1582 , m_needsClosure(needsClosure)
1583{
1584 if (varStack)
1585 m_varStack = *varStack;
1586 if (funcStack)
1587 m_functionStack = *funcStack;
1588}
1589
1590// ------------------------------ ProgramNode -----------------------------
1591
1592ProgramNode::ProgramNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1593 : ScopeNode(children, varStack, funcStack, usesEval, needsClosure)
1594{
1595}
1596
1597ProgramNode::~ProgramNode()
1598{
1599}
1600
1601ProgramNode* ProgramNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1602{
1603 return new ProgramNode(children, varStack, funcStack, usesEval, needsClosure);
1604}
1605
1606// ------------------------------ EvalNode -----------------------------
1607
1608EvalNode::EvalNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1609 : ScopeNode(children, varStack, funcStack, usesEval, needsClosure)
1610{
1611}
1612
1613EvalNode::~EvalNode()
1614{
1615}
1616
1617RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
1618{
1619 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1620
1621 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1622 generator.emitLoad(dstRegister.get(), jsUndefined());
1623 statementListEmitCode(m_children, generator, dstRegister.get());
1624
1625 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1626 generator.emitEnd(dstRegister.get());
1627 return 0;
1628}
1629
1630void EvalNode::generateCode(ScopeChainNode* sc)
1631{
1632 ScopeChain scopeChain(sc);
1633 JSGlobalObject* globalObject = scopeChain.globalObject();
1634
1635 SymbolTable symbolTable;
1636
1637 m_code.set(new EvalCodeBlock(this, globalObject));
1638
1639 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &symbolTable, m_code.get());
1640 generator.generate();
1641}
1642
1643EvalNode* EvalNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1644{
1645 return new EvalNode(children, varStack, funcStack, usesEval, needsClosure);
1646}
1647
1648// ------------------------------ FunctionBodyNode -----------------------------
1649
1650FunctionBodyNode::FunctionBodyNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1651 : ScopeNode(children, varStack, funcStack, usesEval, needsClosure)
1652{
1653}
1654
1655FunctionBodyNode::~FunctionBodyNode()
1656{
1657}
1658
1659void FunctionBodyNode::mark()
1660{
1661 if (m_code)
1662 m_code->mark();
1663}
1664
1665FunctionBodyNode* FunctionBodyNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1666{
1667 return new FunctionBodyNode(children, varStack, funcStack, usesEval, needsClosure);
1668}
1669
1670void FunctionBodyNode::generateCode(ScopeChainNode* sc)
1671{
1672 ScopeChain scopeChain(sc);
1673 JSGlobalObject* globalObject = scopeChain.globalObject();
1674
1675 m_code.set(new CodeBlock(this, FunctionCode));
1676
1677 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get());
1678 generator.generate();
1679}
1680
1681RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
1682{
1683 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
1684 statementListEmitCode(m_children, generator);
1685 if (!m_children.size() || !m_children.last()->isReturnNode()) {
1686 RegisterID* r0 = generator.emitLoad(generator.newTemporary(), jsUndefined());
1687 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1688 generator.emitReturn(r0);
1689 }
1690 return 0;
1691}
1692
1693RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
1694{
1695 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1696
1697 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1698 generator.emitLoad(dstRegister.get(), jsUndefined());
1699 statementListEmitCode(m_children, generator, dstRegister.get());
1700
1701 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1702 generator.emitEnd(dstRegister.get());
1703 return 0;
1704}
1705
1706void ProgramNode::generateCode(ScopeChainNode* sc, bool canCreateGlobals)
1707{
1708 ScopeChain scopeChain(sc);
1709 JSGlobalObject* globalObject = scopeChain.globalObject();
1710
1711 m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject));
1712
1713 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack, canCreateGlobals);
1714 generator.generate();
1715}
1716
1717UString FunctionBodyNode::paramString() const
1718{
1719 UString s("");
1720 size_t count = m_parameters.size();
1721 for (size_t pos = 0; pos < count; ++pos) {
1722 if (!s.isEmpty())
1723 s += ", ";
1724 s += m_parameters[pos].ustring();
1725 }
1726
1727 return s;
1728}
1729
1730// ------------------------------ FuncDeclNode ---------------------------------
1731
1732void FuncDeclNode::addParams()
1733{
1734 for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
1735 m_body->parameters().append(p->ident());
1736}
1737
1738FunctionImp* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
1739{
1740 FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), scopeChain);
1741
1742 JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
1743 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
1744 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
1745 func->putDirect(exec->propertyNames().length, jsNumber(m_body->parameters().size()), ReadOnly | DontDelete | DontEnum);
1746 return func;
1747}
1748
1749RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
1750{
1751 return dst;
1752}
1753
1754// ------------------------------ FuncExprNode ---------------------------------
1755
1756RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1757{
1758 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
1759}
1760
1761FunctionImp* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
1762{
1763 FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), scopeChain);
1764 JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
1765 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
1766 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
1767
1768 /*
1769 The Identifier in a FunctionExpression can be referenced from inside
1770 the FunctionExpression's FunctionBody to allow the function to call
1771 itself recursively. However, unlike in a FunctionDeclaration, the
1772 Identifier in a FunctionExpression cannot be referenced from and
1773 does not affect the scope enclosing the FunctionExpression.
1774 */
1775
1776 if (!m_ident.isNull()) {
1777 JSObject* functionScopeObject = new JSObject;
1778 functionScopeObject->putDirect(m_ident, func, ReadOnly | DontDelete);
1779 func->scope().push(functionScopeObject);
1780 }
1781
1782 return func;
1783}
1784
1785// ECMA 13
1786void FuncExprNode::addParams()
1787{
1788 for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
1789 m_body->parameters().append(p->ident());
1790}
1791
1792} // namespace KJS
Note: See TracBrowser for help on using the repository browser.