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