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

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

2008-07-17 Geoffrey Garen <[email protected]>

Reviewed by John Sullivan and Oliver Hunt.


A tiny bit of tidying in function call register allocation.


This patch saves one register when invoking a function expression and/or
a new expression that is stored in a temporary.


Since it's just one register, I can't make a testcase for it.

  • VM/CodeGenerator.cpp: (KJS::CodeGenerator::emitCall): No need to ref the function we're calling or its base. We'd like the call frame to overlap with them, if possible. op_call will read the function and its base before writing the call frame, so this is safe.
  • kjs/nodes.cpp: (KJS::NewExprNode::emitCode): No need to ref the function we're new-ing, for the same reasons stated above.


(KJS::FunctionCallValueNode::emitCode): ditto

  • Property svn:eol-style set to native
File size: 63.5 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 RegisterID* r0 = generator.emitNode(m_expr.get());
403 return generator.emitConstruct(generator.finalDestination(dst), r0, 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 RegisterID* func = generator.emitNode(m_expr.get());
417 return generator.emitCall(generator.finalDestination(dst), func, 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* PostfixDotNode::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 if (m_operator == OpPlusPlus)
538 generator.emitPreInc(value.get());
539 else
540 generator.emitPreDec(value.get());
541 } else {
542 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
543 }
544 generator.emitPutById(base.get(), m_ident, value.get());
545 return oldValue;
546}
547
548// ------------------------------ PostfixErrorNode -----------------------------------
549
550RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
551{
552 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.");
553}
554
555// ------------------------------ DeleteResolveNode -----------------------------------
556
557RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
558{
559 if (generator.registerForLocal(m_ident))
560 return generator.emitLoad(generator.finalDestination(dst), false);
561
562 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
563 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
564}
565
566// ------------------------------ DeleteBracketNode -----------------------------------
567
568RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
569{
570 RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
571 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript.get());
572 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
573}
574
575// ------------------------------ DeleteDotNode -----------------------------------
576
577RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
578{
579 RegisterID* r0 = generator.emitNode(m_base.get());
580 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
581}
582
583// ------------------------------ DeleteValueNode -----------------------------------
584
585RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
586{
587 generator.emitNode(ignoredResult(), m_expr.get());
588
589 // delete on a non-location expression ignores the value and returns true
590 return generator.emitLoad(generator.finalDestination(dst), true);
591}
592
593// ------------------------------ VoidNode -------------------------------------
594
595RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
596{
597 if (dst == ignoredResult()) {
598 generator.emitNode(ignoredResult(), m_expr.get());
599 return 0;
600 }
601 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
602 return generator.emitLoad(generator.finalDestination(dst, r0.get()), jsUndefined());
603}
604
605// ------------------------------ TypeOfValueNode -----------------------------------
606
607RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
608{
609 if (RegisterID* local = generator.registerForLocal(m_ident)) {
610 if (dst == ignoredResult())
611 return 0;
612 return generator.emitTypeOf(generator.finalDestination(dst), local);
613 }
614
615 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
616 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
617 if (dst == ignoredResult())
618 return 0;
619 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
620}
621
622// ------------------------------ TypeOfValueNode -----------------------------------
623
624RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
625{
626 if (dst == ignoredResult()) {
627 generator.emitNode(ignoredResult(), m_expr.get());
628 return 0;
629 }
630 RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
631 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
632}
633
634// ------------------------------ PrefixResolveNode ----------------------------------
635
636RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
637{
638 if (RegisterID* local = generator.registerForLocal(m_ident)) {
639 if (generator.isLocalConstant(m_ident)) {
640 if (dst == ignoredResult())
641 return 0;
642 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
643 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get());
644 }
645
646 emitPreIncOrDec(generator, local, m_operator);
647 return generator.moveToDestinationIfNeeded(dst, local);
648 }
649
650 int index = 0;
651 size_t depth = 0;
652 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
653 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
654 emitPreIncOrDec(generator, propDst.get(), m_operator);
655 generator.emitPutScopedVar(depth, index, propDst.get());
656 return generator.moveToDestinationIfNeeded(dst, propDst.get());;
657 }
658
659 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
660 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
661 emitPreIncOrDec(generator, propDst.get(), m_operator);
662 generator.emitPutById(base.get(), m_ident, propDst.get());
663 return generator.moveToDestinationIfNeeded(dst, propDst.get());
664}
665
666// ------------------------------ PrefixBracketNode ----------------------------------
667
668RegisterID* PrefixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
669{
670 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
671 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
672 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
673 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
674 if (m_operator == OpPlusPlus)
675 generator.emitPreInc(value);
676 else
677 generator.emitPreDec(value);
678 generator.emitPutByVal(base.get(), property.get(), value);
679 return generator.moveToDestinationIfNeeded(dst, propDst.get());
680}
681
682// ------------------------------ PrefixDotNode ----------------------------------
683
684RegisterID* PrefixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
685{
686 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
687 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
688 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
689 if (m_operator == OpPlusPlus)
690 generator.emitPreInc(value);
691 else
692 generator.emitPreDec(value);
693 generator.emitPutById(base.get(), m_ident, value);
694 return generator.moveToDestinationIfNeeded(dst, propDst.get());
695}
696
697// ------------------------------ PrefixErrorNode -----------------------------------
698
699RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
700{
701 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.");
702}
703
704// ------------------------------ Unary Operation Nodes -----------------------------------
705
706RegisterID* UnaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
707{
708 RegisterID* src = generator.emitNode(m_expr.get());
709 return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src);
710}
711
712// ------------------------------ Binary Operation Nodes -----------------------------------
713
714RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
715{
716 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2->isPure(generator));
717 RegisterID* src2 = generator.emitNode(m_term2.get());
718 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2);
719}
720
721RegisterID* ReverseBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
722{
723 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2->isPure(generator));
724 RegisterID* src2 = generator.emitNode(m_term2.get());
725 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get());
726}
727
728// ------------------------------ Binary Logical Nodes ----------------------------
729
730RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
731{
732 RefPtr<RegisterID> temp = generator.tempDestination(dst);
733 RefPtr<LabelID> target = generator.newLabel();
734
735 generator.emitNode(temp.get(), m_expr1.get());
736 if (m_operator == OpLogicalAnd)
737 generator.emitJumpIfFalse(temp.get(), target.get());
738 else
739 generator.emitJumpIfTrue(temp.get(), target.get());
740 generator.emitNode(temp.get(), m_expr2.get());
741 generator.emitLabel(target.get());
742
743 return generator.moveToDestinationIfNeeded(dst, temp.get());
744}
745
746// ------------------------------ ConditionalNode ------------------------------
747
748RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
749{
750 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
751 RefPtr<LabelID> beforeElse = generator.newLabel();
752 RefPtr<LabelID> afterElse = generator.newLabel();
753
754 RegisterID* cond = generator.emitNode(m_logical.get());
755 generator.emitJumpIfFalse(cond, beforeElse.get());
756
757 generator.emitNode(newDst.get(), m_expr1.get());
758 generator.emitJump(afterElse.get());
759
760 generator.emitLabel(beforeElse.get());
761 generator.emitNode(newDst.get(), m_expr2.get());
762
763 generator.emitLabel(afterElse.get());
764
765 return newDst.get();
766}
767
768// ------------------------------ ReadModifyResolveNode -----------------------------------
769
770// FIXME: should this be moved to be a method on CodeGenerator?
771static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper)
772{
773 OpcodeID opcode;
774 switch (oper) {
775 case OpMultEq:
776 opcode = op_mul;
777 break;
778 case OpDivEq:
779 opcode = op_div;
780 break;
781 case OpPlusEq:
782 opcode = op_add;
783 break;
784 case OpMinusEq:
785 opcode = op_sub;
786 break;
787 case OpLShift:
788 opcode = op_lshift;
789 break;
790 case OpRShift:
791 opcode = op_rshift;
792 break;
793 case OpURShift:
794 opcode = op_urshift;
795 break;
796 case OpAndEq:
797 opcode = op_bitand;
798 break;
799 case OpXOrEq:
800 opcode = op_bitxor;
801 break;
802 case OpOrEq:
803 opcode = op_bitor;
804 break;
805 case OpModEq:
806 opcode = op_mod;
807 break;
808 default:
809 ASSERT_NOT_REACHED();
810 return dst;
811 }
812
813 return generator.emitBinaryOp(opcode, dst, src1, src2);
814}
815
816RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
817{
818 if (RegisterID* local = generator.registerForLocal(m_ident)) {
819 if (generator.isLocalConstant(m_ident)) {
820 RegisterID* src2 = generator.emitNode(m_right.get());
821 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator);
822 }
823
824 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
825 RefPtr<RegisterID> result = generator.newTemporary();
826 generator.emitMove(result.get(), local);
827 RegisterID* src2 = generator.emitNode(m_right.get());
828 emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator);
829 generator.emitMove(local, result.get());
830 return generator.moveToDestinationIfNeeded(dst, result.get());
831 }
832
833 RegisterID* src2 = generator.emitNode(m_right.get());
834 RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator);
835 return generator.moveToDestinationIfNeeded(dst, result);
836 }
837
838 int index = 0;
839 size_t depth = 0;
840 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
841 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
842 RegisterID* src2 = generator.emitNode(m_right.get());
843 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
844 generator.emitPutScopedVar(depth, index, result);
845 return result;
846 }
847
848 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
849 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
850 RegisterID* src2 = generator.emitNode(m_right.get());
851 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
852 return generator.emitPutById(base.get(), m_ident, result);
853}
854
855// ------------------------------ AssignResolveNode -----------------------------------
856
857RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
858{
859 if (RegisterID* local = generator.registerForLocal(m_ident)) {
860 if (generator.isLocalConstant(m_ident))
861 return generator.emitNode(dst, m_right.get());
862
863 RegisterID* result = generator.emitNode(local, m_right.get());
864 return generator.moveToDestinationIfNeeded(dst, result);
865 }
866
867 int index = 0;
868 size_t depth = 0;
869 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
870 if (dst == ignoredResult())
871 dst = 0;
872 RegisterID* value = generator.emitNode(dst, m_right.get());
873 generator.emitPutScopedVar(depth, index, value);
874 return value;
875 }
876
877 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
878 if (dst == ignoredResult())
879 dst = 0;
880 RegisterID* value = generator.emitNode(dst, m_right.get());
881 return generator.emitPutById(base.get(), m_ident, value);
882}
883
884// ------------------------------ AssignDotNode -----------------------------------
885
886RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
887{
888 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
889 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
890 RegisterID* result = generator.emitNode(value.get(), m_right.get());
891 generator.emitPutById(base.get(), m_ident, result);
892 return generator.moveToDestinationIfNeeded(dst, result);
893}
894
895// ------------------------------ ReadModifyDotNode -----------------------------------
896
897RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
898{
899 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
900 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
901 RegisterID* change = generator.emitNode(m_right.get());
902 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
903 return generator.emitPutById(base.get(), m_ident, updatedValue);
904}
905
906// ------------------------------ AssignErrorNode -----------------------------------
907
908RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
909{
910 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
911}
912
913// ------------------------------ AssignBracketNode -----------------------------------
914
915RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
916{
917 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
918 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
919 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
920 RegisterID* result = generator.emitNode(value.get(), m_right.get());
921 generator.emitPutByVal(base.get(), property.get(), result);
922 return generator.moveToDestinationIfNeeded(dst, result);
923}
924
925RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
926{
927 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
928 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
929
930 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
931 RegisterID* change = generator.emitNode(m_right.get());
932 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
933
934 generator.emitPutByVal(base.get(), property.get(), updatedValue);
935
936 return updatedValue;
937}
938
939// ------------------------------ CommaNode ------------------------------------
940
941RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
942{
943 generator.emitNode(ignoredResult(), m_expr1.get());
944 return generator.emitNode(dst, m_expr2.get());
945}
946
947// ------------------------------ ConstDeclNode ----------------------------------
948
949ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
950 : ExpressionNode(globalData)
951 , m_ident(ident)
952 , m_init(init)
953{
954}
955
956RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
957{
958 if (RegisterID* local = generator.registerForLocalConstInit(m_ident)) {
959 if (!m_init)
960 return local;
961
962 return generator.emitNode(local, m_init.get());
963 }
964
965 // FIXME: While this code should only be hit in eval code, it will potentially
966 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
967 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
968 RegisterID* value = generator.emitNode(m_init.get());
969 return generator.emitPutById(base.get(), m_ident, value);
970}
971
972RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
973{
974 RegisterID* result = 0;
975 for (ConstDeclNode* n = this; n; n = n->m_next.get())
976 result = n->emitCodeSingle(generator);
977
978 return result;
979}
980
981// ------------------------------ ConstStatementNode -----------------------------
982
983RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
984{
985 return generator.emitNode(m_next.get());
986}
987
988// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
989
990static inline RegisterID* statementListEmitCode(StatementVector& statements, CodeGenerator& generator, RegisterID* dst = 0)
991{
992 StatementVector::iterator end = statements.end();
993 for (StatementVector::iterator it = statements.begin(); it != end; ++it) {
994 StatementNode* n = it->get();
995 generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
996 generator.emitNode(dst, n);
997 }
998 return 0;
999}
1000
1001static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
1002{
1003 StatementVector::iterator it = statements.end();
1004 StatementVector::iterator begin = statements.begin();
1005 while (it != begin) {
1006 --it;
1007 stack.append((*it).get());
1008 }
1009}
1010
1011static inline Node* statementListInitializeVariableAccessStack(StatementVector& statements, DeclarationStacks::NodeStack& stack)
1012{
1013 if (statements.isEmpty())
1014 return 0;
1015
1016 StatementVector::iterator it = statements.end();
1017 StatementVector::iterator begin = statements.begin();
1018 StatementVector::iterator beginPlusOne = begin + 1;
1019
1020 while (it != beginPlusOne) {
1021 --it;
1022 stack.append((*it).get());
1023 }
1024
1025 return (*begin).get();
1026}
1027
1028// ------------------------------ BlockNode ------------------------------------
1029
1030BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
1031 : StatementNode(globalData)
1032{
1033 if (children)
1034 children->releaseContentsIntoVector(m_children);
1035}
1036
1037RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1038{
1039 return statementListEmitCode(m_children, generator, dst);
1040}
1041
1042// ------------------------------ EmptyStatementNode ---------------------------
1043
1044RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
1045{
1046 return dst;
1047}
1048
1049// ------------------------------ DebuggerStatementNode ---------------------------
1050
1051RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1052{
1053 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1054 return dst;
1055}
1056
1057// ------------------------------ ExprStatementNode ----------------------------
1058
1059RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1060{
1061 ASSERT(m_expr);
1062 return generator.emitNode(dst, m_expr.get());
1063}
1064
1065// ------------------------------ VarStatementNode ----------------------------
1066
1067RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1068{
1069 ASSERT(m_expr);
1070 return generator.emitNode(m_expr.get());
1071}
1072
1073// ------------------------------ IfNode ---------------------------------------
1074
1075RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1076{
1077 RefPtr<LabelID> afterThen = generator.newLabel();
1078
1079 RegisterID* cond = generator.emitNode(m_condition.get());
1080 generator.emitJumpIfFalse(cond, afterThen.get());
1081
1082 generator.emitNode(dst, m_ifBlock.get());
1083 generator.emitLabel(afterThen.get());
1084
1085 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
1086 return 0;
1087}
1088
1089RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1090{
1091 RefPtr<LabelID> beforeElse = generator.newLabel();
1092 RefPtr<LabelID> afterElse = generator.newLabel();
1093
1094 RegisterID* cond = generator.emitNode(m_condition.get());
1095 generator.emitJumpIfFalse(cond, beforeElse.get());
1096
1097 generator.emitNode(dst, m_ifBlock.get());
1098 generator.emitJump(afterElse.get());
1099
1100 generator.emitLabel(beforeElse.get());
1101 generator.emitNode(dst, m_elseBlock.get());
1102
1103 generator.emitLabel(afterElse.get());
1104
1105 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
1106 return 0;
1107}
1108
1109// ------------------------------ DoWhileNode ----------------------------------
1110
1111RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1112{
1113 RefPtr<LabelID> topOfLoop = generator.newLabel();
1114 generator.emitLabel(topOfLoop.get());
1115
1116 RefPtr<LabelID> continueTarget = generator.newLabel();
1117 RefPtr<LabelID> breakTarget = generator.newLabel();
1118
1119 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1120 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1121 generator.popJumpContext();
1122
1123 generator.emitLabel(continueTarget.get());
1124 RegisterID* cond = generator.emitNode(m_expr.get());
1125 generator.emitJumpIfTrue(cond, topOfLoop.get());
1126 generator.emitLabel(breakTarget.get());
1127 return result.get();
1128}
1129
1130// ------------------------------ WhileNode ------------------------------------
1131
1132RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1133{
1134 RefPtr<LabelID> topOfLoop = generator.newLabel();
1135 RefPtr<LabelID> continueTarget = generator.newLabel();
1136 RefPtr<LabelID> breakTarget = generator.newLabel();
1137
1138 generator.emitJump(continueTarget.get());
1139 generator.emitLabel(topOfLoop.get());
1140
1141 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1142 generator.emitNode(dst, m_statement.get());
1143 generator.popJumpContext();
1144
1145 generator.emitLabel(continueTarget.get());
1146 RegisterID* cond = generator.emitNode(m_expr.get());
1147 generator.emitJumpIfTrue(cond, topOfLoop.get());
1148
1149 generator.emitLabel(breakTarget.get());
1150
1151 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1152 return 0;
1153}
1154
1155// ------------------------------ ForNode --------------------------------------
1156
1157RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1158{
1159 if (m_expr1)
1160 generator.emitNode(ignoredResult(), m_expr1.get());
1161
1162 RefPtr<LabelID> topOfLoop = generator.newLabel();
1163 RefPtr<LabelID> beforeCondition = generator.newLabel();
1164 RefPtr<LabelID> continueTarget = generator.newLabel();
1165 RefPtr<LabelID> breakTarget = generator.newLabel();
1166 generator.emitJump(beforeCondition.get());
1167
1168 generator.emitLabel(topOfLoop.get());
1169 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1170 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1171 generator.popJumpContext();
1172 generator.emitLabel(continueTarget.get());
1173 if (m_expr3)
1174 generator.emitNode(ignoredResult(), m_expr3.get());
1175
1176 generator.emitLabel(beforeCondition.get());
1177 if (m_expr2) {
1178 RegisterID* cond = generator.emitNode(m_expr2.get());
1179 generator.emitJumpIfTrue(cond, topOfLoop.get());
1180 } else {
1181 generator.emitJump(topOfLoop.get());
1182 }
1183 generator.emitLabel(breakTarget.get());
1184 return result.get();
1185}
1186
1187// ------------------------------ ForInNode ------------------------------------
1188
1189ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
1190 : StatementNode(globalData)
1191 , m_init(0L)
1192 , m_lexpr(l)
1193 , m_expr(expr)
1194 , m_statement(statement)
1195 , m_identIsVarDecl(false)
1196{
1197}
1198
1199ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement)
1200 : StatementNode(globalData)
1201 , m_ident(ident)
1202 , m_lexpr(new ResolveNode(globalData, ident))
1203 , m_expr(expr)
1204 , m_statement(statement)
1205 , m_identIsVarDecl(true)
1206{
1207 if (in)
1208 m_init = new AssignResolveNode(globalData, ident, in, true);
1209 // for( var foo = bar in baz )
1210}
1211
1212RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1213{
1214 RefPtr<LabelID> loopStart = generator.newLabel();
1215 RefPtr<LabelID> continueTarget = generator.newLabel();
1216 RefPtr<LabelID> breakTarget = generator.newLabel();
1217
1218 if (m_init)
1219 generator.emitNode(ignoredResult(), m_init.get());
1220 RegisterID* forInBase = generator.emitNode(m_expr.get());
1221 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
1222 generator.emitJump(continueTarget.get());
1223 generator.emitLabel(loopStart.get());
1224 RegisterID* propertyName;
1225 if (m_lexpr->isResolveNode()) {
1226 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
1227 propertyName = generator.registerForLocal(ident);
1228 if (!propertyName) {
1229 propertyName = generator.newTemporary();
1230 RefPtr<RegisterID> protect = propertyName;
1231 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
1232 generator.emitPutById(base, ident, propertyName);
1233 }
1234 } else if (m_lexpr->isDotAccessorNode()) {
1235 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
1236 const Identifier& ident = assignNode->identifier();
1237 propertyName = generator.newTemporary();
1238 RefPtr<RegisterID> protect = propertyName;
1239 RegisterID* base = generator.emitNode(assignNode->base());
1240 generator.emitPutById(base, ident, propertyName);
1241 } else {
1242 ASSERT(m_lexpr->isBracketAccessorNode());
1243 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
1244 propertyName = generator.newTemporary();
1245 RefPtr<RegisterID> protect = propertyName;
1246 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1247 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1248 generator.emitPutByVal(base.get(), subscript, propertyName);
1249 }
1250
1251 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1252 generator.emitNode(dst, m_statement.get());
1253 generator.popJumpContext();
1254
1255 generator.emitLabel(continueTarget.get());
1256 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
1257 generator.emitLabel(breakTarget.get());
1258 return dst;
1259}
1260
1261// ------------------------------ ContinueNode ---------------------------------
1262
1263// ECMA 12.7
1264RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1265{
1266 if (!generator.inContinueContext())
1267 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1268
1269 JumpContext* targetContext = generator.jumpContextForContinue(m_ident);
1270
1271 if (!targetContext) {
1272 if (m_ident.isEmpty())
1273 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1274 else
1275 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
1276 }
1277
1278 if (!targetContext->continueTarget)
1279 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1280
1281 generator.emitJumpScopes(targetContext->continueTarget, targetContext->scopeDepth);
1282
1283 return dst;
1284}
1285
1286// ------------------------------ BreakNode ------------------------------------
1287
1288// ECMA 12.8
1289RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1290{
1291 if (!generator.inJumpContext())
1292 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
1293
1294 JumpContext* targetContext = generator.jumpContextForBreak(m_ident);
1295
1296 if (!targetContext) {
1297 if (m_ident.isEmpty())
1298 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
1299 else
1300 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
1301 }
1302
1303 ASSERT(targetContext->breakTarget);
1304
1305 generator.emitJumpScopes(targetContext->breakTarget, targetContext->scopeDepth);
1306
1307 return dst;
1308}
1309
1310// ------------------------------ ReturnNode -----------------------------------
1311
1312RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1313{
1314 if (generator.codeType() != FunctionCode)
1315 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
1316
1317 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(generator.finalDestination(dst), jsUndefined());
1318 if (generator.scopeDepth()) {
1319 RefPtr<LabelID> l0 = generator.newLabel();
1320 generator.emitJumpScopes(l0.get(), 0);
1321 generator.emitLabel(l0.get());
1322 }
1323 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1324 return generator.emitReturn(r0);
1325}
1326
1327// ------------------------------ WithNode -------------------------------------
1328
1329RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1330{
1331 RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
1332 generator.emitPushScope(scope.get());
1333 RegisterID* result = generator.emitNode(dst, m_statement.get());
1334 generator.emitPopScope();
1335 return result;
1336}
1337
1338// ------------------------------ CaseBlockNode --------------------------------
1339
1340RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
1341{
1342 Vector<RefPtr<LabelID>, 8> labelVector;
1343
1344 // Setup jumps
1345 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
1346 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1347 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1348 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression);
1349 labelVector.append(generator.newLabel());
1350 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1351 }
1352
1353 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
1354 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1355 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1356 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression);
1357 labelVector.append(generator.newLabel());
1358 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1359 }
1360
1361 RefPtr<LabelID> defaultLabel;
1362 defaultLabel = generator.newLabel();
1363 generator.emitJump(defaultLabel.get());
1364
1365 RegisterID* result = 0;
1366
1367 size_t i = 0;
1368 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
1369 generator.emitLabel(labelVector[i++].get());
1370 result = statementListEmitCode(list->getClause()->children(), generator, dst);
1371 }
1372
1373 if (m_defaultClause) {
1374 generator.emitLabel(defaultLabel.get());
1375 result = statementListEmitCode(m_defaultClause->children(), generator, dst);
1376 }
1377
1378 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
1379 generator.emitLabel(labelVector[i++].get());
1380 result = statementListEmitCode(list->getClause()->children(), generator, dst);
1381 }
1382 if (!m_defaultClause)
1383 generator.emitLabel(defaultLabel.get());
1384
1385 ASSERT(i == labelVector.size());
1386
1387 return result;
1388}
1389
1390// ------------------------------ SwitchNode -----------------------------------
1391
1392RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1393{
1394 RefPtr<LabelID> breakTarget = generator.newLabel();
1395
1396 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
1397 generator.pushJumpContext(&m_labelStack, 0, breakTarget.get(), true);
1398 RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
1399 generator.popJumpContext();
1400
1401 generator.emitLabel(breakTarget.get());
1402
1403 return r1;
1404}
1405
1406// ------------------------------ LabelNode ------------------------------------
1407
1408RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1409{
1410 if (generator.jumpContextForBreak(m_label))
1411 return emitThrowError(generator, SyntaxError, "Duplicated label %s found.", m_label);
1412
1413 RefPtr<LabelID> l0 = generator.newLabel();
1414 m_labelStack.push(m_label);
1415 generator.pushJumpContext(&m_labelStack, 0, l0.get(), false);
1416
1417 RegisterID* r0 = generator.emitNode(dst, m_statement.get());
1418
1419 generator.popJumpContext();
1420 m_labelStack.pop();
1421
1422 generator.emitLabel(l0.get());
1423 return r0;
1424}
1425
1426// ------------------------------ ThrowNode ------------------------------------
1427
1428RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1429{
1430 generator.emitThrow(generator.emitNode(dst, m_expr.get()));
1431 return dst;
1432}
1433
1434// ------------------------------ TryNode --------------------------------------
1435
1436RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1437{
1438 RefPtr<LabelID> tryStartLabel = generator.newLabel();
1439 RefPtr<LabelID> tryEndLabel = generator.newLabel();
1440 RefPtr<LabelID> finallyStart;
1441 RefPtr<RegisterID> finallyReturnAddr;
1442 if (m_finallyBlock) {
1443 finallyStart = generator.newLabel();
1444 finallyReturnAddr = generator.newTemporary();
1445 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
1446 }
1447 generator.emitLabel(tryStartLabel.get());
1448 generator.emitNode(dst, m_tryBlock.get());
1449 generator.emitLabel(tryEndLabel.get());
1450
1451 if (m_catchBlock) {
1452 RefPtr<LabelID> handlerEndLabel = generator.newLabel();
1453 generator.emitJump(handlerEndLabel.get());
1454 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
1455 RefPtr<RegisterID> newScope = generator.emitNewObject(generator.newTemporary()); // scope must be protected until popped
1456 generator.emitPutById(newScope.get(), m_exceptionIdent, exceptionRegister.get());
1457 exceptionRegister = 0; // Release register used for temporaries
1458 generator.emitPushScope(newScope.get());
1459 generator.emitNode(dst, m_catchBlock.get());
1460 generator.emitPopScope();
1461 generator.emitLabel(handlerEndLabel.get());
1462 }
1463
1464 if (m_finallyBlock) {
1465 generator.popFinallyContext();
1466 // there may be important registers live at the time we jump
1467 // to a finally block (such as for a return or throw) so we
1468 // ref the highest register ever used as a conservative
1469 // approach to not clobbering anything important
1470 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
1471 RefPtr<LabelID> finallyEndLabel = generator.newLabel();
1472 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1473 generator.emitJump(finallyEndLabel.get());
1474
1475 // Finally block for exception path
1476 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
1477 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1478 generator.emitThrow(tempExceptionRegister.get());
1479
1480 // emit the finally block itself
1481 generator.emitLabel(finallyStart.get());
1482 generator.emitNode(dst, m_finallyBlock.get());
1483 generator.emitSubroutineReturn(finallyReturnAddr.get());
1484
1485 generator.emitLabel(finallyEndLabel.get());
1486 }
1487
1488 return dst;
1489}
1490
1491
1492// ------------------------------ FunctionBodyNode -----------------------------
1493
1494ScopeNode::ScopeNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1495 : BlockNode(globalData, children)
1496 , m_sourceURL(globalData->parser->sourceURL())
1497 , m_sourceId(globalData->parser->sourceId())
1498 , m_usesEval(usesEval)
1499 , m_needsClosure(needsClosure)
1500{
1501 if (varStack)
1502 m_varStack = *varStack;
1503 if (funcStack)
1504 m_functionStack = *funcStack;
1505}
1506
1507// ------------------------------ ProgramNode -----------------------------
1508
1509ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1510 : ScopeNode(globalData, children, varStack, funcStack, usesEval, needsClosure)
1511{
1512}
1513
1514ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1515{
1516 return new ProgramNode(globalData, children, varStack, funcStack, usesEval, needsClosure);
1517}
1518
1519// ------------------------------ EvalNode -----------------------------
1520
1521EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1522 : ScopeNode(globalData, children, varStack, funcStack, usesEval, needsClosure)
1523{
1524}
1525
1526RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
1527{
1528 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1529
1530 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1531 generator.emitLoad(dstRegister.get(), jsUndefined());
1532 statementListEmitCode(m_children, generator, dstRegister.get());
1533
1534 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1535 generator.emitEnd(dstRegister.get());
1536 return 0;
1537}
1538
1539void EvalNode::generateCode(ScopeChainNode* sc)
1540{
1541 ScopeChain scopeChain(sc);
1542 JSGlobalObject* globalObject = scopeChain.globalObject();
1543
1544 SymbolTable symbolTable;
1545
1546 m_code.set(new EvalCodeBlock(this, globalObject));
1547
1548 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &symbolTable, m_code.get());
1549 generator.generate();
1550}
1551
1552EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1553{
1554 return new EvalNode(globalData, children, varStack, funcStack, usesEval, needsClosure);
1555}
1556
1557// ------------------------------ FunctionBodyNode -----------------------------
1558
1559FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1560 : ScopeNode(globalData, children, varStack, funcStack, usesEval, needsClosure)
1561{
1562}
1563
1564void FunctionBodyNode::mark()
1565{
1566 if (m_code)
1567 m_code->mark();
1568}
1569
1570FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
1571{
1572 return new FunctionBodyNode(globalData, children, varStack, funcStack, usesEval, needsClosure);
1573}
1574
1575void FunctionBodyNode::generateCode(ScopeChainNode* sc)
1576{
1577 ScopeChain scopeChain(sc);
1578 JSGlobalObject* globalObject = scopeChain.globalObject();
1579
1580 m_code.set(new CodeBlock(this, FunctionCode));
1581
1582 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get());
1583 generator.generate();
1584}
1585
1586RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
1587{
1588 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
1589 statementListEmitCode(m_children, generator);
1590 if (!m_children.size() || !m_children.last()->isReturnNode()) {
1591 RegisterID* r0 = generator.emitLoad(generator.newTemporary(), jsUndefined());
1592 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1593 generator.emitReturn(r0);
1594 }
1595 return 0;
1596}
1597
1598RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
1599{
1600 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1601
1602 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1603 generator.emitLoad(dstRegister.get(), jsUndefined());
1604 statementListEmitCode(m_children, generator, dstRegister.get());
1605
1606 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1607 generator.emitEnd(dstRegister.get());
1608 return 0;
1609}
1610
1611void ProgramNode::generateCode(ScopeChainNode* sc)
1612{
1613 ScopeChain scopeChain(sc);
1614 JSGlobalObject* globalObject = scopeChain.globalObject();
1615
1616 m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject));
1617
1618 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack);
1619 generator.generate();
1620}
1621
1622UString FunctionBodyNode::paramString() const
1623{
1624 UString s("");
1625 size_t count = m_parameters.size();
1626 for (size_t pos = 0; pos < count; ++pos) {
1627 if (!s.isEmpty())
1628 s += ", ";
1629 s += m_parameters[pos].ustring();
1630 }
1631
1632 return s;
1633}
1634
1635// ------------------------------ FuncDeclNode ---------------------------------
1636
1637void FuncDeclNode::addParams()
1638{
1639 for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
1640 m_body->parameters().append(p->ident());
1641}
1642
1643JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
1644{
1645 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
1646
1647 JSObject* proto = constructEmptyObject(exec);
1648 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
1649 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
1650 func->putDirect(exec->propertyNames().length, jsNumber(exec, m_body->parameters().size()), ReadOnly | DontDelete | DontEnum);
1651 return func;
1652}
1653
1654RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
1655{
1656 return dst;
1657}
1658
1659// ------------------------------ FuncExprNode ---------------------------------
1660
1661RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1662{
1663 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
1664}
1665
1666JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
1667{
1668 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
1669 JSObject* proto = constructEmptyObject(exec);
1670 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
1671 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
1672
1673 /*
1674 The Identifier in a FunctionExpression can be referenced from inside
1675 the FunctionExpression's FunctionBody to allow the function to call
1676 itself recursively. However, unlike in a FunctionDeclaration, the
1677 Identifier in a FunctionExpression cannot be referenced from and
1678 does not affect the scope enclosing the FunctionExpression.
1679 */
1680
1681 if (!m_ident.isNull()) {
1682 JSObject* functionScopeObject = new (exec) JSObject;
1683 functionScopeObject->putDirect(m_ident, func, ReadOnly | DontDelete);
1684 func->scope().push(functionScopeObject);
1685 }
1686
1687 return func;
1688}
1689
1690// ECMA 13
1691void FuncExprNode::addParams()
1692{
1693 for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
1694 m_body->parameters().append(p->ident());
1695}
1696
1697} // namespace KJS
Note: See TracBrowser for help on using the repository browser.