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

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

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

Reviewed by Maciej.

Make a UnaryOpNode class to reduce boilerplate code for UnaryPlusNode,
NegateNode, BitwiseNotNode, and LogicalNotNode.

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