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