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

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

2008-07-01 Cameron Zwarich <[email protected]>

Reviewed by Darin.

Bug 19844: JavaScript Switch statement modifies "this"
<https://bugs.webkit.org/show_bug.cgi?id=19844>

Use a temporary when generating code for switch clauses to avoid
overwriting 'this' or a local variable.

JavaScriptCore:

  • kjs/nodes.cpp: (KJS::CaseBlockNode::emitCodeForBlock):

LayoutTests:

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