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