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