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

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

2008-07-29 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

Bug 20209: Atomize constant strings
<https://bugs.webkit.org/show_bug.cgi?id=20209>

Prevents significant performance degradation seen when a script contains multiple
identical strings that are used as keys to identify properties on objects.

No performance change on SunSpider.

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