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