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

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

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

Reviewed by Cameron Zwarich.

Merge pre&post resolve nodes to simplify the parse tree.
Sunspider results show no performance change.

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