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

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

JavaScriptCore:

2008-06-16 Maciej Stachowiak <[email protected]>

Reviewed by Alexey.


  • removed nearly unused types.h and LocalStorageEntry.h headers
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • kjs/ExecState.h:
  • kjs/LocalStorageEntry.h: Removed.
  • kjs/RegExpObject.cpp:
  • kjs/error_object.cpp:
  • kjs/grammar.y:
  • kjs/nodes.cpp:
  • kjs/types.h: Removed.

JavaScriptGlue:

2008-06-16 Maciej Stachowiak <[email protected]>

Reviewed by Alexey.

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