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

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

2008-08-24 Cameron Zwarich <[email protected]>

Reviewed by Oliver.

Remove an unnecessary RefPtr to a RegisterID.

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