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