6368152f74bcfaf778bce359ef1017638ea2b61d
[WebKit-https.git] / JavaScriptCore / kjs / nodes.cpp
1 /*
2  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
5  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6  *  Copyright (C) 2007 Maks Orlovich
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Library General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Library General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Library General Public License
19  *  along with this library; see the file COPYING.LIB.  If not, write to
20  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  *  Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #include "config.h"
26 #include "nodes.h"
27
28 #include "ExecState.h"
29 #include "JSGlobalObject.h"
30 #include "PropertyNameArray.h"
31 #include "debugger.h"
32 #include "function_object.h"
33 #include "lexer.h"
34 #include "operations.h"
35 #include "regexp_object.h"
36 #include <math.h>
37 #include <wtf/Assertions.h>
38 #include <wtf/HashCountedSet.h>
39 #include <wtf/HashSet.h>
40 #include <wtf/MathExtras.h>
41
42 namespace KJS {
43
44 #define KJS_BREAKPOINT \
45   if (Debugger::debuggersPresent > 0 && !hitStatement(exec)) \
46     return Completion(Normal);
47
48 #define KJS_CHECKEXCEPTION \
49   if (exec->hadException()) \
50     return rethrowException(exec);
51
52 #define KJS_CHECKEXCEPTIONVALUE \
53   if (exec->hadException()) { \
54     handleException(exec); \
55     return jsUndefined(); \
56   }
57
58 #define KJS_CHECKEXCEPTIONLIST \
59   if (exec->hadException()) { \
60     handleException(exec); \
61     return; \
62   }
63
64 #define KJS_CHECKEXCEPTIONVOID \
65   if (exec->hadException()) { \
66     handleException(exec); \
67     return; \
68   }
69
70 #if !ASSERT_DISABLED
71 static inline bool canSkipLookup(ExecState* exec, const Identifier& ident)
72 {
73     // Static lookup in EvalCode is impossible because variables aren't DontDelete. 
74     // Static lookup in GlobalCode may be possible, but we haven't implemented support for it yet.
75     if (exec->codeType() != FunctionCode)
76         return false;
77
78     // Static lookup is impossible when something dynamic has been added to the front of the scope chain.
79     if (exec->variableObject() != exec->scopeChain().top())
80         return false;
81
82     ASSERT(exec->variableObject()->isActivation()); // Because this is function code.
83
84     // Static lookup is impossible if the symbol isn't statically declared.
85     if (!static_cast<ActivationImp*>(exec->variableObject())->symbolTable().contains(ident.ustring().rep()))
86         return false;
87         
88     return true;
89 }
90 #endif
91
92 // ------------------------------ Node -----------------------------------------
93
94 #ifndef NDEBUG
95 #ifndef LOG_CHANNEL_PREFIX
96 #define LOG_CHANNEL_PREFIX Log
97 #endif
98 static WTFLogChannel LogKJSNodeLeaks = { 0x00000000, "", WTFLogChannelOn };
99
100 struct NodeCounter { 
101     static unsigned count; 
102     ~NodeCounter() 
103     { 
104         if (count) 
105             LOG(KJSNodeLeaks, "LEAK: %u KJS::Node\n", count); 
106     }
107 };
108 unsigned NodeCounter::count = 0;
109 static NodeCounter nodeCounter;
110 #endif
111
112 static HashSet<Node*>* newNodes;
113 static HashCountedSet<Node*>* nodeExtraRefCounts;
114
115 Node::Node()
116     : m_mayHaveDeclarations(false)
117 {
118 #ifndef NDEBUG
119     ++NodeCounter::count;
120 #endif
121   m_line = Lexer::curr()->lineNo();
122   if (!newNodes)
123       newNodes = new HashSet<Node*>;
124   newNodes->add(this);
125 }
126
127 Node::~Node()
128 {
129 #ifndef NDEBUG
130     --NodeCounter::count;
131 #endif
132 }
133
134 void Node::ref()
135 {
136     // bumping from 0 to 1 is just removing from the new nodes set
137     if (newNodes) {
138         HashSet<Node*>::iterator it = newNodes->find(this);
139         if (it != newNodes->end()) {
140             newNodes->remove(it);
141             ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
142             return;
143         }
144     }   
145
146     ASSERT(!newNodes || !newNodes->contains(this));
147     
148     if (!nodeExtraRefCounts)
149         nodeExtraRefCounts = new HashCountedSet<Node*>;
150     nodeExtraRefCounts->add(this);
151 }
152
153 void Node::deref()
154 {
155     ASSERT(!newNodes || !newNodes->contains(this));
156     
157     if (!nodeExtraRefCounts) {
158         delete this;
159         return;
160     }
161
162     HashCountedSet<Node*>::iterator it = nodeExtraRefCounts->find(this);
163     if (it == nodeExtraRefCounts->end())
164         delete this;
165     else
166         nodeExtraRefCounts->remove(it);
167 }
168
169 unsigned Node::refcount()
170 {
171     if (newNodes && newNodes->contains(this)) {
172         ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
173         return 0;
174     }
175  
176     ASSERT(!newNodes || !newNodes->contains(this));
177
178     if (!nodeExtraRefCounts)
179         return 1;
180
181     return 1 + nodeExtraRefCounts->count(this);
182 }
183
184 void Node::clearNewNodes()
185 {
186     if (!newNodes)
187         return;
188
189 #ifndef NDEBUG
190     HashSet<Node*>::iterator end = newNodes->end();
191     for (HashSet<Node*>::iterator it = newNodes->begin(); it != end; ++it)
192         ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(*it));
193 #endif
194     deleteAllValues(*newNodes);
195     delete newNodes;
196     newNodes = 0;
197 }
198
199 static void substitute(UString &string, const UString &substring) KJS_FAST_CALL;
200 static void substitute(UString &string, const UString &substring)
201 {
202     int position = string.find("%s");
203     ASSERT(position != -1);
204     UString newString = string.substr(0, position);
205     newString.append(substring);
206     newString.append(string.substr(position + 2));
207     string = newString;
208 }
209
210 static inline int currentSourceId(ExecState* exec) KJS_FAST_CALL;
211 static inline int currentSourceId(ExecState* exec)
212 {
213     return exec->currentBody()->sourceId();
214 }
215
216 static inline const UString& currentSourceURL(ExecState* exec) KJS_FAST_CALL;
217 static inline const UString& currentSourceURL(ExecState* exec)
218 {
219     return exec->currentBody()->sourceURL();
220 }
221
222 Completion Node::createErrorCompletion(ExecState* exec, ErrorType e, const char *msg)
223 {
224     return Completion(Throw, Error::create(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
225 }
226
227 Completion Node::createErrorCompletion(ExecState *exec, ErrorType e, const char *msg, const Identifier &ident)
228 {
229     UString message = msg;
230     substitute(message, ident.ustring());
231     return Completion(Throw, Error::create(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
232 }
233
234 JSValue *Node::throwError(ExecState* exec, ErrorType e, const char *msg)
235 {
236     return KJS::throwError(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec));
237 }
238
239 JSValue *Node::throwError(ExecState* exec, ErrorType e, const char* msg, const char* string)
240 {
241     UString message = msg;
242     substitute(message, string);
243     return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
244 }
245
246 JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, JSValue *v, Node *expr)
247 {
248     UString message = msg;
249     substitute(message, v->toString(exec));
250     substitute(message, expr->toString());
251     return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
252 }
253
254
255 JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, const Identifier &label)
256 {
257     UString message = msg;
258     substitute(message, label.ustring());
259     return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
260 }
261
262 JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, JSValue *v, Node *e1, Node *e2)
263 {
264     UString message = msg;
265     substitute(message, v->toString(exec));
266     substitute(message, e1->toString());
267     substitute(message, e2->toString());
268     return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
269 }
270
271 JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, JSValue *v, Node *expr, const Identifier &label)
272 {
273     UString message = msg;
274     substitute(message, v->toString(exec));
275     substitute(message, expr->toString());
276     substitute(message, label.ustring());
277     return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
278 }
279
280 JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, JSValue *v, const Identifier &label)
281 {
282     UString message = msg;
283     substitute(message, v->toString(exec));
284     substitute(message, label.ustring());
285     return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
286 }
287
288 JSValue *Node::throwUndefinedVariableError(ExecState *exec, const Identifier &ident)
289 {
290     return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
291 }
292
293 void Node::handleException(ExecState* exec)
294 {
295     handleException(exec, exec->exception());
296 }
297
298 void Node::handleException(ExecState* exec, JSValue* exceptionValue)
299 {
300     if (exceptionValue->isObject()) {
301         JSObject* exception = static_cast<JSObject*>(exceptionValue);
302         if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
303             exception->put(exec, "line", jsNumber(m_line));
304             exception->put(exec, "sourceURL", jsString(currentSourceURL(exec)));
305         }
306     }
307     Debugger* dbg = exec->dynamicInterpreter()->debugger();
308     if (dbg && !dbg->hasHandledException(exec, exceptionValue)) {
309         bool cont = dbg->exception(exec, currentSourceId(exec), m_line, exceptionValue);
310         if (!cont)
311             dbg->imp()->abort();
312     }
313 }
314
315 Completion Node::rethrowException(ExecState* exec)
316 {
317     JSValue* exception = exec->exception();
318     exec->clearException();
319     handleException(exec, exception);
320     return Completion(Throw, exception);
321 }
322
323 // ------------------------------ StatementNode --------------------------------
324
325 StatementNode::StatementNode() 
326     : m_lastLine(-1)
327 {
328     m_line = -1;
329 }
330
331 void StatementNode::setLoc(int firstLine, int lastLine)
332 {
333     m_line = firstLine;
334     m_lastLine = lastLine;
335 }
336
337 // return true if the debugger wants us to stop at this point
338 bool StatementNode::hitStatement(ExecState* exec)
339 {
340   Debugger *dbg = exec->dynamicInterpreter()->debugger();
341   if (dbg)
342     return dbg->atStatement(exec, currentSourceId(exec), firstLine(), lastLine());
343   else
344     return true; // continue
345 }
346
347 // ------------------------------ NullNode -------------------------------------
348
349 JSValue *NullNode::evaluate(ExecState *)
350 {
351   return jsNull();
352 }
353
354 // ------------------------------ BooleanNode ----------------------------------
355
356 JSValue *BooleanNode::evaluate(ExecState *)
357 {
358   return jsBoolean(value);
359 }
360
361 // ------------------------------ NumberNode -----------------------------------
362
363 JSValue *NumberNode::evaluate(ExecState *)
364 {
365     // Number nodes are only created when the number can't fit in a JSImmediate, so no need to check again.
366     return jsNumberCell(val);
367 }
368
369 JSValue* ImmediateNumberNode::evaluate(ExecState*)
370 {
371     return m_value;
372 }
373
374 // ------------------------------ StringNode -----------------------------------
375
376 JSValue *StringNode::evaluate(ExecState *)
377 {
378   return jsOwnedString(value);
379 }
380
381 // ------------------------------ RegExpNode -----------------------------------
382
383 JSValue *RegExpNode::evaluate(ExecState *exec)
384 {
385   List list;
386   list.append(jsOwnedString(pattern));
387   list.append(jsOwnedString(flags));
388
389   JSObject *reg = exec->lexicalInterpreter()->builtinRegExp();
390   return reg->construct(exec,list);
391 }
392
393 // ------------------------------ ThisNode -------------------------------------
394
395 // ECMA 11.1.1
396 JSValue *ThisNode::evaluate(ExecState *exec)
397 {
398   return exec->thisValue();
399 }
400
401 // ------------------------------ ResolveNode ----------------------------------
402
403 // ECMA 11.1.2 & 10.1.4
404 JSValue *ResolveNode::evaluate(ExecState *exec)
405 {
406   // Check for missed optimization opportunity.
407   ASSERT(!canSkipLookup(exec, ident));
408
409   const ScopeChain& chain = exec->scopeChain();
410   ScopeChainIterator iter = chain.begin();
411   ScopeChainIterator end = chain.end();
412   
413   // we must always have something in the scope chain
414   ASSERT(iter != end);
415
416   PropertySlot slot;
417   do { 
418     JSObject *o = *iter;
419
420     if (o->getPropertySlot(exec, ident, slot))
421       return slot.getValue(exec, o, ident);
422     
423     ++iter;
424   } while (iter != end);
425
426   return throwUndefinedVariableError(exec, ident);
427 }
428
429 void ResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
430 {
431     size_t index = functionBody->symbolTable().get(ident.ustring().rep());
432     if (index != missingSymbolMarker())
433         new (this) LocalVarAccessNode(index);
434 }
435
436 JSValue* LocalVarAccessNode::evaluate(ExecState* exec)
437 {
438     ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
439     ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
440     return exec->localStorage()[index].value;
441 }
442
443 // ------------------------------ ElementNode ----------------------------------
444
445 void ElementNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
446 {
447     if (next)
448         nodeStack.append(next.get());
449     ASSERT(node);
450     nodeStack.append(node.get());
451 }
452
453 // ECMA 11.1.4
454 JSValue *ElementNode::evaluate(ExecState *exec)
455 {
456   JSObject *array = exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty());
457   int length = 0;
458   for (ElementNode *n = this; n; n = n->next.get()) {
459     JSValue *val = n->node->evaluate(exec);
460     KJS_CHECKEXCEPTIONVALUE
461     length += n->elision;
462     array->put(exec, length++, val);
463   }
464   return array;
465 }
466
467 // ------------------------------ ArrayNode ------------------------------------
468
469 void ArrayNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
470 {
471     if (element)
472         nodeStack.append(element.get());
473 }
474
475
476 // ECMA 11.1.4
477 JSValue *ArrayNode::evaluate(ExecState *exec)
478 {
479   JSObject *array;
480   int length;
481
482   if (element) {
483     array = static_cast<JSObject*>(element->evaluate(exec));
484     KJS_CHECKEXCEPTIONVALUE
485     length = opt ? array->get(exec, exec->propertyNames().length)->toInt32(exec) : 0;
486   } else {
487     JSValue *newArr = exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty());
488     array = static_cast<JSObject*>(newArr);
489     length = 0;
490   }
491
492   if (opt)
493     array->put(exec, exec->propertyNames().length, jsNumber(elision + length), DontEnum | DontDelete);
494
495   return array;
496 }
497
498 // ------------------------------ ObjectLiteralNode ----------------------------
499
500 void ObjectLiteralNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
501 {
502     if (list)
503         nodeStack.append(list.get());
504 }
505
506 // ECMA 11.1.5
507 JSValue *ObjectLiteralNode::evaluate(ExecState *exec)
508 {
509   if (list)
510     return list->evaluate(exec);
511
512   return exec->lexicalInterpreter()->builtinObject()->construct(exec,List::empty());
513 }
514
515 // ------------------------------ PropertyListNode -----------------------------
516
517 void PropertyListNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
518 {
519     if (next)
520         nodeStack.append(next.get());
521     nodeStack.append(node.get());
522 }
523
524 // ECMA 11.1.5
525 JSValue *PropertyListNode::evaluate(ExecState *exec)
526 {
527   JSObject *obj = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
528   
529   for (PropertyListNode *p = this; p; p = p->next.get()) {
530     JSValue *v = p->node->assign->evaluate(exec);
531     KJS_CHECKEXCEPTIONVALUE
532     
533     switch (p->node->type) {
534       case PropertyNode::Getter:
535         ASSERT(v->isObject());
536         obj->defineGetter(exec, p->node->name(), static_cast<JSObject *>(v));
537         break;
538       case PropertyNode::Setter:
539         ASSERT(v->isObject());
540         obj->defineSetter(exec, p->node->name(), static_cast<JSObject *>(v));
541         break;
542       case PropertyNode::Constant:
543         obj->put(exec, p->node->name(), v);
544         break;
545     }
546   }
547
548   return obj;
549 }
550
551 // ------------------------------ PropertyNode -----------------------------
552
553 void PropertyNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
554 {
555     nodeStack.append(assign.get());
556 }
557
558 // ECMA 11.1.5
559 JSValue *PropertyNode::evaluate(ExecState*)
560 {
561   ASSERT(false);
562   return jsNull();
563 }
564
565 // ------------------------------ BracketAccessorNode --------------------------------
566
567 void BracketAccessorNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
568 {
569     nodeStack.append(expr2.get());
570     nodeStack.append(expr1.get());
571 }
572
573 // ECMA 11.2.1a
574 JSValue *BracketAccessorNode::evaluate(ExecState *exec)
575 {
576   JSValue *v1 = expr1->evaluate(exec);
577   KJS_CHECKEXCEPTIONVALUE
578   JSValue *v2 = expr2->evaluate(exec);
579   KJS_CHECKEXCEPTIONVALUE
580   JSObject *o = v1->toObject(exec);
581   uint32_t i;
582   if (v2->getUInt32(i))
583     return o->get(exec, i);
584   return o->get(exec, Identifier(v2->toString(exec)));
585 }
586
587 // ------------------------------ DotAccessorNode --------------------------------
588
589 void DotAccessorNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
590 {
591     nodeStack.append(expr.get());
592 }
593
594 // ECMA 11.2.1b
595 JSValue *DotAccessorNode::evaluate(ExecState *exec)
596 {
597   JSValue *v = expr->evaluate(exec);
598   KJS_CHECKEXCEPTIONVALUE
599   return v->toObject(exec)->get(exec, ident);
600
601 }
602
603 // ------------------------------ ArgumentListNode -----------------------------
604
605 void ArgumentListNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
606 {
607     if (next)
608         nodeStack.append(next.get());
609     ASSERT(expr);
610     nodeStack.append(expr.get());
611 }
612
613 JSValue *ArgumentListNode::evaluate(ExecState *)
614 {
615   ASSERT(0);
616   return 0; // dummy, see evaluateList()
617 }
618
619 // ECMA 11.2.4
620 void ArgumentListNode::evaluateList(ExecState* exec, List& list)
621 {
622   for (ArgumentListNode *n = this; n; n = n->next.get()) {
623     JSValue *v = n->expr->evaluate(exec);
624     KJS_CHECKEXCEPTIONLIST
625     list.append(v);
626   }
627 }
628
629 // ------------------------------ ArgumentsNode --------------------------------
630
631 void ArgumentsNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
632 {
633     if (listNode)
634         nodeStack.append(listNode.get());
635 }
636
637 JSValue *ArgumentsNode::evaluate(ExecState *)
638 {
639   ASSERT(0);
640   return 0; // dummy, see evaluateList()
641 }
642
643 // ------------------------------ NewExprNode ----------------------------------
644
645 void NewExprNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
646 {
647     if (args)
648         nodeStack.append(args.get());
649     nodeStack.append(expr.get());
650 }
651
652 // ECMA 11.2.2
653
654 JSValue *NewExprNode::evaluate(ExecState *exec)
655 {
656   JSValue *v = expr->evaluate(exec);
657   KJS_CHECKEXCEPTIONVALUE
658
659   List argList;
660   if (args) {
661     args->evaluateList(exec, argList);
662     KJS_CHECKEXCEPTIONVALUE
663   }
664
665   if (!v->isObject()) {
666     return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, expr.get());
667   }
668
669   JSObject *constr = static_cast<JSObject*>(v);
670   if (!constr->implementsConstruct()) {
671     return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, expr.get());
672   }
673
674   return constr->construct(exec, argList);
675 }
676
677 void FunctionCallValueNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
678 {
679     nodeStack.append(args.get());
680     nodeStack.append(expr.get());
681 }
682
683 // ECMA 11.2.3
684 JSValue *FunctionCallValueNode::evaluate(ExecState *exec)
685 {
686   JSValue *v = expr->evaluate(exec);
687   KJS_CHECKEXCEPTIONVALUE
688
689   if (!v->isObject()) {
690     return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, expr.get());
691   }
692   
693   JSObject *func = static_cast<JSObject*>(v);
694
695   if (!func->implementsCall()) {
696     return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, expr.get());
697   }
698
699   List argList;
700   args->evaluateList(exec, argList);
701   KJS_CHECKEXCEPTIONVALUE
702
703   JSObject *thisObj =  exec->dynamicInterpreter()->globalObject();
704
705   return func->call(exec, thisObj, argList);
706 }
707
708 void FunctionCallResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack& nodeStack)
709 {
710     nodeStack.append(args.get());
711
712     size_t index = functionBody->symbolTable().get(ident.ustring().rep());
713     if (index != missingSymbolMarker())
714         new (this) LocalVarFunctionCallNode(index);
715 }
716
717 // ECMA 11.2.3
718 JSValue *FunctionCallResolveNode::evaluate(ExecState *exec)
719 {
720   // Check for missed optimization opportunity.
721   ASSERT(!canSkipLookup(exec, ident));
722
723   const ScopeChain& chain = exec->scopeChain();
724   ScopeChainIterator iter = chain.begin();
725   ScopeChainIterator end = chain.end();
726   
727   // we must always have something in the scope chain
728   ASSERT(iter != end);
729
730   PropertySlot slot;
731   JSObject *base;
732   do { 
733     base = *iter;
734     if (base->getPropertySlot(exec, ident, slot)) {
735       JSValue *v = slot.getValue(exec, base, ident);
736       KJS_CHECKEXCEPTIONVALUE
737         
738       if (!v->isObject()) {
739         return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
740       }
741       
742       JSObject *func = static_cast<JSObject*>(v);
743       
744       if (!func->implementsCall()) {
745         return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
746       }
747       
748       List argList;
749       args->evaluateList(exec, argList);
750       KJS_CHECKEXCEPTIONVALUE
751         
752       JSObject *thisObj = base;
753       // ECMA 11.2.3 says that in this situation the this value should be null.
754       // However, section 10.2.3 says that in the case where the value provided
755       // by the caller is null, the global object should be used. It also says
756       // that the section does not apply to interal functions, but for simplicity
757       // of implementation we use the global object anyway here. This guarantees
758       // that in host objects you always get a valid object for this.
759       if (thisObj->isActivation())
760         thisObj = exec->dynamicInterpreter()->globalObject();
761
762       return func->call(exec, thisObj, argList);
763     }
764     ++iter;
765   } while (iter != end);
766   
767   return throwUndefinedVariableError(exec, ident);
768 }
769
770 JSValue* LocalVarFunctionCallNode::evaluate(ExecState* exec)
771 {
772     ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
773     ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
774
775     JSValue* v = exec->localStorage()[index].value;
776
777     if (!v->isObject())
778         return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
779       
780     JSObject* func = static_cast<JSObject*>(v);
781     if (!func->implementsCall())
782         return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
783       
784     List argList;
785     args->evaluateList(exec, argList);
786     KJS_CHECKEXCEPTIONVALUE
787
788     return func->call(exec, exec->dynamicInterpreter()->globalObject(), argList);
789 }
790
791 void FunctionCallBracketNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
792 {
793     nodeStack.append(args.get());
794     nodeStack.append(subscript.get());
795     nodeStack.append(base.get());
796 }
797
798 // ECMA 11.2.3
799 JSValue *FunctionCallBracketNode::evaluate(ExecState *exec)
800 {
801   JSValue *baseVal = base->evaluate(exec);
802   KJS_CHECKEXCEPTIONVALUE
803
804   JSValue *subscriptVal = subscript->evaluate(exec);
805
806   JSObject *baseObj = baseVal->toObject(exec);
807   uint32_t i;
808   PropertySlot slot;
809
810   JSValue *funcVal;
811   if (subscriptVal->getUInt32(i)) {
812     if (baseObj->getPropertySlot(exec, i, slot))
813       funcVal = slot.getValue(exec, baseObj, i);
814     else
815       funcVal = jsUndefined();
816   } else {
817     Identifier ident(subscriptVal->toString(exec));
818     if (baseObj->getPropertySlot(exec, ident, slot))
819       funcVal = baseObj->get(exec, ident);
820     else
821       funcVal = jsUndefined();
822   }
823
824   KJS_CHECKEXCEPTIONVALUE
825   
826   if (!funcVal->isObject()) {
827     return throwError(exec, TypeError, "Value %s (result of expression %s[%s]) is not object.", funcVal, base.get(), subscript.get());
828   }
829   
830   JSObject *func = static_cast<JSObject*>(funcVal);
831
832   if (!func->implementsCall()) {
833     return throwError(exec, TypeError, "Object %s (result of expression %s[%s]) does not allow calls.", funcVal, base.get(), subscript.get());
834   }
835
836   List argList;
837   args->evaluateList(exec, argList);
838   KJS_CHECKEXCEPTIONVALUE
839
840   JSObject *thisObj = baseObj;
841   ASSERT(thisObj);
842   ASSERT(thisObj->isObject());
843   ASSERT(!thisObj->isActivation());
844
845   return func->call(exec, thisObj, argList);
846 }
847
848 static const char *dotExprNotAnObjectString() KJS_FAST_CALL;
849 static const char *dotExprNotAnObjectString()
850 {
851   return "Value %s (result of expression %s.%s) is not object.";
852 }
853
854 static const char *dotExprDoesNotAllowCallsString() KJS_FAST_CALL;
855 static const char *dotExprDoesNotAllowCallsString()
856 {
857   return "Object %s (result of expression %s.%s) does not allow calls.";
858 }
859
860 void FunctionCallDotNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
861 {
862     nodeStack.append(args.get());
863     nodeStack.append(base.get());
864 }
865
866 // ECMA 11.2.3
867 JSValue *FunctionCallDotNode::evaluate(ExecState *exec)
868 {
869   JSValue *baseVal = base->evaluate(exec);
870   KJS_CHECKEXCEPTIONVALUE
871
872   JSObject *baseObj = baseVal->toObject(exec);
873   PropertySlot slot;
874   JSValue *funcVal = baseObj->getPropertySlot(exec, ident, slot) ? slot.getValue(exec, baseObj, ident) : jsUndefined();
875   KJS_CHECKEXCEPTIONVALUE
876
877   if (!funcVal->isObject())
878     return throwError(exec, TypeError, dotExprNotAnObjectString(), funcVal, base.get(), ident);
879   
880   JSObject *func = static_cast<JSObject*>(funcVal);
881
882   if (!func->implementsCall())
883     return throwError(exec, TypeError, dotExprDoesNotAllowCallsString(), funcVal, base.get(), ident);
884
885   List argList;
886   args->evaluateList(exec, argList);
887   KJS_CHECKEXCEPTIONVALUE
888
889   JSObject *thisObj = baseObj;
890   ASSERT(thisObj);
891   ASSERT(thisObj->isObject());
892   ASSERT(!thisObj->isActivation());
893
894   return func->call(exec, thisObj, argList);
895 }
896
897 // ECMA 11.3
898
899 // ------------------------------ PostfixResolveNode ----------------------------------
900
901 // Increment
902 void PostIncResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
903 {
904     size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
905     if (index != missingSymbolMarker())
906         new (this) PostIncLocalVarNode(index);
907 }
908
909 JSValue *PostIncResolveNode::evaluate(ExecState *exec)
910 {
911   // Check for missed optimization opportunity.
912   ASSERT(!canSkipLookup(exec, m_ident));
913
914   const ScopeChain& chain = exec->scopeChain();
915   ScopeChainIterator iter = chain.begin();
916   ScopeChainIterator end = chain.end();
917   
918   // we must always have something in the scope chain
919   ASSERT(iter != end);
920
921   PropertySlot slot;
922   JSObject *base;
923   do { 
924     base = *iter;
925     if (base->getPropertySlot(exec, m_ident, slot)) {
926         JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
927         base->put(exec, m_ident, jsNumber(v->toNumber(exec) + 1));
928         return v;
929     }
930
931     ++iter;
932   } while (iter != end);
933
934   return throwUndefinedVariableError(exec, m_ident);
935 }
936
937 void PostIncResolveNode::optimizeForUnnecessaryResult()
938 {
939     new (this) PreIncResolveNode(PlacementNewAdopt);
940 }
941     
942 JSValue* PostIncLocalVarNode::evaluate(ExecState* exec)
943 {
944     ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
945     ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
946
947     JSValue** slot = &exec->localStorage()[m_index].value;
948     JSValue* v = (*slot)->toJSNumber(exec);
949     *slot = jsNumber(v->toNumber(exec) + 1);
950     return v;
951 }
952
953 void PostIncLocalVarNode::optimizeForUnnecessaryResult()
954 {
955     new (this) PreIncLocalVarNode(m_index);
956 }
957
958
959 // Decrement
960 void PostDecResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
961 {
962     size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
963     if (index != missingSymbolMarker())
964         new (this) PostDecLocalVarNode(index);
965 }
966
967 JSValue *PostDecResolveNode::evaluate(ExecState *exec)
968 {
969   // Check for missed optimization opportunity.
970   ASSERT(!canSkipLookup(exec, m_ident));
971
972   const ScopeChain& chain = exec->scopeChain();
973   ScopeChainIterator iter = chain.begin();
974   ScopeChainIterator end = chain.end();
975   
976   // we must always have something in the scope chain
977   ASSERT(iter != end);
978
979   PropertySlot slot;
980   JSObject *base;
981   do { 
982     base = *iter;
983     if (base->getPropertySlot(exec, m_ident, slot)) {
984         JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
985         base->put(exec, m_ident, jsNumber(v->toNumber(exec) - 1));
986         return v;
987     }
988
989     ++iter;
990   } while (iter != end);
991
992   return throwUndefinedVariableError(exec, m_ident);
993 }
994     
995 void PostDecResolveNode::optimizeForUnnecessaryResult()
996 {
997     new (this) PreDecResolveNode(PlacementNewAdopt);
998 }
999     
1000 JSValue* PostDecLocalVarNode::evaluate(ExecState* exec)
1001 {
1002     ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
1003     ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
1004
1005     JSValue** slot = &exec->localStorage()[m_index].value;
1006     JSValue* v = (*slot)->toJSNumber(exec);
1007     *slot = jsNumber(v->toNumber(exec) - 1);
1008     return v;
1009 }
1010
1011 void PostDecLocalVarNode::optimizeForUnnecessaryResult()
1012 {
1013     new (this) PreDecLocalVarNode(m_index);
1014 }
1015     
1016 // ------------------------------ PostfixBracketNode ----------------------------------
1017
1018 void PostfixBracketNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1019 {
1020     nodeStack.append(m_subscript.get());
1021     nodeStack.append(m_base.get());
1022 }
1023
1024 JSValue *PostIncBracketNode::evaluate(ExecState *exec)
1025 {
1026   JSValue *baseValue = m_base->evaluate(exec);
1027   KJS_CHECKEXCEPTIONVALUE
1028   JSValue *subscript = m_subscript->evaluate(exec);
1029   KJS_CHECKEXCEPTIONVALUE
1030
1031   JSObject *base = baseValue->toObject(exec);
1032
1033   uint32_t propertyIndex;
1034   if (subscript->getUInt32(propertyIndex)) {
1035     PropertySlot slot;
1036     JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1037     KJS_CHECKEXCEPTIONVALUE
1038
1039     JSValue* v2 = v->toJSNumber(exec);
1040     base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) + 1));
1041         
1042     return v2;
1043   }
1044
1045   Identifier propertyName(subscript->toString(exec));
1046   PropertySlot slot;
1047   JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1048   KJS_CHECKEXCEPTIONVALUE
1049
1050   JSValue* v2 = v->toJSNumber(exec);
1051   base->put(exec, propertyName, jsNumber(v2->toNumber(exec) + 1));
1052   return v2;
1053 }
1054
1055 JSValue *PostDecBracketNode::evaluate(ExecState *exec)
1056 {
1057   JSValue *baseValue = m_base->evaluate(exec);
1058   KJS_CHECKEXCEPTIONVALUE
1059   JSValue *subscript = m_subscript->evaluate(exec);
1060   KJS_CHECKEXCEPTIONVALUE
1061
1062   JSObject *base = baseValue->toObject(exec);
1063
1064   uint32_t propertyIndex;
1065   if (subscript->getUInt32(propertyIndex)) {
1066     PropertySlot slot;
1067     JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1068     KJS_CHECKEXCEPTIONVALUE
1069
1070     JSValue* v2 = v->toJSNumber(exec);
1071     base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) - 1));
1072     return v2;
1073   }
1074
1075   Identifier propertyName(subscript->toString(exec));
1076   PropertySlot slot;
1077   JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1078   KJS_CHECKEXCEPTIONVALUE
1079
1080   JSValue* v2 = v->toJSNumber(exec);
1081   base->put(exec, propertyName, jsNumber(v2->toNumber(exec) - 1));
1082   return v2;
1083 }
1084
1085 // ------------------------------ PostfixDotNode ----------------------------------
1086
1087 void PostfixDotNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1088 {
1089     nodeStack.append(m_base.get());
1090 }
1091
1092 JSValue *PostIncDotNode::evaluate(ExecState *exec)
1093 {
1094   JSValue *baseValue = m_base->evaluate(exec);
1095   KJS_CHECKEXCEPTIONVALUE
1096   JSObject *base = baseValue->toObject(exec);
1097
1098   PropertySlot slot;
1099   JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1100   KJS_CHECKEXCEPTIONVALUE
1101
1102   JSValue* v2 = v->toJSNumber(exec);
1103   base->put(exec, m_ident, jsNumber(v2->toNumber(exec) + 1));
1104   return v2;
1105 }
1106
1107 JSValue *PostDecDotNode::evaluate(ExecState *exec)
1108 {
1109   JSValue *baseValue = m_base->evaluate(exec);
1110   KJS_CHECKEXCEPTIONVALUE
1111   JSObject *base = baseValue->toObject(exec);
1112
1113   PropertySlot slot;
1114   JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1115   KJS_CHECKEXCEPTIONVALUE
1116
1117   JSValue* v2 = v->toJSNumber(exec);
1118   base->put(exec, m_ident, jsNumber(v2->toNumber(exec) - 1));
1119   return v2;
1120 }
1121
1122 // ------------------------------ PostfixErrorNode -----------------------------------
1123
1124 JSValue* PostfixErrorNode::evaluate(ExecState* exec)
1125 {
1126     throwError(exec, ReferenceError, "Postfix %s operator applied to value that is not a reference.",
1127         m_oper == OpPlusPlus ? "++" : "--");
1128     handleException(exec);
1129     return jsUndefined();
1130 }
1131
1132 // ------------------------------ DeleteResolveNode -----------------------------------
1133
1134 void DeleteResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
1135 {
1136     size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
1137     if (index != missingSymbolMarker())
1138         new (this) LocalVarDeleteNode();
1139 }
1140
1141 // ECMA 11.4.1
1142
1143 JSValue *DeleteResolveNode::evaluate(ExecState *exec)
1144 {
1145   // Check for missed optimization opportunity.
1146   ASSERT(!canSkipLookup(exec, m_ident));
1147
1148   const ScopeChain& chain = exec->scopeChain();
1149   ScopeChainIterator iter = chain.begin();
1150   ScopeChainIterator end = chain.end();
1151   
1152   // we must always have something in the scope chain
1153   ASSERT(iter != end);
1154
1155   PropertySlot slot;
1156   JSObject *base;
1157   do { 
1158     base = *iter;
1159     if (base->getPropertySlot(exec, m_ident, slot)) {
1160         return jsBoolean(base->deleteProperty(exec, m_ident));
1161     }
1162
1163     ++iter;
1164   } while (iter != end);
1165
1166   return jsBoolean(true);
1167 }
1168
1169 JSValue* LocalVarDeleteNode::evaluate(ExecState*)
1170 {
1171     return jsBoolean(false);
1172 }
1173
1174 // ------------------------------ DeleteBracketNode -----------------------------------
1175
1176 void DeleteBracketNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1177 {
1178     nodeStack.append(m_subscript.get());
1179     nodeStack.append(m_base.get());
1180 }
1181
1182 JSValue *DeleteBracketNode::evaluate(ExecState *exec)
1183 {
1184   JSValue *baseValue = m_base->evaluate(exec);
1185   KJS_CHECKEXCEPTIONVALUE
1186   JSValue *subscript = m_subscript->evaluate(exec);
1187   KJS_CHECKEXCEPTIONVALUE
1188
1189   JSObject *base = baseValue->toObject(exec);
1190
1191   uint32_t propertyIndex;
1192   if (subscript->getUInt32(propertyIndex))
1193       return jsBoolean(base->deleteProperty(exec, propertyIndex));
1194
1195   Identifier propertyName(subscript->toString(exec));
1196   return jsBoolean(base->deleteProperty(exec, propertyName));
1197 }
1198
1199 // ------------------------------ DeleteDotNode -----------------------------------
1200
1201 void DeleteDotNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1202 {
1203     nodeStack.append(m_base.get());
1204 }
1205
1206 JSValue *DeleteDotNode::evaluate(ExecState *exec)
1207 {
1208   JSValue *baseValue = m_base->evaluate(exec);
1209   JSObject *base = baseValue->toObject(exec);
1210   KJS_CHECKEXCEPTIONVALUE
1211
1212   return jsBoolean(base->deleteProperty(exec, m_ident));
1213 }
1214
1215 // ------------------------------ DeleteValueNode -----------------------------------
1216
1217 void DeleteValueNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1218 {
1219     nodeStack.append(m_expr.get());
1220 }
1221
1222 JSValue *DeleteValueNode::evaluate(ExecState *exec)
1223 {
1224   m_expr->evaluate(exec);
1225   KJS_CHECKEXCEPTIONVALUE
1226
1227   // delete on a non-location expression ignores the value and returns true
1228   return jsBoolean(true);
1229 }
1230
1231 // ------------------------------ VoidNode -------------------------------------
1232
1233 void VoidNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1234 {
1235     nodeStack.append(expr.get());
1236 }
1237
1238 // ECMA 11.4.2
1239 JSValue *VoidNode::evaluate(ExecState *exec)
1240 {
1241   expr->evaluate(exec);
1242   KJS_CHECKEXCEPTIONVALUE
1243
1244   return jsUndefined();
1245 }
1246
1247 // ECMA 11.4.3
1248
1249 // ------------------------------ TypeOfValueNode -----------------------------------
1250
1251 void TypeOfValueNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1252 {
1253     nodeStack.append(m_expr.get());
1254 }
1255
1256 static JSValue *typeStringForValue(JSValue *v) KJS_FAST_CALL;
1257 static JSValue *typeStringForValue(JSValue *v)
1258 {
1259     switch (v->type()) {
1260     case UndefinedType:
1261         return jsString("undefined");
1262     case NullType:
1263         return jsString("object");
1264     case BooleanType:
1265         return jsString("boolean");
1266     case NumberType:
1267         return jsString("number");
1268     case StringType:
1269         return jsString("string");
1270     default:
1271         if (v->isObject()) {
1272             // Return "undefined" for objects that should be treated
1273             // as null when doing comparisons.
1274             if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
1275                 return jsString("undefined");            
1276             else if (static_cast<JSObject*>(v)->implementsCall())
1277                 return jsString("function");
1278         }
1279         
1280         return jsString("object");
1281     }
1282 }
1283
1284 void TypeOfResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
1285 {
1286     size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
1287     if (index != missingSymbolMarker())
1288         new (this) LocalVarTypeOfNode(index);
1289 }
1290
1291 JSValue* LocalVarTypeOfNode::evaluate(ExecState* exec)
1292 {
1293     ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
1294     ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
1295
1296     return typeStringForValue(exec->localStorage()[m_index].value);
1297 }
1298
1299 JSValue *TypeOfResolveNode::evaluate(ExecState *exec)
1300 {
1301   const ScopeChain& chain = exec->scopeChain();
1302   ScopeChainIterator iter = chain.begin();
1303   ScopeChainIterator end = chain.end();
1304   
1305   // we must always have something in the scope chain
1306   ASSERT(iter != end);
1307
1308   PropertySlot slot;
1309   JSObject *base;
1310   do { 
1311     base = *iter;
1312     if (base->getPropertySlot(exec, m_ident, slot)) {
1313         JSValue *v = slot.getValue(exec, base, m_ident);
1314         return typeStringForValue(v);
1315     }
1316
1317     ++iter;
1318   } while (iter != end);
1319
1320   return jsString("undefined");
1321 }
1322
1323 // ------------------------------ TypeOfValueNode -----------------------------------
1324
1325 JSValue *TypeOfValueNode::evaluate(ExecState *exec)
1326 {
1327   JSValue *v = m_expr->evaluate(exec);
1328   KJS_CHECKEXCEPTIONVALUE
1329
1330   return typeStringForValue(v);
1331 }
1332
1333 // ECMA 11.4.4 and 11.4.5
1334
1335 // ------------------------------ PrefixResolveNode ----------------------------------
1336
1337 void PreIncResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
1338 {
1339     size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
1340     if (index != missingSymbolMarker())
1341         new (this) PreIncLocalVarNode(index);
1342 }
1343
1344 JSValue* PreIncLocalVarNode::evaluate(ExecState* exec)
1345 {
1346     ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
1347     ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
1348     JSValue** slot = &exec->localStorage()[m_index].value;
1349
1350     double n = (*slot)->toNumber(exec);
1351     JSValue* n2 = jsNumber(n + 1);
1352     *slot = n2;
1353     return n2;
1354 }
1355
1356 JSValue *PreIncResolveNode::evaluate(ExecState *exec)
1357 {
1358   const ScopeChain& chain = exec->scopeChain();
1359   ScopeChainIterator iter = chain.begin();
1360   ScopeChainIterator end = chain.end();
1361   
1362   // we must always have something in the scope chain
1363   ASSERT(iter != end);
1364
1365   PropertySlot slot;
1366   JSObject *base;
1367   do { 
1368     base = *iter;
1369     if (base->getPropertySlot(exec, m_ident, slot)) {
1370         JSValue *v = slot.getValue(exec, base, m_ident);
1371
1372         double n = v->toNumber(exec);
1373         JSValue *n2 = jsNumber(n + 1);
1374         base->put(exec, m_ident, n2);
1375
1376         return n2;
1377     }
1378
1379     ++iter;
1380   } while (iter != end);
1381
1382   return throwUndefinedVariableError(exec, m_ident);
1383 }
1384
1385 void PreDecResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack&)
1386 {
1387     size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
1388     if (index != missingSymbolMarker())
1389         new (this) PreDecLocalVarNode(index);
1390 }
1391
1392 JSValue* PreDecLocalVarNode::evaluate(ExecState* exec)
1393 {
1394     ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
1395     ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
1396     JSValue** slot = &exec->localStorage()[m_index].value;
1397
1398     double n = (*slot)->toNumber(exec);
1399     JSValue* n2 = jsNumber(n - 1);
1400     *slot = n2;
1401     return n2;
1402 }
1403
1404 JSValue *PreDecResolveNode::evaluate(ExecState *exec)
1405 {
1406   const ScopeChain& chain = exec->scopeChain();
1407   ScopeChainIterator iter = chain.begin();
1408   ScopeChainIterator end = chain.end();
1409   
1410   // we must always have something in the scope chain
1411   ASSERT(iter != end);
1412
1413   PropertySlot slot;
1414   JSObject *base;
1415   do { 
1416     base = *iter;
1417     if (base->getPropertySlot(exec, m_ident, slot)) {
1418         JSValue *v = slot.getValue(exec, base, m_ident);
1419
1420         double n = v->toNumber(exec);
1421         JSValue *n2 = jsNumber(n - 1);
1422         base->put(exec, m_ident, n2);
1423
1424         return n2;
1425     }
1426
1427     ++iter;
1428   } while (iter != end);
1429
1430   return throwUndefinedVariableError(exec, m_ident);
1431 }
1432
1433 // ------------------------------ PrefixBracketNode ----------------------------------
1434
1435 void PrefixBracketNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1436 {
1437     nodeStack.append(m_subscript.get());
1438     nodeStack.append(m_base.get());
1439 }
1440
1441 JSValue *PreIncBracketNode::evaluate(ExecState *exec)
1442 {
1443   JSValue *baseValue = m_base->evaluate(exec);
1444   KJS_CHECKEXCEPTIONVALUE
1445   JSValue *subscript = m_subscript->evaluate(exec);
1446   KJS_CHECKEXCEPTIONVALUE
1447
1448   JSObject *base = baseValue->toObject(exec);
1449
1450   uint32_t propertyIndex;
1451   if (subscript->getUInt32(propertyIndex)) {
1452     PropertySlot slot;
1453     JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1454     KJS_CHECKEXCEPTIONVALUE
1455
1456     JSValue *n2 = jsNumber(v->toNumber(exec) + 1);
1457     base->put(exec, propertyIndex, n2);
1458
1459     return n2;
1460   }
1461
1462   Identifier propertyName(subscript->toString(exec));
1463   PropertySlot slot;
1464   JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1465   KJS_CHECKEXCEPTIONVALUE
1466
1467   JSValue *n2 = jsNumber(v->toNumber(exec) + 1);
1468   base->put(exec, propertyName, n2);
1469
1470   return n2;
1471 }
1472
1473 JSValue *PreDecBracketNode::evaluate(ExecState *exec)
1474 {
1475   JSValue *baseValue = m_base->evaluate(exec);
1476   KJS_CHECKEXCEPTIONVALUE
1477   JSValue *subscript = m_subscript->evaluate(exec);
1478   KJS_CHECKEXCEPTIONVALUE
1479
1480   JSObject *base = baseValue->toObject(exec);
1481
1482   uint32_t propertyIndex;
1483   if (subscript->getUInt32(propertyIndex)) {
1484     PropertySlot slot;
1485     JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1486     KJS_CHECKEXCEPTIONVALUE
1487
1488     JSValue *n2 = jsNumber(v->toNumber(exec) - 1);
1489     base->put(exec, propertyIndex, n2);
1490
1491     return n2;
1492   }
1493
1494   Identifier propertyName(subscript->toString(exec));
1495   PropertySlot slot;
1496   JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1497   KJS_CHECKEXCEPTIONVALUE
1498
1499   JSValue *n2 = jsNumber(v->toNumber(exec) - 1);
1500   base->put(exec, propertyName, n2);
1501
1502   return n2;
1503 }
1504
1505 // ------------------------------ PrefixDotNode ----------------------------------
1506
1507 void PrefixDotNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1508 {
1509     nodeStack.append(m_base.get());
1510 }
1511
1512 JSValue *PreIncDotNode::evaluate(ExecState *exec)
1513 {
1514   JSValue *baseValue = m_base->evaluate(exec);
1515   KJS_CHECKEXCEPTIONVALUE
1516   JSObject *base = baseValue->toObject(exec);
1517
1518   PropertySlot slot;
1519   JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1520   KJS_CHECKEXCEPTIONVALUE
1521
1522   double n = v->toNumber(exec);
1523   JSValue *n2 = jsNumber(n + 1);
1524   base->put(exec, m_ident, n2);
1525
1526   return n2;
1527 }
1528
1529 JSValue *PreDecDotNode::evaluate(ExecState *exec)
1530 {
1531   JSValue *baseValue = m_base->evaluate(exec);
1532   KJS_CHECKEXCEPTIONVALUE
1533   JSObject *base = baseValue->toObject(exec);
1534
1535   PropertySlot slot;
1536   JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1537   KJS_CHECKEXCEPTIONVALUE
1538
1539   double n = v->toNumber(exec);
1540   JSValue *n2 = jsNumber(n - 1);
1541   base->put(exec, m_ident, n2);
1542
1543   return n2;
1544 }
1545
1546 // ------------------------------ PrefixErrorNode -----------------------------------
1547
1548 JSValue* PrefixErrorNode::evaluate(ExecState* exec)
1549 {
1550     throwError(exec, ReferenceError, "Prefix %s operator applied to value that is not a reference.",
1551         m_oper == OpPlusPlus ? "++" : "--");
1552     handleException(exec);
1553     return jsUndefined();
1554 }
1555
1556 // ------------------------------ UnaryPlusNode --------------------------------
1557
1558 void UnaryPlusNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1559 {
1560     nodeStack.append(expr.get());
1561 }
1562
1563 // ECMA 11.4.6
1564 JSValue *UnaryPlusNode::evaluate(ExecState *exec)
1565 {
1566   JSValue *v = expr->evaluate(exec);
1567   KJS_CHECKEXCEPTIONVALUE
1568
1569   return v->toJSNumber(exec);
1570 }
1571
1572 // ------------------------------ NegateNode -----------------------------------
1573
1574 void NegateNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1575 {
1576     nodeStack.append(expr.get());
1577 }
1578
1579 // ECMA 11.4.7
1580 JSValue *NegateNode::evaluate(ExecState *exec)
1581 {
1582   JSValue *v = expr->evaluate(exec);
1583   KJS_CHECKEXCEPTIONVALUE
1584
1585   double n = v->toNumber(exec);
1586   return jsNumber(-n);
1587 }
1588
1589 // ------------------------------ BitwiseNotNode -------------------------------
1590
1591 void BitwiseNotNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1592 {
1593     nodeStack.append(expr.get());
1594 }
1595
1596 // ECMA 11.4.8
1597 JSValue *BitwiseNotNode::evaluate(ExecState *exec)
1598 {
1599   JSValue *v = expr->evaluate(exec);
1600   KJS_CHECKEXCEPTIONVALUE
1601   return jsNumber(~v->toInt32(exec));
1602 }
1603
1604 // ------------------------------ LogicalNotNode -------------------------------
1605
1606 void LogicalNotNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1607 {
1608     nodeStack.append(expr.get());
1609 }
1610
1611 // ECMA 11.4.9
1612 JSValue *LogicalNotNode::evaluate(ExecState *exec)
1613 {
1614   JSValue *v = expr->evaluate(exec);
1615   KJS_CHECKEXCEPTIONVALUE
1616   return jsBoolean(!v->toBoolean(exec));
1617 }
1618
1619 // ------------------------------ Multiplicative Nodes -----------------------------------
1620
1621 void MultNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1622 {
1623     nodeStack.append(term1.get());
1624     nodeStack.append(term2.get());
1625 }
1626
1627 // ECMA 11.5.1
1628 JSValue *MultNode::evaluate(ExecState *exec)
1629 {
1630     JSValue *v1 = term1->evaluate(exec);
1631     KJS_CHECKEXCEPTIONVALUE
1632         
1633     JSValue *v2 = term2->evaluate(exec);
1634     KJS_CHECKEXCEPTIONVALUE
1635
1636     return jsNumber(v1->toNumber(exec) * v2->toNumber(exec));
1637 }
1638
1639 void DivNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1640 {
1641     nodeStack.append(term1.get());
1642     nodeStack.append(term2.get());
1643 }
1644
1645 // ECMA 11.5.2
1646 JSValue *DivNode::evaluate(ExecState *exec)
1647 {
1648     JSValue *v1 = term1->evaluate(exec);
1649     KJS_CHECKEXCEPTIONVALUE
1650         
1651     JSValue *v2 = term2->evaluate(exec);
1652     KJS_CHECKEXCEPTIONVALUE
1653
1654     return jsNumber(v1->toNumber(exec) / v2->toNumber(exec));
1655 }
1656
1657 void ModNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1658 {
1659     nodeStack.append(term1.get());
1660     nodeStack.append(term2.get());
1661 }
1662
1663 // ECMA 11.5.3
1664 JSValue *ModNode::evaluate(ExecState *exec)
1665 {
1666     JSValue *v1 = term1->evaluate(exec);
1667     KJS_CHECKEXCEPTIONVALUE
1668         
1669     JSValue *v2 = term2->evaluate(exec);
1670     KJS_CHECKEXCEPTIONVALUE
1671
1672     return jsNumber(fmod(v1->toNumber(exec), v2->toNumber(exec)));
1673 }
1674
1675 // ------------------------------ Additive Nodes --------------------------------------
1676
1677 static JSValue* throwOutOfMemoryError(ExecState* exec)
1678 {
1679     JSObject* error = Error::create(exec, GeneralError, "Out of memory");
1680     exec->setException(error);
1681     return error;
1682 }
1683
1684 // ECMA 11.6
1685 static JSValue* addSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
1686 {
1687     // exception for the Date exception in defaultValue()
1688     JSValue *p1 = v1->toPrimitive(exec, UnspecifiedType);
1689     JSValue *p2 = v2->toPrimitive(exec, UnspecifiedType);
1690     
1691     if (p1->isString() || p2->isString()) {
1692         UString value = p1->toString(exec) + p2->toString(exec);
1693         if (value.isNull())
1694             return throwOutOfMemoryError(exec);
1695         return jsString(value);
1696     }
1697     
1698     return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
1699 }
1700
1701 // Fast-path choices here are based on frequency data from SunSpider:
1702 //    <times> Add case: <t1> <t2>
1703 //    ---------------------------
1704 //    5627160 Add case: 1 1
1705 //    247427  Add case: 5 5
1706 //    20901   Add case: 5 6
1707 //    13978   Add case: 5 1
1708 //    4000    Add case: 1 5
1709 //    1       Add case: 3 5
1710
1711 static inline JSValue* add(ExecState* exec, JSValue* v1, JSValue *v2)
1712 {
1713     JSType t1 = v1->type();
1714     JSType t2 = v2->type();
1715     const unsigned bothTypes = (t1 << 3) | t2;
1716     
1717     if (bothTypes == ((NumberType << 3) | NumberType))
1718         return jsNumber(v1->toNumber(exec) + v2->toNumber(exec));
1719     else if (bothTypes == ((StringType << 3) | StringType)) {
1720         UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
1721         if (value.isNull())
1722             return throwOutOfMemoryError(exec);
1723         return jsString(value);
1724     }
1725     
1726     // All other cases are pretty uncommon
1727     return addSlowCase(exec, v1, v2);
1728 }
1729
1730 void AddNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1731 {
1732     nodeStack.append(term1.get());
1733     nodeStack.append(term2.get());
1734 }
1735
1736 // ECMA 11.6.1
1737 JSValue *AddNode::evaluate(ExecState *exec)
1738 {
1739   JSValue *v1 = term1->evaluate(exec);
1740   KJS_CHECKEXCEPTIONVALUE
1741
1742   JSValue *v2 = term2->evaluate(exec);
1743   KJS_CHECKEXCEPTIONVALUE
1744
1745   return add(exec, v1, v2);
1746 }
1747
1748 void SubNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1749 {
1750     nodeStack.append(term1.get());
1751     nodeStack.append(term2.get());
1752 }
1753
1754 // ECMA 11.6.2
1755 JSValue *SubNode::evaluate(ExecState *exec)
1756 {
1757     JSValue *v1 = term1->evaluate(exec);
1758     KJS_CHECKEXCEPTIONVALUE
1759         
1760     JSValue *v2 = term2->evaluate(exec);
1761     KJS_CHECKEXCEPTIONVALUE
1762         
1763     return jsNumber(v1->toNumber(exec) - v2->toNumber(exec));
1764 }
1765
1766 // ------------------------------ Shift Nodes ------------------------------------
1767
1768 void LeftShiftNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1769 {
1770     nodeStack.append(term1.get());
1771     nodeStack.append(term2.get());
1772 }
1773
1774 // ECMA 11.7.1
1775 JSValue *LeftShiftNode::evaluate(ExecState *exec)
1776 {
1777   JSValue *v1 = term1->evaluate(exec);
1778   KJS_CHECKEXCEPTIONVALUE
1779   JSValue *v2 = term2->evaluate(exec);
1780   KJS_CHECKEXCEPTIONVALUE
1781   unsigned int i2 = v2->toUInt32(exec);
1782   i2 &= 0x1f;
1783
1784   return jsNumber(v1->toInt32(exec) << i2);
1785 }
1786
1787 void RightShiftNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1788 {
1789     nodeStack.append(term1.get());
1790     nodeStack.append(term2.get());
1791 }
1792
1793 // ECMA 11.7.2
1794 JSValue *RightShiftNode::evaluate(ExecState *exec)
1795 {
1796   JSValue *v1 = term1->evaluate(exec);
1797   KJS_CHECKEXCEPTIONVALUE
1798   JSValue *v2 = term2->evaluate(exec);
1799   KJS_CHECKEXCEPTIONVALUE
1800   unsigned int i2 = v2->toUInt32(exec);
1801   i2 &= 0x1f;
1802
1803   return jsNumber(v1->toInt32(exec) >> i2);
1804 }
1805
1806 void UnsignedRightShiftNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1807 {
1808     nodeStack.append(term1.get());
1809     nodeStack.append(term2.get());
1810 }
1811
1812 // ECMA 11.7.3
1813 JSValue *UnsignedRightShiftNode::evaluate(ExecState *exec)
1814 {
1815   JSValue *v1 = term1->evaluate(exec);
1816   KJS_CHECKEXCEPTIONVALUE
1817   JSValue *v2 = term2->evaluate(exec);
1818   KJS_CHECKEXCEPTIONVALUE
1819   unsigned int i2 = v2->toUInt32(exec);
1820   i2 &= 0x1f;
1821
1822   return jsNumber(v1->toUInt32(exec) >> i2);
1823 }
1824
1825 // ------------------------------ Relational Nodes -------------------------------
1826
1827 static inline JSValue* lessThan(ExecState *exec, JSValue* v1, JSValue* v2) 
1828 {
1829     double n1;
1830     double n2;
1831     bool wasNotString1 = v1->getPrimitiveNumber(exec, n1);
1832     bool wasNotString2 = v2->getPrimitiveNumber(exec, n2);
1833     
1834     if (wasNotString1 | wasNotString2)
1835         return jsBoolean(n1 < n2);
1836
1837     return jsBoolean(v1->toString(exec) < v2->toString(exec));
1838 }
1839
1840 static inline JSValue* lessThanEq(ExecState *exec, JSValue* v1, JSValue* v2) 
1841 {
1842     double n1;
1843     double n2;
1844     bool wasNotString1 = v1->getPrimitiveNumber(exec, n1);
1845     bool wasNotString2 = v2->getPrimitiveNumber(exec, n2);
1846     
1847     if (wasNotString1 | wasNotString2)
1848         return jsBoolean(n1 <= n2);
1849
1850     return jsBoolean(!(v2->toString(exec) < v1->toString(exec)));
1851 }
1852
1853 void LessNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1854 {
1855     nodeStack.append(expr2.get());
1856     nodeStack.append(expr1.get());
1857 }
1858
1859 // ECMA 11.8.1
1860 JSValue *LessNode::evaluate(ExecState *exec)
1861 {
1862   JSValue *v1 = expr1->evaluate(exec);
1863   KJS_CHECKEXCEPTIONVALUE
1864   JSValue *v2 = expr2->evaluate(exec);
1865   KJS_CHECKEXCEPTIONVALUE
1866   return lessThan(exec, v1, v2);
1867 }
1868
1869 void GreaterNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1870 {
1871     nodeStack.append(expr2.get());
1872     nodeStack.append(expr1.get());
1873 }
1874
1875 // ECMA 11.8.2
1876 JSValue *GreaterNode::evaluate(ExecState *exec)
1877 {
1878   JSValue *v1 = expr1->evaluate(exec);
1879   KJS_CHECKEXCEPTIONVALUE
1880   JSValue *v2 = expr2->evaluate(exec);
1881   KJS_CHECKEXCEPTIONVALUE
1882   return lessThan(exec, v2, v1);
1883 }
1884
1885 void LessEqNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1886 {
1887     nodeStack.append(expr2.get());
1888     nodeStack.append(expr1.get());
1889 }
1890
1891 // ECMA 11.8.3
1892 JSValue *LessEqNode::evaluate(ExecState *exec)
1893 {
1894   JSValue *v1 = expr1->evaluate(exec);
1895   KJS_CHECKEXCEPTIONVALUE
1896   JSValue *v2 = expr2->evaluate(exec);
1897   KJS_CHECKEXCEPTIONVALUE
1898   return lessThanEq(exec, v1, v2);
1899 }
1900
1901 void GreaterEqNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1902 {
1903     nodeStack.append(expr2.get());
1904     nodeStack.append(expr1.get());
1905 }
1906
1907 // ECMA 11.8.4
1908 JSValue *GreaterEqNode::evaluate(ExecState *exec)
1909 {
1910   JSValue *v1 = expr1->evaluate(exec);
1911   KJS_CHECKEXCEPTIONVALUE
1912   JSValue *v2 = expr2->evaluate(exec);
1913   KJS_CHECKEXCEPTIONVALUE
1914   return lessThanEq(exec, v2, v1);
1915 }
1916
1917 void InstanceOfNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1918 {
1919     nodeStack.append(expr2.get());
1920     nodeStack.append(expr1.get());
1921 }
1922
1923 // ECMA 11.8.6
1924 JSValue *InstanceOfNode::evaluate(ExecState *exec)
1925 {
1926   JSValue *v1 = expr1->evaluate(exec);
1927   KJS_CHECKEXCEPTIONVALUE
1928   JSValue *v2 = expr2->evaluate(exec);
1929   KJS_CHECKEXCEPTIONVALUE
1930
1931   if (!v2->isObject())
1932       return throwError(exec,  TypeError,
1933                           "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, expr2.get());
1934
1935   JSObject *o2(static_cast<JSObject*>(v2));
1936   if (!o2->implementsHasInstance())
1937       // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
1938       // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
1939       // property. It seems that all object have the property, but not all implement it, so in this
1940       // case we return false (consistent with mozilla)
1941       return jsBoolean(false);
1942   return jsBoolean(o2->hasInstance(exec, v1));
1943 }
1944
1945 void InNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1946 {
1947     nodeStack.append(expr2.get());
1948     nodeStack.append(expr1.get());
1949 }
1950
1951 // ECMA 11.8.7
1952 JSValue *InNode::evaluate(ExecState *exec)
1953 {
1954   JSValue *v1 = expr1->evaluate(exec);
1955   KJS_CHECKEXCEPTIONVALUE
1956   JSValue *v2 = expr2->evaluate(exec);
1957   KJS_CHECKEXCEPTIONVALUE
1958
1959   // Is all of this OK for host objects?
1960   if (!v2->isObject())
1961       return throwError(exec,  TypeError,
1962                          "Value %s (result of expression %s) is not an object. Cannot be used with IN expression.", v2, expr2.get());
1963   JSObject *o2(static_cast<JSObject*>(v2));
1964   return jsBoolean(o2->hasProperty(exec, Identifier(v1->toString(exec))));
1965 }
1966
1967 // ------------------------------ Equality Nodes ------------------------------------
1968
1969 void EqualNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1970 {
1971     nodeStack.append(expr2.get());
1972     nodeStack.append(expr1.get());
1973 }
1974
1975 // ECMA 11.9.1
1976 JSValue *EqualNode::evaluate(ExecState *exec)
1977 {
1978   JSValue *v1 = expr1->evaluate(exec);
1979   KJS_CHECKEXCEPTIONVALUE
1980   JSValue *v2 = expr2->evaluate(exec);
1981   KJS_CHECKEXCEPTIONVALUE
1982
1983   return jsBoolean(equal(exec,v1, v2));
1984 }
1985
1986 void NotEqualNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
1987 {
1988     nodeStack.append(expr2.get());
1989     nodeStack.append(expr1.get());
1990 }
1991
1992 // ECMA 11.9.2
1993 JSValue *NotEqualNode::evaluate(ExecState *exec)
1994 {
1995   JSValue *v1 = expr1->evaluate(exec);
1996   KJS_CHECKEXCEPTIONVALUE
1997   JSValue *v2 = expr2->evaluate(exec);
1998   KJS_CHECKEXCEPTIONVALUE
1999
2000   return jsBoolean(!equal(exec,v1, v2));
2001 }
2002
2003 void StrictEqualNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2004 {
2005     nodeStack.append(expr2.get());
2006     nodeStack.append(expr1.get());
2007 }
2008
2009 // ECMA 11.9.4
2010 JSValue *StrictEqualNode::evaluate(ExecState *exec)
2011 {
2012   JSValue *v1 = expr1->evaluate(exec);
2013   KJS_CHECKEXCEPTIONVALUE
2014   JSValue *v2 = expr2->evaluate(exec);
2015   KJS_CHECKEXCEPTIONVALUE
2016
2017   return jsBoolean(strictEqual(exec,v1, v2));
2018 }
2019
2020 void NotStrictEqualNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2021 {
2022     nodeStack.append(expr2.get());
2023     nodeStack.append(expr1.get());
2024 }
2025
2026 // ECMA 11.9.5
2027 JSValue *NotStrictEqualNode::evaluate(ExecState *exec)
2028 {
2029   JSValue *v1 = expr1->evaluate(exec);
2030   KJS_CHECKEXCEPTIONVALUE
2031   JSValue *v2 = expr2->evaluate(exec);
2032   KJS_CHECKEXCEPTIONVALUE
2033
2034   return jsBoolean(!strictEqual(exec,v1, v2));
2035 }
2036
2037 // ------------------------------ Bit Operation Nodes ----------------------------------
2038
2039 void BitAndNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2040 {
2041     nodeStack.append(expr2.get());
2042     nodeStack.append(expr1.get());
2043 }
2044
2045 // ECMA 11.10
2046 JSValue *BitAndNode::evaluate(ExecState *exec)
2047 {
2048   JSValue *v1 = expr1->evaluate(exec);
2049   KJS_CHECKEXCEPTIONVALUE
2050   JSValue *v2 = expr2->evaluate(exec);
2051   KJS_CHECKEXCEPTIONVALUE
2052   
2053   return jsNumber(v1->toInt32(exec) & v2->toInt32(exec));
2054 }
2055
2056 void BitXOrNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2057 {
2058     nodeStack.append(expr2.get());
2059     nodeStack.append(expr1.get());
2060 }
2061
2062 JSValue *BitXOrNode::evaluate(ExecState *exec)
2063 {
2064   JSValue *v1 = expr1->evaluate(exec);
2065   KJS_CHECKEXCEPTIONVALUE
2066   JSValue *v2 = expr2->evaluate(exec);
2067   KJS_CHECKEXCEPTIONVALUE
2068   
2069   return jsNumber(v1->toInt32(exec) ^ v2->toInt32(exec));
2070 }
2071
2072 void BitOrNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2073 {
2074     nodeStack.append(expr2.get());
2075     nodeStack.append(expr1.get());
2076 }
2077
2078 JSValue *BitOrNode::evaluate(ExecState *exec)
2079 {
2080   JSValue *v1 = expr1->evaluate(exec);
2081   KJS_CHECKEXCEPTIONVALUE
2082   JSValue *v2 = expr2->evaluate(exec);
2083   KJS_CHECKEXCEPTIONVALUE
2084   
2085   return jsNumber(v1->toInt32(exec) | v2->toInt32(exec));
2086 }
2087
2088 // ------------------------------ Binary Logical Nodes ----------------------------
2089
2090 void LogicalAndNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2091 {
2092     nodeStack.append(expr2.get());
2093     nodeStack.append(expr1.get());
2094 }
2095
2096 // ECMA 11.11
2097 JSValue *LogicalAndNode::evaluate(ExecState *exec)
2098 {
2099   JSValue *v1 = expr1->evaluate(exec);
2100   KJS_CHECKEXCEPTIONVALUE
2101   bool b1 = v1->toBoolean(exec);
2102   if (!b1)
2103     return v1;
2104
2105   JSValue *v2 = expr2->evaluate(exec);
2106   KJS_CHECKEXCEPTIONVALUE
2107
2108   return v2;
2109 }
2110
2111 void LogicalOrNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2112 {
2113     nodeStack.append(expr2.get());
2114     nodeStack.append(expr1.get());
2115 }
2116
2117 JSValue *LogicalOrNode::evaluate(ExecState *exec)
2118 {
2119   JSValue *v1 = expr1->evaluate(exec);
2120   KJS_CHECKEXCEPTIONVALUE
2121   bool b1 = v1->toBoolean(exec);
2122   if (b1)
2123     return v1;
2124
2125   JSValue *v2 = expr2->evaluate(exec);
2126   KJS_CHECKEXCEPTIONVALUE
2127
2128   return v2;
2129 }
2130
2131 // ------------------------------ ConditionalNode ------------------------------
2132
2133 void ConditionalNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2134 {
2135     nodeStack.append(expr2.get());
2136     nodeStack.append(expr1.get());
2137     nodeStack.append(logical.get());
2138 }
2139
2140 // ECMA 11.12
2141 JSValue *ConditionalNode::evaluate(ExecState *exec)
2142 {
2143   JSValue *v = logical->evaluate(exec);
2144   KJS_CHECKEXCEPTIONVALUE
2145   bool b = v->toBoolean(exec);
2146
2147   if (b)
2148     v = expr1->evaluate(exec);
2149   else
2150     v = expr2->evaluate(exec);
2151   KJS_CHECKEXCEPTIONVALUE
2152
2153   return v;
2154 }
2155
2156 // ECMA 11.13
2157
2158 static ALWAYS_INLINE JSValue *valueForReadModifyAssignment(ExecState * exec, JSValue *v1, JSValue *v2, Operator oper) KJS_FAST_CALL;
2159 static ALWAYS_INLINE JSValue *valueForReadModifyAssignment(ExecState * exec, JSValue *v1, JSValue *v2, Operator oper)
2160 {
2161   JSValue *v;
2162   int i1;
2163   int i2;
2164   unsigned int ui;
2165   switch (oper) {
2166   case OpMultEq:
2167     v = jsNumber(v1->toNumber(exec) * v2->toNumber(exec));
2168     break;
2169   case OpDivEq:
2170     v = jsNumber(v1->toNumber(exec) / v2->toNumber(exec));
2171     break;
2172   case OpPlusEq:
2173     v = add(exec, v1, v2);
2174     break;
2175   case OpMinusEq:
2176     v = jsNumber(v1->toNumber(exec) - v2->toNumber(exec));
2177     break;
2178   case OpLShift:
2179     i1 = v1->toInt32(exec);
2180     i2 = v2->toInt32(exec);
2181     v = jsNumber(i1 << i2);
2182     break;
2183   case OpRShift:
2184     i1 = v1->toInt32(exec);
2185     i2 = v2->toInt32(exec);
2186     v = jsNumber(i1 >> i2);
2187     break;
2188   case OpURShift:
2189     ui = v1->toUInt32(exec);
2190     i2 = v2->toInt32(exec);
2191     v = jsNumber(ui >> i2);
2192     break;
2193   case OpAndEq:
2194     i1 = v1->toInt32(exec);
2195     i2 = v2->toInt32(exec);
2196     v = jsNumber(i1 & i2);
2197     break;
2198   case OpXOrEq:
2199     i1 = v1->toInt32(exec);
2200     i2 = v2->toInt32(exec);
2201     v = jsNumber(i1 ^ i2);
2202     break;
2203   case OpOrEq:
2204     i1 = v1->toInt32(exec);
2205     i2 = v2->toInt32(exec);
2206     v = jsNumber(i1 | i2);
2207     break;
2208   case OpModEq: {
2209     double d1 = v1->toNumber(exec);
2210     double d2 = v2->toNumber(exec);
2211     v = jsNumber(fmod(d1, d2));
2212   }
2213     break;
2214   default:
2215     ASSERT(0);
2216     v = jsUndefined();
2217   }
2218   
2219   return v;
2220 }
2221
2222 // ------------------------------ ReadModifyResolveNode -----------------------------------
2223
2224 void ReadModifyResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack& nodeStack)
2225 {
2226     nodeStack.append(m_right.get());
2227     size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
2228     if (index != missingSymbolMarker())
2229         new (this) ReadModifyLocalVarNode(index);
2230 }
2231
2232 void AssignResolveNode::optimizeVariableAccess(FunctionBodyNode* functionBody, DeclarationStacks::NodeStack& nodeStack)
2233 {
2234     nodeStack.append(m_right.get());
2235     size_t index = functionBody->symbolTable().get(m_ident.ustring().rep());
2236     if (index != missingSymbolMarker())
2237         new (this) AssignLocalVarNode(index);
2238 }
2239
2240 JSValue* ReadModifyLocalVarNode::evaluate(ExecState* exec)
2241 {
2242     ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
2243     ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
2244     JSValue** slot = &exec->localStorage()[m_index].value;
2245
2246     ASSERT(m_oper != OpEqual);
2247     JSValue* v2 = m_right->evaluate(exec);
2248     JSValue* v = valueForReadModifyAssignment(exec, *slot, v2, m_oper);
2249
2250     KJS_CHECKEXCEPTIONVALUE
2251
2252     *slot = v;
2253     return v;
2254 }
2255
2256 JSValue* AssignLocalVarNode::evaluate(ExecState* exec)
2257 {
2258     ASSERT(static_cast<ActivationImp*>(exec->variableObject())->isActivation());
2259     ASSERT(static_cast<ActivationImp*>(exec->variableObject()) == exec->scopeChain().top());
2260     JSValue* v = m_right->evaluate(exec);
2261
2262     KJS_CHECKEXCEPTIONVALUE
2263
2264     exec->localStorage()[m_index].value = v;
2265     
2266     return v;
2267 }
2268
2269 JSValue *ReadModifyResolveNode::evaluate(ExecState *exec)
2270 {
2271   const ScopeChain& chain = exec->scopeChain();
2272   ScopeChainIterator iter = chain.begin();
2273   ScopeChainIterator end = chain.end();
2274   
2275   // we must always have something in the scope chain
2276   ASSERT(iter != end);
2277
2278   PropertySlot slot;
2279   JSObject *base;
2280   do { 
2281     base = *iter;
2282     if (base->getPropertySlot(exec, m_ident, slot))
2283       goto found;
2284
2285     ++iter;
2286   } while (iter != end);
2287
2288   ASSERT(m_oper != OpEqual);
2289   return throwUndefinedVariableError(exec, m_ident);
2290
2291  found:
2292   JSValue *v;
2293
2294   
2295   ASSERT(m_oper != OpEqual);
2296   JSValue *v1 = slot.getValue(exec, base, m_ident);
2297   KJS_CHECKEXCEPTIONVALUE
2298   JSValue *v2 = m_right->evaluate(exec);
2299   v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
2300
2301   KJS_CHECKEXCEPTIONVALUE
2302
2303   base->put(exec, m_ident, v);
2304   return v;
2305 }
2306
2307 JSValue *AssignResolveNode::evaluate(ExecState *exec)
2308 {
2309   const ScopeChain& chain = exec->scopeChain();
2310   ScopeChainIterator iter = chain.begin();
2311   ScopeChainIterator end = chain.end();
2312   
2313   // we must always have something in the scope chain
2314   ASSERT(iter != end);
2315
2316   PropertySlot slot;
2317   JSObject *base;
2318   do { 
2319     base = *iter;
2320     if (base->getPropertySlot(exec, m_ident, slot))
2321       goto found;
2322
2323     ++iter;
2324   } while (iter != end);
2325
2326  found:
2327   JSValue *v = m_right->evaluate(exec);
2328
2329   KJS_CHECKEXCEPTIONVALUE
2330
2331   base->put(exec, m_ident, v);
2332   return v;
2333 }
2334
2335 // ------------------------------ ReadModifyDotNode -----------------------------------
2336
2337 void AssignDotNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2338 {
2339     nodeStack.append(m_right.get());
2340     nodeStack.append(m_base.get());
2341 }
2342
2343 JSValue *AssignDotNode::evaluate(ExecState *exec)
2344 {
2345   JSValue *baseValue = m_base->evaluate(exec);
2346   KJS_CHECKEXCEPTIONVALUE
2347   JSObject *base = baseValue->toObject(exec);
2348
2349   JSValue *v = m_right->evaluate(exec);
2350
2351   KJS_CHECKEXCEPTIONVALUE
2352
2353   base->put(exec, m_ident, v);
2354   return v;
2355 }
2356
2357 void ReadModifyDotNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2358 {
2359     nodeStack.append(m_right.get());
2360     nodeStack.append(m_base.get());
2361 }
2362
2363 JSValue *ReadModifyDotNode::evaluate(ExecState *exec)
2364 {
2365   JSValue *baseValue = m_base->evaluate(exec);
2366   KJS_CHECKEXCEPTIONVALUE
2367   JSObject *base = baseValue->toObject(exec);
2368
2369   JSValue *v;
2370
2371   ASSERT(m_oper != OpEqual);
2372   PropertySlot slot;
2373   JSValue *v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2374   KJS_CHECKEXCEPTIONVALUE
2375   JSValue *v2 = m_right->evaluate(exec);
2376   v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
2377
2378   KJS_CHECKEXCEPTIONVALUE
2379
2380   base->put(exec, m_ident, v);
2381   return v;
2382 }
2383
2384 // ------------------------------ AssignErrorNode -----------------------------------
2385
2386 JSValue* AssignErrorNode::evaluate(ExecState* exec)
2387 {
2388     throwError(exec, ReferenceError, "Left side of assignment is not a reference.");
2389     handleException(exec);
2390     return jsUndefined();
2391 }
2392
2393 // ------------------------------ AssignBracketNode -----------------------------------
2394
2395 void AssignBracketNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2396 {
2397     nodeStack.append(m_right.get());
2398     nodeStack.append(m_subscript.get());
2399     nodeStack.append(m_base.get());
2400 }
2401
2402 JSValue *AssignBracketNode::evaluate(ExecState *exec)
2403 {
2404   JSValue *baseValue = m_base->evaluate(exec);
2405   KJS_CHECKEXCEPTIONVALUE
2406   JSValue *subscript = m_subscript->evaluate(exec);
2407   KJS_CHECKEXCEPTIONVALUE
2408
2409   JSObject *base = baseValue->toObject(exec);
2410
2411   uint32_t propertyIndex;
2412   if (subscript->getUInt32(propertyIndex)) {
2413     JSValue *v = m_right->evaluate(exec);
2414     KJS_CHECKEXCEPTIONVALUE
2415
2416     base->put(exec, propertyIndex, v);
2417     return v;
2418   }
2419
2420   Identifier propertyName(subscript->toString(exec));
2421   JSValue *v = m_right->evaluate(exec);
2422   KJS_CHECKEXCEPTIONVALUE
2423
2424   base->put(exec, propertyName, v);
2425   return v;
2426 }
2427 void ReadModifyBracketNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2428 {
2429     nodeStack.append(m_right.get());
2430     nodeStack.append(m_subscript.get());
2431     nodeStack.append(m_base.get());
2432 }
2433
2434 JSValue *ReadModifyBracketNode::evaluate(ExecState *exec)
2435 {
2436   JSValue *baseValue = m_base->evaluate(exec);
2437   KJS_CHECKEXCEPTIONVALUE
2438   JSValue *subscript = m_subscript->evaluate(exec);
2439   KJS_CHECKEXCEPTIONVALUE
2440
2441   JSObject *base = baseValue->toObject(exec);
2442
2443   uint32_t propertyIndex;
2444   if (subscript->getUInt32(propertyIndex)) {
2445     JSValue *v;
2446     ASSERT(m_oper != OpEqual);
2447     PropertySlot slot;
2448     JSValue *v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2449     KJS_CHECKEXCEPTIONVALUE
2450     JSValue *v2 = m_right->evaluate(exec);
2451     v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
2452
2453     KJS_CHECKEXCEPTIONVALUE
2454
2455     base->put(exec, propertyIndex, v);
2456     return v;
2457   }
2458
2459   Identifier propertyName(subscript->toString(exec));
2460   JSValue *v;
2461
2462   ASSERT(m_oper != OpEqual);
2463   PropertySlot slot;
2464   JSValue *v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2465   KJS_CHECKEXCEPTIONVALUE
2466   JSValue *v2 = m_right->evaluate(exec);
2467   v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
2468
2469   KJS_CHECKEXCEPTIONVALUE
2470
2471   base->put(exec, propertyName, v);
2472   return v;
2473 }
2474
2475 // ------------------------------ CommaNode ------------------------------------
2476
2477 void CommaNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2478 {
2479     nodeStack.append(expr2.get());
2480     nodeStack.append(expr1.get());
2481 }
2482
2483 // ECMA 11.14
2484 JSValue *CommaNode::evaluate(ExecState *exec)
2485 {
2486   expr1->evaluate(exec);
2487   KJS_CHECKEXCEPTIONVALUE
2488   JSValue *v = expr2->evaluate(exec);
2489   KJS_CHECKEXCEPTIONVALUE
2490
2491   return v;
2492 }
2493
2494 // ------------------------------ AssignExprNode -------------------------------
2495
2496 void AssignExprNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2497 {
2498     nodeStack.append(expr.get());
2499 }
2500
2501 // ECMA 12.2
2502 JSValue *AssignExprNode::evaluate(ExecState *exec)
2503 {
2504   return expr->evaluate(exec);
2505 }
2506
2507 // ------------------------------ VarDeclNode ----------------------------------
2508
2509 VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in, Type t)
2510     : varType(t)
2511     , ident(id)
2512     , init(in)
2513 {
2514     m_mayHaveDeclarations = true; 
2515 }
2516
2517 void VarDeclNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2518 {
2519     if (next)
2520         nodeStack.append(next.get());
2521     if (init)
2522         nodeStack.append(init.get());
2523 }
2524
2525 void VarDeclNode::getDeclarations(DeclarationStacks& stacks)
2526 {
2527     if (next) {
2528         ASSERT(next->mayHaveDeclarations());
2529         stacks.nodeStack.append(next.get()); 
2530     }
2531
2532     // The normal check to avoid overwriting pre-existing values with variable
2533     // declarations doesn't work for the "arguments" property because we 
2534     // instantiate it lazily. So we need to check here instead.
2535     if (ident == stacks.exec->propertyNames().arguments)
2536         return;
2537
2538     stacks.varStack.append(this); 
2539 }
2540
2541 void VarDeclNode::handleSlowCase(ExecState* exec, const ScopeChain& chain, JSValue* val)
2542 {
2543     ScopeChainIterator iter = chain.begin();
2544     ScopeChainIterator end = chain.end();        
2545     
2546     // we must always have something in the scope chain
2547     ASSERT(iter != end);
2548     
2549     PropertySlot slot;
2550     JSObject* base;
2551     
2552     do {
2553         base = *iter;
2554         if (base->getPropertySlot(exec, ident, slot))
2555             break;
2556         
2557         ++iter;
2558     } while (iter != end);
2559     
2560     unsigned flags = 0;
2561     base->getPropertyAttributes(ident, flags);
2562     if (varType == VarDeclNode::Constant)
2563         flags |= ReadOnly;
2564     
2565     base->put(exec, ident, val, flags);
2566 }
2567
2568 // ECMA 12.2
2569 inline void VarDeclNode::evaluateSingle(ExecState* exec)
2570 {
2571     const ScopeChain& chain = exec->scopeChain();
2572     JSObject* variableObject = exec->variableObject();
2573
2574     ASSERT(!chain.isEmpty());
2575
2576     bool inGlobalScope = ++chain.begin() == chain.end();
2577
2578     if (inGlobalScope && (init || !variableObject->getDirect(ident))) {
2579         JSValue* val = init ? init->evaluate(exec) : jsUndefined();
2580         int flags = Internal;
2581         if (exec->codeType() != EvalCode)
2582             flags |= DontDelete;
2583         if (varType == VarDeclNode::Constant)
2584             flags |= ReadOnly;
2585         variableObject->putDirect(ident, val, flags);
2586     } else if (init) {
2587         JSValue* val = init->evaluate(exec);
2588         KJS_CHECKEXCEPTIONVOID
2589             
2590         // if the variable object is the top of the scope chain, then that must
2591         // be where this variable is declared, processVarDecls would have put 
2592         // it there. Don't search the scope chain, to optimize this very common case.
2593         if (chain.top() != variableObject)
2594             return handleSlowCase(exec, chain, val);
2595
2596         unsigned flags = 0;
2597         variableObject->getPropertyAttributes(ident, flags);
2598         if (varType == VarDeclNode::Constant)
2599             flags |= ReadOnly;
2600         
2601         ASSERT(variableObject->hasProperty(exec, ident));
2602         variableObject->put(exec, ident, val, flags);
2603     }
2604 }
2605
2606 JSValue* VarDeclNode::evaluate(ExecState* exec)
2607 {
2608     evaluateSingle(exec);
2609
2610     if (VarDeclNode* n = next.get()) {
2611         do {
2612             n->evaluateSingle(exec);
2613             KJS_CHECKEXCEPTIONVALUE
2614             n = n->next.get();
2615         } while (n);
2616     }
2617     return jsUndefined();
2618 }
2619
2620 // ------------------------------ VarStatementNode -----------------------------
2621
2622 void VarStatementNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2623 {
2624     ASSERT(next);
2625     nodeStack.append(next.get());
2626 }
2627
2628 // ECMA 12.2
2629 Completion VarStatementNode::execute(ExecState *exec)
2630 {
2631     KJS_BREAKPOINT;
2632
2633     next->evaluate(exec);
2634     KJS_CHECKEXCEPTION
2635
2636     return Completion(Normal);
2637 }
2638
2639 void VarStatementNode::getDeclarations(DeclarationStacks& stacks)
2640 {
2641     ASSERT(next->mayHaveDeclarations());
2642     stacks.nodeStack.append(next.get());
2643 }
2644
2645 // ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
2646
2647 static inline void statementListPushFIFO(SourceElements& statements, DeclarationStacks::NodeStack& stack)
2648 {
2649     for (SourceElements::iterator ptr = statements.end() - 1; ptr >= statements.begin(); --ptr)
2650         stack.append((*ptr).get());
2651 }
2652
2653 static inline void statementListGetDeclarations(SourceElements& statements, DeclarationStacks& stacks)
2654 {
2655     for (SourceElements::iterator ptr = statements.end() - 1; ptr >= statements.begin(); --ptr)
2656         if ((*ptr)->mayHaveDeclarations())
2657             stacks.nodeStack.append((*ptr).get());
2658 }
2659
2660 static inline Node* statementListInitializeDeclarationStacks(SourceElements& statements, DeclarationStacks::NodeStack& stack)
2661 {
2662     for (SourceElements::iterator ptr = statements.end() - 1; ptr >= statements.begin(); --ptr)
2663         if ((*ptr)->mayHaveDeclarations())
2664              stack.append((*ptr).get());
2665     if (!stack.size())
2666         return 0;
2667     Node* n = stack.last();
2668     stack.removeLast();
2669     return n;
2670 }
2671
2672 static inline Node* statementListInitializeVariableAccessStack(SourceElements& statements, DeclarationStacks::NodeStack& stack)
2673 {
2674     for (SourceElements::iterator ptr = statements.end() - 1; ptr != statements.begin(); --ptr)
2675         stack.append((*ptr).get());
2676     return statements[0].get();
2677 }
2678
2679 static inline Completion statementListExecute(SourceElements& statements, ExecState* exec)
2680 {
2681     JSValue* v = 0;
2682     Completion c(Normal);
2683     const SourceElements::iterator end = statements.end();
2684     for (SourceElements::iterator ptr = statements.begin(); ptr != end; ++ptr) {
2685         c = (*ptr)->execute(exec);
2686         
2687         if (JSValue* v2 = c.value())
2688             v = v2;
2689         c.setValue(v);
2690         
2691         if (c.complType() != Normal)
2692             return c;
2693     }
2694     return c;
2695 }
2696     
2697 // ------------------------------ BlockNode ------------------------------------
2698
2699 void BlockNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2700 {
2701     if (m_children)
2702         statementListPushFIFO(*m_children, nodeStack);
2703 }
2704
2705 BlockNode::BlockNode(SourceElements* children)
2706 {
2707   if (children) {
2708     m_mayHaveDeclarations = true; 
2709     m_children.set(children);
2710     setLoc(children->at(0)->firstLine(), children->at(children->size() - 1)->lastLine());
2711   }
2712 }
2713
2714 void BlockNode::getDeclarations(DeclarationStacks& stacks)
2715
2716     ASSERT(m_children);
2717     statementListGetDeclarations(*m_children, stacks);
2718 }
2719
2720 // ECMA 12.1
2721 Completion BlockNode::execute(ExecState *exec)
2722 {
2723   if (!m_children)
2724     return Completion(Normal);
2725
2726   return statementListExecute(*m_children, exec);
2727 }
2728
2729 // ------------------------------ EmptyStatementNode ---------------------------
2730
2731 // ECMA 12.3
2732 Completion EmptyStatementNode::execute(ExecState *)
2733 {
2734   return Completion(Normal);
2735 }
2736
2737 // ------------------------------ ExprStatementNode ----------------------------
2738
2739 void ExprStatementNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2740 {
2741     ASSERT(expr);
2742     nodeStack.append(expr.get());
2743 }
2744
2745 // ECMA 12.4
2746 Completion ExprStatementNode::execute(ExecState *exec)
2747 {
2748   KJS_BREAKPOINT;
2749
2750   JSValue *v = expr->evaluate(exec);
2751   KJS_CHECKEXCEPTION
2752
2753   return Completion(Normal, v);
2754 }
2755
2756 // ------------------------------ IfNode ---------------------------------------
2757
2758 void IfNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2759 {
2760     if (statement2)
2761         nodeStack.append(statement2.get());
2762     ASSERT(statement1);
2763     nodeStack.append(statement1.get());
2764     ASSERT(expr);
2765     nodeStack.append(expr.get());
2766 }
2767
2768 // ECMA 12.5
2769 Completion IfNode::execute(ExecState *exec)
2770 {
2771   KJS_BREAKPOINT;
2772
2773   JSValue *v = expr->evaluate(exec);
2774   KJS_CHECKEXCEPTION
2775   bool b = v->toBoolean(exec);
2776
2777   // if ... then
2778   if (b)
2779     return statement1->execute(exec);
2780
2781   // no else
2782   if (!statement2)
2783     return Completion(Normal);
2784
2785   // else
2786   return statement2->execute(exec);
2787 }
2788
2789 void IfNode::getDeclarations(DeclarationStacks& stacks)
2790
2791     if (statement2 && statement2->mayHaveDeclarations()) 
2792         stacks.nodeStack.append(statement2.get()); 
2793     if (statement1->mayHaveDeclarations()) 
2794         stacks.nodeStack.append(statement1.get()); 
2795 }
2796
2797 // ------------------------------ DoWhileNode ----------------------------------
2798
2799 void DoWhileNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2800 {
2801     nodeStack.append(statement.get());
2802     nodeStack.append(expr.get());
2803 }
2804
2805 // ECMA 12.6.1
2806 Completion DoWhileNode::execute(ExecState *exec)
2807 {
2808   KJS_BREAKPOINT;
2809
2810   JSValue *bv;
2811   Completion c;
2812   JSValue* value = 0;
2813
2814   do {
2815     exec->pushIteration();
2816     c = statement->execute(exec);
2817     exec->popIteration();
2818     
2819     if (exec->dynamicInterpreter()->timedOut())
2820         return Completion(Interrupted);
2821
2822     if (c.isValueCompletion())
2823         value = c.value();
2824
2825     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2826       if ((c.complType() == Break) && ls.contains(c.target()))
2827         return Completion(Normal, value);
2828       if (c.complType() != Normal)
2829         return c;
2830     }
2831     bv = expr->evaluate(exec);
2832     KJS_CHECKEXCEPTION
2833   } while (bv->toBoolean(exec));
2834
2835   return Completion(Normal, value);
2836 }
2837
2838 void DoWhileNode::getDeclarations(DeclarationStacks& stacks)
2839
2840     if (statement->mayHaveDeclarations()) 
2841         stacks.nodeStack.append(statement.get()); 
2842 }
2843
2844 // ------------------------------ WhileNode ------------------------------------
2845
2846 void WhileNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2847 {
2848     nodeStack.append(statement.get());
2849     nodeStack.append(expr.get());
2850 }
2851
2852 // ECMA 12.6.2
2853 Completion WhileNode::execute(ExecState *exec)
2854 {
2855   KJS_BREAKPOINT;
2856
2857   JSValue *bv;
2858   Completion c;
2859   bool b(false);
2860   JSValue *value = 0;
2861
2862   while (1) {
2863     bv = expr->evaluate(exec);
2864     KJS_CHECKEXCEPTION
2865     b = bv->toBoolean(exec);
2866
2867     if (!b)
2868       return Completion(Normal, value);
2869
2870     exec->pushIteration();
2871     c = statement->execute(exec);
2872     exec->popIteration();
2873
2874     if (exec->dynamicInterpreter()->timedOut())
2875         return Completion(Interrupted);
2876     
2877     if (c.isValueCompletion())
2878       value = c.value();
2879
2880     if ((c.complType() == Continue) && ls.contains(c.target()))
2881       continue;
2882     if ((c.complType() == Break) && ls.contains(c.target()))
2883       return Completion(Normal, value);
2884     if (c.complType() != Normal)
2885       return c;
2886   }
2887
2888   return Completion(); // work around gcc 4.0 bug
2889 }
2890
2891 void WhileNode::getDeclarations(DeclarationStacks& stacks)
2892
2893     if (statement->mayHaveDeclarations()) 
2894         stacks.nodeStack.append(statement.get()); 
2895 }
2896
2897 // ------------------------------ ForNode --------------------------------------
2898
2899 void ForNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2900 {
2901     nodeStack.append(statement.get());
2902     if (expr3)
2903         nodeStack.append(expr3.get());
2904     if (expr2)
2905         nodeStack.append(expr2.get());
2906     if (expr1)
2907         nodeStack.append(expr1.get());
2908 }
2909
2910 // ECMA 12.6.3
2911 Completion ForNode::execute(ExecState *exec)
2912 {
2913   JSValue *v, *cval = 0;
2914
2915   if (expr1) {
2916     v = expr1->evaluate(exec);
2917     KJS_CHECKEXCEPTION
2918   }
2919   while (1) {
2920     if (expr2) {
2921       v = expr2->evaluate(exec);
2922       KJS_CHECKEXCEPTION
2923       if (!v->toBoolean(exec))
2924         return Completion(Normal, cval);
2925     }
2926
2927     exec->pushIteration();
2928     Completion c = statement->execute(exec);
2929     exec->popIteration();
2930     if (c.isValueCompletion())
2931       cval = c.value();
2932     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2933       if ((c.complType() == Break) && ls.contains(c.target()))
2934         return Completion(Normal, cval);
2935       if (c.complType() != Normal)
2936       return c;
2937     }
2938     
2939     if (exec->dynamicInterpreter()->timedOut())
2940         return Completion(Interrupted);
2941     
2942     if (expr3) {
2943       v = expr3->evaluate(exec);
2944       KJS_CHECKEXCEPTION
2945     }
2946   }
2947   
2948   return Completion(); // work around gcc 4.0 bug
2949 }
2950
2951 void ForNode::getDeclarations(DeclarationStacks& stacks)
2952
2953     if (statement->mayHaveDeclarations()) 
2954         stacks.nodeStack.append(statement.get()); 
2955     if (expr1 && expr1->mayHaveDeclarations()) 
2956         stacks.nodeStack.append(expr1.get()); 
2957 }
2958
2959 // ------------------------------ ForInNode ------------------------------------
2960
2961 ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
2962   : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
2963 {
2964     m_mayHaveDeclarations = true; 
2965 }
2966
2967 ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
2968   : ident(i), init(in), expr(e), statement(s)
2969 {
2970   m_mayHaveDeclarations = true; 
2971
2972   // for( var foo = bar in baz )
2973   varDecl = new VarDeclNode(ident, init.get(), VarDeclNode::Variable);
2974   lexpr = new ResolveNode(ident);
2975 }
2976
2977 void ForInNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
2978 {
2979     nodeStack.append(statement.get());
2980     nodeStack.append(expr.get());
2981     nodeStack.append(lexpr.get());
2982     if (varDecl)
2983         nodeStack.append(varDecl.get());
2984 }
2985
2986 void ForInNode::getDeclarations(DeclarationStacks& stacks)
2987
2988     if (statement->mayHaveDeclarations()) 
2989         stacks.nodeStack.append(statement.get()); 
2990     if (varDecl && varDecl->mayHaveDeclarations()) 
2991         stacks.nodeStack.append(varDecl.get()); 
2992 }
2993
2994 // ECMA 12.6.4
2995 Completion ForInNode::execute(ExecState *exec)
2996 {
2997   JSValue *e;
2998   JSValue *retval = 0;
2999   JSObject *v;
3000   Completion c;
3001   PropertyNameArray propertyNames;
3002
3003   if (varDecl) {
3004     varDecl->evaluate(exec);
3005     KJS_CHECKEXCEPTION
3006   }
3007
3008   e = expr->evaluate(exec);
3009
3010   // for Null and Undefined, we want to make sure not to go through
3011   // the loop at all, because their object wrappers will have a
3012   // property list but will throw an exception if you attempt to
3013   // access any property.
3014   if (e->isUndefinedOrNull())
3015     return Completion(Normal);
3016
3017   KJS_CHECKEXCEPTION
3018   v = e->toObject(exec);
3019   v->getPropertyNames(exec, propertyNames);
3020   
3021   PropertyNameArrayIterator end = propertyNames.end();
3022   for (PropertyNameArrayIterator it = propertyNames.begin(); it != end; ++it) {
3023       const Identifier &name = *it;
3024       if (!v->hasProperty(exec, name))
3025           continue;
3026
3027       JSValue *str = jsOwnedString(name.ustring());
3028
3029       if (lexpr->isResolveNode()) {
3030         const Identifier &ident = static_cast<ResolveNode *>(lexpr.get())->identifier();
3031
3032         const ScopeChain& chain = exec->scopeChain();
3033         ScopeChainIterator iter = chain.begin();
3034         ScopeChainIterator end = chain.end();
3035   
3036         // we must always have something in the scope chain
3037         ASSERT(iter != end);
3038
3039         PropertySlot slot;
3040         JSObject *o;
3041         do { 
3042             o = *iter;
3043             if (o->getPropertySlot(exec, ident, slot)) {
3044                 o->put(exec, ident, str);
3045                 break;
3046             }
3047             ++iter;
3048         } while (iter != end);
3049         
3050         if (iter == end)
3051             o->put(exec, ident, str);
3052     } else if (lexpr->isDotAccessorNode()) {
3053         const Identifier& ident = static_cast<DotAccessorNode *>(lexpr.get())->identifier();
3054         JSValue *v = static_cast<DotAccessorNode *>(lexpr.get())->base()->evaluate(exec);
3055         KJS_CHECKEXCEPTION
3056         JSObject *o = v->toObject(exec);
3057
3058         o->put(exec, ident, str);
3059     } else {
3060         ASSERT(lexpr->isBracketAccessorNode());
3061         JSValue *v = static_cast<BracketAccessorNode *>(lexpr.get())->base()->evaluate(exec);
3062         KJS_CHECKEXCEPTION
3063         JSValue *v2 = static_cast<BracketAccessorNode *>(lexpr.get())->subscript()->evaluate(exec);
3064         KJS_CHECKEXCEPTION
3065         JSObject *o = v->toObject(exec);
3066
3067         uint32_t i;
3068         if (v2->getUInt32(i))
3069             o->put(exec, i, str);
3070         o->put(exec, Identifier(v2->toString(exec)), str);
3071     }
3072
3073     KJS_CHECKEXCEPTION
3074
3075     exec->pushIteration();
3076     c = statement->execute(exec);
3077     exec->popIteration();
3078     if (c.isValueCompletion())
3079       retval = c.value();
3080
3081     if (!((c.complType() == Continue) && ls.contains(c.target()))) {
3082       if ((c.complType() == Break) && ls.contains(c.target()))
3083         break;
3084       if (c.complType() != Normal) {
3085         return c;
3086       }
3087     }
3088   }
3089
3090   return Completion(Normal, retval);
3091 }
3092
3093 // ------------------------------ ContinueNode ---------------------------------
3094
3095 // ECMA 12.7
3096 Completion ContinueNode::execute(ExecState *exec)
3097 {
3098   KJS_BREAKPOINT;
3099
3100   if (ident.isEmpty() && !exec->inIteration())
3101     return createErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
3102   if (!ident.isEmpty() && !exec->seenLabels()->contains(ident))
3103     return createErrorCompletion(exec, SyntaxError, "Label %s not found.", ident);
3104   return Completion(Continue, &ident);
3105 }
3106
3107 // ------------------------------ BreakNode ------------------------------------
3108
3109 // ECMA 12.8
3110 Completion BreakNode::execute(ExecState *exec)
3111 {
3112   KJS_BREAKPOINT;
3113
3114   if (ident.isEmpty() && !exec->inIteration() &&
3115       !exec->inSwitch())
3116     return createErrorCompletion(exec, SyntaxError, "Invalid break statement.");
3117   if (!ident.isEmpty() && !exec->seenLabels()->contains(ident))
3118     return createErrorCompletion(exec, SyntaxError, "Label %s not found.");
3119   return Completion(Break, &ident);
3120 }
3121
3122 // ------------------------------ ReturnNode -----------------------------------
3123
3124 void ReturnNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
3125 {
3126     if (value)
3127         nodeStack.append(value.get());
3128 }
3129
3130 // ECMA 12.9
3131 Completion ReturnNode::execute(ExecState *exec)
3132 {
3133   KJS_BREAKPOINT;
3134
3135   CodeType codeType = exec->codeType();
3136   if (codeType != FunctionCode)
3137     return createErrorCompletion(exec, SyntaxError, "Invalid return statement.");
3138
3139   if (!value)
3140     return Completion(ReturnValue, jsUndefined());
3141
3142   JSValue *v = value->evaluate(exec);
3143   KJS_CHECKEXCEPTION
3144
3145   return Completion(ReturnValue, v);
3146 }
3147
3148 // ------------------------------ WithNode -------------------------------------
3149
3150 void WithNode::getDeclarations(DeclarationStacks& stacks)
3151
3152     if (statement->mayHaveDeclarations()) 
3153         stacks.nodeStack.append(statement.get()); 
3154 }
3155
3156 void WithNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
3157 {
3158     // Can't optimize within statement because "with" introduces a dynamic scope.
3159     nodeStack.append(expr.get());
3160 }
3161
3162 // ECMA 12.10
3163 Completion WithNode::execute(ExecState *exec)
3164 {
3165   KJS_BREAKPOINT;
3166
3167   JSValue *v = expr->evaluate(exec);
3168   KJS_CHECKEXCEPTION
3169   JSObject *o = v->toObject(exec);
3170   KJS_CHECKEXCEPTION
3171   exec->pushScope(o);
3172   Completion res = statement->execute(exec);
3173   exec->popScope();
3174
3175   return res;
3176 }
3177     
3178 // ------------------------------ CaseClauseNode -------------------------------
3179
3180 void CaseClauseNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
3181 {
3182     if (expr)
3183         nodeStack.append(expr.get());
3184     if (m_children)
3185         statementListPushFIFO(*m_children, nodeStack);
3186 }
3187
3188 void CaseClauseNode::getDeclarations(DeclarationStacks& stacks)
3189
3190     if (m_children) 
3191         statementListGetDeclarations(*m_children, stacks);
3192 }
3193
3194 // ECMA 12.11
3195 JSValue *CaseClauseNode::evaluate(ExecState *exec)
3196 {
3197   JSValue *v = expr->evaluate(exec);
3198   KJS_CHECKEXCEPTIONVALUE
3199
3200   return v;
3201 }
3202
3203 // ECMA 12.11
3204 Completion CaseClauseNode::evalStatements(ExecState *exec)
3205 {
3206   if (m_children)
3207     return statementListExecute(*m_children, exec);
3208   else
3209     return Completion(Normal, jsUndefined());
3210 }
3211
3212 // ------------------------------ ClauseListNode -------------------------------
3213
3214 void ClauseListNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
3215 {
3216     if (next)
3217         nodeStack.append(next.get());
3218     nodeStack.append(clause.get());
3219 }
3220
3221 void ClauseListNode::getDeclarations(DeclarationStacks& stacks)
3222
3223     if (next && next->mayHaveDeclarations()) 
3224         stacks.nodeStack.append(next.get()); 
3225     if (clause->mayHaveDeclarations()) 
3226         stacks.nodeStack.append(clause.get()); 
3227 }
3228
3229 JSValue *ClauseListNode::evaluate(ExecState *)
3230 {
3231   // should never be called
3232   ASSERT(false);
3233   return 0;
3234 }
3235
3236 // ------------------------------ CaseBlockNode --------------------------------
3237
3238 CaseBlockNode::CaseBlockNode(ClauseListNode* l1, CaseClauseNode* d, ClauseListNode* l2)
3239     : list1(l1)
3240     , def(d)
3241     , list2(l2)
3242 {
3243     m_mayHaveDeclarations = true; 
3244 }
3245  
3246 void CaseBlockNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
3247 {
3248     if (list2)
3249         nodeStack.append(list2.get());
3250     if (def)
3251         nodeStack.append(def.get());
3252     if (list1)
3253         nodeStack.append(list1.get());
3254 }
3255
3256 void CaseBlockNode::getDeclarations(DeclarationStacks& stacks) 
3257
3258     if (list2 && list2->mayHaveDeclarations()) 
3259         stacks.nodeStack.append(list2.get());
3260     if (def && def->mayHaveDeclarations()) 
3261         stacks.nodeStack.append(def.get()); 
3262     if (list1 && list1->mayHaveDeclarations()) 
3263         stacks.nodeStack.append(list1.get()); 
3264 }
3265
3266 JSValue *CaseBlockNode::evaluate(ExecState *)
3267 {
3268   // should never be called
3269   ASSERT(false);
3270   return 0;
3271 }
3272
3273 // ECMA 12.11
3274 Completion CaseBlockNode::evalBlock(ExecState *exec, JSValue *input)
3275 {
3276   JSValue *v;
3277   Completion res;
3278   ClauseListNode *a = list1.get();
3279   ClauseListNode *b = list2.get();
3280   CaseClauseNode *clause;
3281
3282     while (a) {
3283       clause = a->getClause();
3284       a = a->getNext();
3285       v = clause->evaluate(exec);
3286       KJS_CHECKEXCEPTION
3287       if (strictEqual(exec, input, v)) {
3288         res = clause->evalStatements(exec);
3289         if (res.complType() != Normal)
3290           return res;
3291         while (a) {
3292           res = a->getClause()->evalStatements(exec);
3293           if (res.complType() != Normal)
3294             return res;
3295           a = a->getNext();
3296         }
3297         break;
3298       }
3299     }
3300
3301   while (b) {
3302     clause = b->getClause();
3303     b = b->getNext();
3304     v = clause->evaluate(exec);
3305     KJS_CHECKEXCEPTION
3306     if (strictEqual(exec, input, v)) {
3307       res = clause->evalStatements(exec);
3308       if (res.complType() != Normal)
3309         return res;
3310       goto step18;
3311     }
3312   }
3313
3314   // default clause
3315   if (def) {
3316     res = def->evalStatements(exec);
3317     if (res.complType() != Normal)
3318       return res;
3319   }
3320   b = list2.get();
3321  step18:
3322   while (b) {
3323     clause = b->getClause();
3324     res = clause->evalStatements(exec);
3325     if (res.complType() != Normal)
3326       return res;
3327     b = b->getNext();
3328   }
3329
3330   // bail out on error
3331   KJS_CHECKEXCEPTION
3332
3333   return Completion(Normal);
3334 }
3335
3336 // ------------------------------ SwitchNode -----------------------------------
3337
3338 void SwitchNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
3339 {
3340     nodeStack.append(block.get());
3341     nodeStack.append(expr.get());
3342 }
3343
3344 void SwitchNode::getDeclarations(DeclarationStacks& stacks) 
3345
3346     if (block->mayHaveDeclarations()) 
3347         stacks.nodeStack.append(block.get()); 
3348 }
3349
3350 // ECMA 12.11
3351 Completion SwitchNode::execute(ExecState *exec)
3352 {
3353   KJS_BREAKPOINT;
3354
3355   JSValue *v = expr->evaluate(exec);
3356   KJS_CHECKEXCEPTION
3357
3358   exec->pushSwitch();
3359   Completion res = block->evalBlock(exec,v);
3360   exec->popSwitch();
3361
3362   if ((res.complType() == Break) && ls.contains(res.target()))
3363     return Completion(Normal, res.value());
3364   return res;
3365 }
3366
3367 // ------------------------------ LabelNode ------------------------------------
3368
3369 void LabelNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
3370 {
3371     nodeStack.append(statement.get());
3372 }
3373
3374 void LabelNode::getDeclarations(DeclarationStacks& stacks) 
3375
3376     if (statement->mayHaveDeclarations()) 
3377         stacks.nodeStack.append(statement.get()); 
3378 }
3379
3380 // ECMA 12.12
3381 Completion LabelNode::execute(ExecState *exec)
3382 {
3383   if (!exec->seenLabels()->push(label))
3384     return createErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", label);
3385   Completion e = statement->execute(exec);
3386   exec->seenLabels()->pop();
3387
3388   if ((e.complType() == Break) && (e.target() == label))
3389     return Completion(Normal, e.value());
3390   return e;
3391 }
3392
3393 // ------------------------------ ThrowNode ------------------------------------
3394
3395 void ThrowNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
3396 {
3397     nodeStack.append(expr.get());
3398 }
3399
3400 // ECMA 12.13
3401 Completion ThrowNode::execute(ExecState *exec)
3402 {
3403   KJS_BREAKPOINT;
3404
3405   JSValue *v = expr->evaluate(exec);
3406   KJS_CHECKEXCEPTION
3407
3408   handleException(exec, v);
3409   return Completion(Throw, v);
3410 }
3411
3412 // ------------------------------ TryNode --------------------------------------
3413
3414 void TryNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
3415 {
3416     // Can't optimize within catchBlock because "catch" introduces a dynamic scope.
3417     if (finallyBlock)
3418         nodeStack.append(finallyBlock.get());
3419     nodeStack.append(tryBlock.get());
3420 }
3421
3422 void TryNode::getDeclarations(DeclarationStacks& stacks) 
3423
3424     if (finallyBlock && finallyBlock->mayHaveDeclarations()) 
3425         stacks.nodeStack.append(finallyBlock.get()); 
3426     if (catchBlock && catchBlock->mayHaveDeclarations()) 
3427         stacks.nodeStack.append(catchBlock.get()); 
3428     if (tryBlock->mayHaveDeclarations()) 
3429         stacks.nodeStack.append(tryBlock.get()); 
3430 }
3431
3432 // ECMA 12.14
3433 Completion TryNode::execute(ExecState *exec)
3434 {
3435   KJS_BREAKPOINT;
3436
3437   Completion c = tryBlock->execute(exec);
3438
3439   if (Collector::isOutOfMemory())
3440       return c; // don't try to catch an out of memory exception thrown by the collector
3441   
3442   if (catchBlock && c.complType() == Throw) {
3443     JSObject *obj = new JSObject;
3444     obj->put(exec, exceptionIdent, c.value(), DontDelete);
3445     exec->pushScope(obj);
3446     c = catchBlock->execute(exec);
3447     exec->popScope();
3448   }
3449
3450   if (finallyBlock) {
3451     Completion c2 = finallyBlock->execute(exec);
3452     if (c2.complType() != Normal)
3453       c = c2;
3454   }
3455
3456   return c;
3457 }
3458
3459 // ------------------------------ ParameterNode --------------------------------
3460
3461 // ECMA 13
3462 JSValue *ParameterNode::evaluate(ExecState *)
3463 {
3464   return jsUndefined();
3465 }
3466
3467 // ------------------------------ FunctionBodyNode -----------------------------
3468
3469 FunctionBodyNode::FunctionBodyNode(SourceElements* children)
3470     : BlockNode(children)
3471     , m_sourceURL(Lexer::curr()->sourceURL())
3472     , m_sourceId(Parser::sid)
3473     , m_initializedDeclarationStacks(false)
3474     , m_initializedSymbolTable(false)
3475     , m_optimizedResolveNodes(false)
3476 {
3477   setLoc(-1, -1);
3478 }
3479
3480 void FunctionBodyNode::initializeDeclarationStacks(ExecState* exec)
3481 {
3482     if (!m_children)
3483         return;
3484
3485     DeclarationStacks::NodeStack nodeStack;
3486     DeclarationStacks stacks(exec, nodeStack, m_varStack, m_functionStack);
3487     Node* node = statementListInitializeDeclarationStacks(*m_children, nodeStack);
3488     if (!node)
3489         return;
3490     
3491     while (true) {
3492         ASSERT(node->mayHaveDeclarations()); // Otherwise, we wasted time putting an irrelevant node on the stack.
3493         node->getDeclarations(stacks);
3494         
3495         size_t size = nodeStack.size();
3496         if (!size)
3497             break;
3498         --size;
3499         node = nodeStack[size];
3500         nodeStack.shrink(size);
3501     }
3502
3503     m_initializedDeclarationStacks = true;
3504 }
3505
3506 void FunctionBodyNode::initializeSymbolTable()
3507 {
3508     size_t i, size;
3509     size_t count = 0;
3510
3511     // The order of additions here implicitly enforces the mutual exclusion described in ECMA 10.1.3.
3512     for (i = 0, size = m_varStack.size(); i < size; ++i)
3513         m_symbolTable.set(m_varStack[i]->ident.ustring().rep(), count++);
3514
3515     for (i = 0, size = m_parameters.size(); i < size; ++i)
3516         m_symbolTable.set(m_parameters[i].ustring().rep(), count++);
3517
3518     for (i = 0, size = m_functionStack.size(); i < size; ++i)
3519         m_symbolTable.set(m_functionStack[i]->ident.ustring().rep(), count++);
3520
3521     m_initializedSymbolTable = true;
3522 }
3523
3524 void FunctionBodyNode::optimizeVariableAccess()
3525 {
3526     if (!m_children)
3527         return;
3528
3529     DeclarationStacks::NodeStack nodeStack;
3530     Node* node = statementListInitializeVariableAccessStack(*m_children, nodeStack);
3531     if (!node)
3532         return;
3533     
3534     while (true) {
3535         node->optimizeVariableAccess(this, nodeStack);
3536         
3537         size_t size = nodeStack.size();
3538         if (!size)
3539             break;
3540         --size;
3541         node = nodeStack[size];
3542         nodeStack.shrink(size);
3543     }
3544
3545     m_optimizedResolveNodes = true;
3546 }
3547
3548 void FunctionBodyNode::processDeclarations(ExecState* exec)
3549 {
3550     if (!m_initializedDeclarationStacks)
3551         initializeDeclarationStacks(exec);
3552
3553     if (exec->codeType() == FunctionCode)
3554         processDeclarationsForFunctionCode(exec);
3555     else
3556         processDeclarationsForProgramCode(exec);
3557 }
3558
3559 void FunctionBodyNode::processDeclarationsForFunctionCode(ExecState* exec)
3560 {
3561     if (!m_initializedSymbolTable)
3562         initializeSymbolTable();
3563
3564     if (!m_optimizedResolveNodes)
3565         optimizeVariableAccess();
3566
3567     ASSERT(exec->variableObject()->isActivation());
3568     LocalStorage& localStorage = static_cast<ActivationImp*>(exec->variableObject())->localStorage();
3569     localStorage.reserveCapacity(m_varStack.size() + m_parameters.size() + m_functionStack.size());
3570     
3571     int minAttributes = Internal | DontDelete;
3572     
3573     size_t i, size;
3574
3575     // NOTE: Must match the order of addition in initializeSymbolTable().
3576
3577     for (i = 0, size = m_varStack.size(); i < size; ++i) {
3578         VarDeclNode* node = m_varStack[i];
3579         int attributes = minAttributes;
3580         if (node->varType == VarDeclNode::Constant)
3581             attributes |= ReadOnly;
3582         localStorage.append(LocalStorageEntry(jsUndefined(), attributes));
3583     }
3584
3585     const List& args = *exec->arguments();
3586     for (i = 0, size = m_parameters.size(); i < size; ++i)
3587         localStorage.append(LocalStorageEntry(args[i], DontDelete));
3588
3589     for (i = 0, size = m_functionStack.size(); i < size; ++i) {
3590         FuncDeclNode* node = m_functionStack[i];
3591         localStorage.append(LocalStorageEntry(node->makeFunction(exec), minAttributes));
3592     }
3593
3594     exec->updateLocalStorage();
3595 }
3596
3597 void FunctionBodyNode::processDeclarationsForProgramCode(ExecState* exec)
3598 {
3599     size_t i, size;
3600
3601     JSObject* variableObject = exec->variableObject();
3602     
3603     int minAttributes = Internal | (exec->codeType() != EvalCode ? DontDelete : 0);
3604
3605     for (i = 0, size = m_varStack.size(); i < size; ++i) {
3606         VarDeclNode* node = m_varStack[i];
3607         if (variableObject->hasProperty(exec, node->ident))
3608             continue;
3609         int attributes = minAttributes;
3610         if (node->varType == VarDeclNode::Constant)
3611             attributes |= ReadOnly;
3612         variableObject->put(exec, node->ident, jsUndefined(), attributes);
3613     }
3614
3615     ASSERT(!m_parameters.size());
3616
3617     for (i = 0, size = m_functionStack.size(); i < size; ++i) {
3618         FuncDeclNode* node = m_functionStack[i];
3619         variableObject->put(exec, node->ident, node->makeFunction(exec), minAttributes);
3620     }
3621 }
3622
3623 void FunctionBodyNode::addParam(const Identifier& ident)
3624 {
3625   m_parameters.append(ident);
3626 }
3627
3628 UString FunctionBodyNode::paramString() const
3629 {
3630   UString s("");
3631   size_t count = numParams();
3632   for (size_t pos = 0; pos < count; ++pos) {
3633     if (!s.isEmpty())
3634         s += ", ";
3635     s += paramName(pos).ustring();
3636   }
3637
3638   return s;
3639 }
3640
3641 Completion FunctionBodyNode::execute(ExecState* exec)
3642 {
3643     processDeclarations(exec);
3644     return BlockNode::execute(exec);
3645 }
3646
3647 // ------------------------------ FuncDeclNode ---------------------------------
3648
3649 void FuncDeclNode::addParams() 
3650 {
3651   for (ParameterNode *p = param.get(); p != 0L; p = p->nextParam())
3652     body->addParam(p->ident());
3653 }
3654
3655 void FuncDeclNode::getDeclarations(DeclarationStacks& stacks) 
3656 {
3657     stacks.functionStack.append(this);
3658 }
3659
3660 FunctionImp* FuncDeclNode::makeFunction(ExecState* exec)
3661 {
3662   FunctionImp *func = new FunctionImp(exec, ident, body.get(), exec->scopeChain());
3663
3664   JSObject *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
3665   proto->put(exec, exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
3666   func->put(exec, exec->propertyNames().prototype, proto, Internal|DontDelete);
3667
3668   func->put(exec, exec->propertyNames().length, jsNumber(body->numParams()), ReadOnly|DontDelete|DontEnum);
3669   return func;
3670 }
3671
3672 Completion FuncDeclNode::execute(ExecState *)
3673 {
3674     return Completion(Normal);
3675 }
3676
3677 // ------------------------------ FuncExprNode ---------------------------------
3678
3679 // ECMA 13
3680 void FuncExprNode::addParams()
3681 {
3682   for (ParameterNode *p = param.get(); p != 0L; p = p->nextParam())
3683     body->addParam(p->ident());
3684 }
3685
3686 JSValue *FuncExprNode::evaluate(ExecState *exec)
3687 {
3688   bool named = !ident.isNull();
3689   JSObject *functionScopeObject = 0;
3690
3691   if (named) {
3692     // named FunctionExpressions can recursively call themselves,
3693     // but they won't register with the current scope chain and should
3694     // be contained as single property in an anonymous object.
3695     functionScopeObject = new JSObject;
3696     exec->pushScope(functionScopeObject);
3697   }
3698
3699   FunctionImp* func = new FunctionImp(exec, ident, body.get(), exec->scopeChain());
3700   JSObject* proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
3701   proto->put(exec, exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
3702   func->put(exec, exec->propertyNames().prototype, proto, Internal | DontDelete);
3703
3704   if (named) {
3705     functionScopeObject->put(exec, ident, func, Internal | ReadOnly | (exec->codeType() == EvalCode ? 0 : DontDelete));
3706     exec->popScope();
3707   }
3708
3709   return func;
3710 }
3711
3712 ProgramNode::ProgramNode(SourceElements* children)
3713     : FunctionBodyNode(children)
3714 {
3715 }
3716
3717 }