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