/*
*  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
*  Copyright (C) 2001 Peter Kelly (pmk@post.com)
*  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
*  Copyright (C) 2007 Maks Orlovich
*  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Library General Public
*  License as published by the Free Software Foundation; either
*  version 2 of the License, or (at your option) any later version.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  Library General Public License for more details.
*
*  You should have received a copy of the GNU Library General Public License
*  along with this library; see the file COPYING.LIB.  If not, write to
*  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
*  Boston, MA 02110-1301, USA.
*
*/

#include "config.h"
#include "nodes.h"

#include "ExecState.h"
#include "JSGlobalObject.h"
#include "Parser.h"
#include "PropertyNameArray.h"
#include "array_object.h"
#include "debugger.h"
#include "function_object.h"
#include "lexer.h"
#include "operations.h"
#include "regexp_object.h"
#include <math.h>
#include <wtf/Assertions.h>
#include <wtf/HashCountedSet.h>
#include <wtf/HashSet.h>
#include <wtf/MathExtras.h>

namespace KJS {

class FunctionBodyNodeWithDebuggerHooks : public FunctionBodyNode {
public:
    FunctionBodyNodeWithDebuggerHooks(SourceElements*, VarStack*, FunctionStack*) KJS_FAST_CALL;
    virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
};

#define KJS_CHECKEXCEPTION \
if (exec->hadException()) \
    return rethrowException(exec);

#define KJS_CHECKEXCEPTIONVALUE \
if (exec->hadException()) { \
    handleException(exec); \
    return jsUndefined(); \
}

#define KJS_CHECKEXCEPTIONNUMBER \
if (exec->hadException()) { \
    handleException(exec); \
    return 0; \
}

#define KJS_CHECKEXCEPTIONBOOLEAN \
if (exec->hadException()) { \
    handleException(exec); \
    return false; \
}

#define KJS_CHECKEXCEPTIONVOID \
if (exec->hadException()) { \
    handleException(exec); \
    return; \
}

#if !ASSERT_DISABLED
static inline bool canSkipLookup(ExecState* exec, const Identifier& ident)
{
    // Static lookup in EvalCode is impossible because variables aren't DontDelete.
    // Static lookup in GlobalCode may be possible, but we haven't implemented support for it yet.
    if (exec->codeType() != FunctionCode)
        return false;

    // Static lookup is impossible when something dynamic has been added to the front of the scope chain.
    if (exec->variableObject() != exec->scopeChain().top())
        return false;

    // Static lookup is impossible if the symbol isn't statically declared.
    if (!exec->variableObject()->symbolTable().contains(ident.ustring().rep()))
        return false;

    return true;
}
#endif

static inline bool isConstant(const LocalStorage& localStorage, size_t index)
{
    ASSERT(index < localStorage.size());
    return localStorage[index].attributes & ReadOnly;
}

// ------------------------------ Node -----------------------------------------

#ifndef NDEBUG
#ifndef LOG_CHANNEL_PREFIX
#define LOG_CHANNEL_PREFIX Log
#endif
static WTFLogChannel LogKJSNodeLeaks = { 0x00000000, "", WTFLogChannelOn };

struct ParserRefCountedCounter {
    static unsigned count;
    ParserRefCountedCounter()
    {
        if (count)
            LOG(KJSNodeLeaks, "LEAK: %u KJS::Node\n", count);
    }
};
unsigned ParserRefCountedCounter::count = 0;
static ParserRefCountedCounter parserRefCountedCounter;
#endif

static HashSet<ParserRefCounted*>* newTrackedObjects;
static HashCountedSet<ParserRefCounted*>* trackedObjectExtraRefCounts;

ParserRefCounted::ParserRefCounted()
{
#ifndef NDEBUG
    ++ParserRefCountedCounter::count;
#endif
    if (!newTrackedObjects)
        newTrackedObjects = new HashSet<ParserRefCounted*>;
    newTrackedObjects->add(this);
    ASSERT(newTrackedObjects->contains(this));
}

ParserRefCounted::~ParserRefCounted()
{
#ifndef NDEBUG
    --ParserRefCountedCounter::count;
#endif
}

void ParserRefCounted::ref()
{
    // bumping from 0 to 1 is just removing from the new nodes set
    if (newTrackedObjects) {
        HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->find(this);
        if (it != newTrackedObjects->end()) {
            newTrackedObjects->remove(it);
            ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
            return;
        }
    }

    ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));

    if (!trackedObjectExtraRefCounts)
        trackedObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
    trackedObjectExtraRefCounts->add(this);
}

void ParserRefCounted::deref()
{
    ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));

    if (!trackedObjectExtraRefCounts) {
        delete this;
        return;
    }

    HashCountedSet<ParserRefCounted*>::iterator it = trackedObjectExtraRefCounts->find(this);
    if (it == trackedObjectExtraRefCounts->end())
        delete this;
    else
        trackedObjectExtraRefCounts->remove(it);
}

unsigned ParserRefCounted::refcount()
{
    if (newTrackedObjects && newTrackedObjects->contains(this)) {
        ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
        return 0;
    }

    ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));

    if (!trackedObjectExtraRefCounts)
        return 1;

    return 1 + trackedObjectExtraRefCounts->count(this);
}

void ParserRefCounted::deleteNewObjects()
{
    if (!newTrackedObjects)
        return;

#ifndef NDEBUG
    HashSet<ParserRefCounted*>::iterator end = newTrackedObjects->end();
    for (HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->begin(); it != end; ++it)
        ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(*it));
#endif
    deleteAllValues(*newTrackedObjects);
    delete newTrackedObjects;
    newTrackedObjects = 0;
}

Node::Node()
    : m_expectedReturnType(ObjectType)
{
    m_line = lexer().lineNo();
}

Node::Node(JSType expectedReturn)
    : m_expectedReturnType(expectedReturn)
{
    m_line = lexer().lineNo();
}

double ExpressionNode::evaluateToNumber(ExecState* exec)
{
    JSValue* value = evaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return value->toNumber(exec);
}

bool ExpressionNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* value = evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return value->toBoolean(exec);
}

int32_t ExpressionNode::evaluateToInt32(ExecState* exec)
{
    JSValue* value = evaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return value->toInt32(exec);
}

uint32_t ExpressionNode::evaluateToUInt32(ExecState* exec)
{
    JSValue* value = evaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return value->toUInt32(exec);
}

static void substitute(UString& string, const UString& substring) KJS_FAST_CALL;
static void substitute(UString& string, const UString& substring)
{
    int position = string.find("%s");
    ASSERT(position != -1);
    UString newString = string.substr(0, position);
    newString.append(substring);
    newString.append(string.substr(position + 2));
    string = newString;
}

static inline int currentSourceId(ExecState* exec) KJS_FAST_CALL;
static inline int currentSourceId(ExecState* exec)
{
    return exec->scopeNode()->sourceId();
}

static inline const UString& currentSourceURL(ExecState* exec) KJS_FAST_CALL;
static inline const UString& currentSourceURL(ExecState* exec)
{
    return exec->scopeNode()->sourceURL();
}

JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg)
{
    return exec->setThrowCompletion(Error::create(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
}

JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg, const Identifier& ident)
{
    UString message = msg;
    substitute(message, ident.ustring());
    return exec->setThrowCompletion(Error::create(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
}

JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg)
{
    return KJS::throwError(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}

JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const char* string)
{
    UString message = msg;
    substitute(message, string);
    return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}

JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr)
{
    UString message = msg;
    substitute(message, v->toString(exec));
    substitute(message, expr->toString());
    return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}

JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const Identifier& label)
{
    UString message = msg;
    substitute(message, label.ustring());
    return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}

JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* e1, Node* e2)
{
    UString message = msg;
    substitute(message, v->toString(exec));
    substitute(message, e1->toString());
    substitute(message, e2->toString());
    return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}

JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr, const Identifier& label)
{
    UString message = msg;
    substitute(message, v->toString(exec));
    substitute(message, expr->toString());
    substitute(message, label.ustring());
    return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}

JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, const Identifier& label)
{
    UString message = msg;
    substitute(message, v->toString(exec));
    substitute(message, label.ustring());
    return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
}

JSValue* Node::throwUndefinedVariableError(ExecState* exec, const Identifier& ident)
{
    return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
}

void Node::handleException(ExecState* exec)
{
    handleException(exec, exec->exception());
}

void Node::handleException(ExecState* exec, JSValue* exceptionValue)
{
    if (exceptionValue->isObject()) {
        JSObject* exception = static_cast<JSObject*>(exceptionValue);
        if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
            exception->put(exec, "line", jsNumber(m_line));
            exception->put(exec, "sourceURL", jsString(currentSourceURL(exec)));
        }
    }
    Debugger* dbg = exec->dynamicGlobalObject()->debugger();
    if (dbg && !dbg->hasHandledException(exec, exceptionValue)) {
        bool cont = dbg->exception(exec, currentSourceId(exec), m_line, exceptionValue);
        if (!cont)
            dbg->imp()->abort();
    }
}

NEVER_INLINE JSValue* Node::rethrowException(ExecState* exec)
{
    JSValue* exception = exec->exception();
    exec->clearException();
    handleException(exec, exception);
    return exec->setThrowCompletion(exception);
}

// ------------------------------ StatementNode --------------------------------

StatementNode::StatementNode()
    : m_lastLine(-1)
{
    m_line = -1;
}

void StatementNode::setLoc(int firstLine, int lastLine)
{
    m_line = firstLine;
    m_lastLine = lastLine;
}

// ------------------------------ SourceElements --------------------------------

void SourceElements::append(PassRefPtr<StatementNode> statement)
{
    if (statement->isEmptyStatement())
        return;

    if (Debugger::debuggersPresent)
        m_statements.append(new BreakpointCheckStatement(statement));
    else
        m_statements.append(statement);
}

// ------------------------------ BreakpointCheckStatement --------------------------------

BreakpointCheckStatement::BreakpointCheckStatement(PassRefPtr<StatementNode> statement)
    : m_statement(statement)
{
    ASSERT(m_statement);
}

JSValue* BreakpointCheckStatement::execute(ExecState* exec)
{
    if (Debugger* debugger = exec->dynamicGlobalObject()->debugger())
        if (!debugger->atStatement(exec, currentSourceId(exec), m_statement->firstLine(), m_statement->lastLine()))
            return exec->setNormalCompletion();
    return m_statement->execute(exec);
}

void BreakpointCheckStatement::streamTo(SourceStream& stream) const
{
    m_statement->streamTo(stream);
}

void BreakpointCheckStatement::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_statement.get());
}

// ------------------------------ NullNode -------------------------------------

JSValue* NullNode::evaluate(ExecState* )
{
    return jsNull();
}

// ------------------------------ FalseNode ----------------------------------

JSValue* FalseNode::evaluate(ExecState*)
{
    return jsBoolean(false);
}

// ------------------------------ TrueNode ----------------------------------

JSValue* TrueNode::evaluate(ExecState*)
{
    return jsBoolean(true);
}

// ------------------------------ NumberNode -----------------------------------

JSValue* NumberNode::evaluate(ExecState*)
{
    // Number nodes are only created when the number can't fit in a JSImmediate, so no need to check again.
    return jsNumberCell(m_double);
}

double NumberNode::evaluateToNumber(ExecState*)
{
    return m_double;
}

bool NumberNode::evaluateToBoolean(ExecState*)
{
    return m_double < 0.0 || m_double > 0.0; // false for NaN as well as 0
}

int32_t NumberNode::evaluateToInt32(ExecState*)
{
    return JSValue::toInt32(m_double);
}

uint32_t NumberNode::evaluateToUInt32(ExecState*)
{
    return JSValue::toUInt32(m_double);
}

// ------------------------------ ImmediateNumberNode -----------------------------------

JSValue* ImmediateNumberNode::evaluate(ExecState*)
{
    return m_value;
}

int32_t ImmediateNumberNode::evaluateToInt32(ExecState*)
{
    return JSImmediate::getTruncatedInt32(m_value);
}

uint32_t ImmediateNumberNode::evaluateToUInt32(ExecState*)
{
    uint32_t i;
    if (JSImmediate::getTruncatedUInt32(m_value, i))
        return i;
    bool ok;
    return JSValue::toUInt32SlowCase(m_double, ok);
}

// ------------------------------ StringNode -----------------------------------

JSValue* StringNode::evaluate(ExecState*)
{
    return jsOwnedString(m_value);
}

double StringNode::evaluateToNumber(ExecState*)
{
    return m_value.toDouble();
}

bool StringNode::evaluateToBoolean(ExecState*)
{
    return !m_value.isEmpty();
}

// ------------------------------ RegExpNode -----------------------------------

JSValue* RegExpNode::evaluate(ExecState* exec)
{
    return exec->lexicalGlobalObject()->regExpConstructor()->createRegExpImp(exec, m_regExp);
}

// ------------------------------ ThisNode -------------------------------------

// ECMA 11.1.1
JSValue* ThisNode::evaluate(ExecState* exec)
{
    return exec->thisValue();
}

// ------------------------------ ResolveNode ----------------------------------

// ECMA 11.1.2 & 10.1.4
JSValue* ResolveNode::inlineEvaluate(ExecState* exec)
{
    // Check for missed optimization opportunity.
    ASSERT(!canSkipLookup(exec, m_ident));

    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // we must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    do {
        JSObject* o = *iter;

        if (o->getPropertySlot(exec, m_ident, slot))
            return slot.getValue(exec, o, m_ident);

        ++iter;
    } while (iter != end);

    return throwUndefinedVariableError(exec, m_ident);
}

JSValue* ResolveNode::evaluate(ExecState* exec)
{
    return inlineEvaluate(exec);
}

double ResolveNode::evaluateToNumber(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toNumber(exec);
}

bool ResolveNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return v->toBoolean(exec);
}

int32_t ResolveNode::evaluateToInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toInt32(exec);
}

uint32_t ResolveNode::evaluateToUInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toUInt32(exec);
}

void ResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
{
    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker())
        new (this) LocalVarAccessNode(index);
}

JSValue* LocalVarAccessNode::inlineEvaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());
    return exec->localStorage()[m_index].value;
}

JSValue* LocalVarAccessNode::evaluate(ExecState* exec)
{
    return inlineEvaluate(exec);
}

double LocalVarAccessNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluate(exec)->toNumber(exec);
}

bool LocalVarAccessNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluate(exec)->toBoolean(exec);
}

int32_t LocalVarAccessNode::evaluateToInt32(ExecState* exec)
{
    return inlineEvaluate(exec)->toInt32(exec);
}

uint32_t LocalVarAccessNode::evaluateToUInt32(ExecState* exec)
{
    return inlineEvaluate(exec)->toUInt32(exec);
}

// ------------------------------ ElementNode ----------------------------------

void ElementNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_next)
        nodeStack.append(m_next.get());
    ASSERT(m_node);
    nodeStack.append(m_node.get());
}

// ECMA 11.1.4
JSValue* ElementNode::evaluate(ExecState* exec)
{
    JSObject* array = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
    int length = 0;
    for (ElementNode* n = this; n; n = n->m_next.get()) {
        JSValue* val = n->m_node->evaluate(exec);
        KJS_CHECKEXCEPTIONVALUE
        length += n->m_elision;
        array->put(exec, length++, val);
    }
    return array;
}

// ------------------------------ ArrayNode ------------------------------------

void ArrayNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_element)
        nodeStack.append(m_element.get());
}

// ECMA 11.1.4
JSValue* ArrayNode::evaluate(ExecState* exec)
{
    JSObject* array;
    int length;

    if (m_element) {
        array = static_cast<JSObject*>(m_element->evaluate(exec));
        KJS_CHECKEXCEPTIONVALUE
        length = m_optional ? array->get(exec, exec->propertyNames().length)->toInt32(exec) : 0;
    } else {
        JSValue* newArr = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
        array = static_cast<JSObject*>(newArr);
        length = 0;
    }

    if (m_optional)
        array->put(exec, exec->propertyNames().length, jsNumber(m_elision + length));

    return array;
}

// ------------------------------ ObjectLiteralNode ----------------------------

void ObjectLiteralNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_list)
        nodeStack.append(m_list.get());
}

// ECMA 11.1.5
JSValue* ObjectLiteralNode::evaluate(ExecState* exec)
{
    if (m_list)
        return m_list->evaluate(exec);

    return exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
}

// ------------------------------ PropertyListNode -----------------------------

void PropertyListNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_next)
        nodeStack.append(m_next.get());
    nodeStack.append(m_node.get());
}

// ECMA 11.1.5
JSValue* PropertyListNode::evaluate(ExecState* exec)
{
    JSObject* obj = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());

    for (PropertyListNode* p = this; p; p = p->m_next.get()) {
        JSValue* v = p->m_node->m_assign->evaluate(exec);
        KJS_CHECKEXCEPTIONVALUE

        switch (p->m_node->m_type) {
            case PropertyNode::Getter:
                ASSERT(v->isObject());
                obj->defineGetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
                break;
            case PropertyNode::Setter:
                ASSERT(v->isObject());
                obj->defineSetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
                break;
            case PropertyNode::Constant:
                obj->put(exec, p->m_node->name(), v);
                break;
        }
    }

    return obj;
}

// ------------------------------ PropertyNode -----------------------------

void PropertyNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_assign.get());
}

// ECMA 11.1.5
JSValue* PropertyNode::evaluate(ExecState*)
{
    ASSERT(false);
    return jsNull();
}

// ------------------------------ BracketAccessorNode --------------------------------

void BracketAccessorNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_subscript.get());
    nodeStack.append(m_base.get());
}

// ECMA 11.2.1a
JSValue* BracketAccessorNode::inlineEvaluate(ExecState* exec)
{
    JSValue* v1 = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* v2 = m_subscript->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSObject* o = v1->toObject(exec);
    uint32_t i;
    if (v2->getUInt32(i))
        return o->get(exec, i);
    return o->get(exec, Identifier(v2->toString(exec)));
}

JSValue* BracketAccessorNode::evaluate(ExecState* exec)
{
    return inlineEvaluate(exec);
}

double BracketAccessorNode::evaluateToNumber(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toNumber(exec);
}

bool BracketAccessorNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return v->toBoolean(exec);
}

int32_t BracketAccessorNode::evaluateToInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toInt32(exec);
}

uint32_t BracketAccessorNode::evaluateToUInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toUInt32(exec);
}

// ------------------------------ DotAccessorNode --------------------------------

void DotAccessorNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_base.get());
}

// ECMA 11.2.1b
JSValue* DotAccessorNode::inlineEvaluate(ExecState* exec)
{
    JSValue* v = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    return v->toObject(exec)->get(exec, m_ident);
}

JSValue* DotAccessorNode::evaluate(ExecState* exec)
{
    return inlineEvaluate(exec);
}

double DotAccessorNode::evaluateToNumber(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toNumber(exec);
}

bool DotAccessorNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return v->toBoolean(exec);
}

int32_t DotAccessorNode::evaluateToInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toInt32(exec);
}

uint32_t DotAccessorNode::evaluateToUInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toUInt32(exec);
}

// ------------------------------ ArgumentListNode -----------------------------

void ArgumentListNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_next)
        nodeStack.append(m_next.get());
    ASSERT(m_expr);
    nodeStack.append(m_expr.get());
}

// ECMA 11.2.4
void ArgumentListNode::evaluateList(ExecState* exec, List& list)
{
    for (ArgumentListNode* n = this; n; n = n->m_next.get()) {
        JSValue* v = n->m_expr->evaluate(exec);
        KJS_CHECKEXCEPTIONVOID
        list.append(v);
    }
}

// ------------------------------ ArgumentsNode --------------------------------

void ArgumentsNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_listNode)
        nodeStack.append(m_listNode.get());
}

// ------------------------------ NewExprNode ----------------------------------

void NewExprNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_args)
        nodeStack.append(m_args.get());
    nodeStack.append(m_expr.get());
}

// ECMA 11.2.2

JSValue* NewExprNode::inlineEvaluate(ExecState* exec)
{
    JSValue* v = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    List argList;
    if (m_args) {
        m_args->evaluateList(exec, argList);
        KJS_CHECKEXCEPTIONVALUE
    }

    if (!v->isObject())
        return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, m_expr.get());

    JSObject* constr = static_cast<JSObject*>(v);
    if (!constr->implementsConstruct())
        return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, m_expr.get());

    return constr->construct(exec, argList);
}

JSValue* NewExprNode::evaluate(ExecState* exec)
{
    return inlineEvaluate(exec);
}

double NewExprNode::evaluateToNumber(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toNumber(exec);
}

bool NewExprNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return v->toBoolean(exec);
}

int32_t NewExprNode::evaluateToInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toInt32(exec);
}

uint32_t NewExprNode::evaluateToUInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toUInt32(exec);
}

void FunctionCallValueNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_args.get());
    nodeStack.append(m_expr.get());
}

// ECMA 11.2.3
JSValue* FunctionCallValueNode::evaluate(ExecState* exec)
{
    JSValue* v = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    if (!v->isObject()) {
        return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_expr.get());
    }

    JSObject* func = static_cast<JSObject*>(v);

    if (!func->implementsCall()) {
        return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_expr.get());
    }

    List argList;
    m_args->evaluateList(exec, argList);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* thisObj =  exec->dynamicGlobalObject();

    return func->call(exec, thisObj, argList);
}

void FunctionCallResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_args.get());

    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker())
        new (this) LocalVarFunctionCallNode(index);
}

// ECMA 11.2.3
JSValue* FunctionCallResolveNode::inlineEvaluate(ExecState* exec)
{
    // Check for missed optimization opportunity.
    ASSERT(!canSkipLookup(exec, m_ident));

    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // we must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    JSObject* base;
    do {
        base = *iter;
        if (base->getPropertySlot(exec, m_ident, slot)) {
            JSValue* v = slot.getValue(exec, base, m_ident);
            KJS_CHECKEXCEPTIONVALUE

            if (!v->isObject())
                return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);

            JSObject* func = static_cast<JSObject*>(v);

            if (!func->implementsCall())
                return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);

            List argList;
            m_args->evaluateList(exec, argList);
            KJS_CHECKEXCEPTIONVALUE

            JSObject* thisObj = base;
            // ECMA 11.2.3 says that in this situation the this value should be null.
            // However, section 10.2.3 says that in the case where the value provided
            // by the caller is null, the global object should be used. It also says
            // that the section does not apply to internal functions, but for simplicity
            // of implementation we use the global object anyway here. This guarantees
            // that in host objects you always get a valid object for this.
            if (thisObj->isActivationObject())
                thisObj = exec->dynamicGlobalObject();

            return func->call(exec, thisObj, argList);
        }
        ++iter;
    } while (iter != end);

    return throwUndefinedVariableError(exec, m_ident);
}

JSValue* FunctionCallResolveNode::evaluate(ExecState* exec)
{
    return inlineEvaluate(exec);
}

double FunctionCallResolveNode::evaluateToNumber(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toNumber(exec);
}

bool FunctionCallResolveNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return v->toBoolean(exec);
}

int32_t FunctionCallResolveNode::evaluateToInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toInt32(exec);
}

uint32_t FunctionCallResolveNode::evaluateToUInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toUInt32(exec);
}

JSValue* LocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());

    JSValue* v = exec->localStorage()[m_index].value;

    if (!v->isObject())
        return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);

    JSObject* func = static_cast<JSObject*>(v);
    if (!func->implementsCall())
        return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);

    List argList;
    m_args->evaluateList(exec, argList);
    KJS_CHECKEXCEPTIONVALUE

    return func->call(exec, exec->dynamicGlobalObject(), argList);
}

JSValue* LocalVarFunctionCallNode::evaluate(ExecState* exec)
{
    return inlineEvaluate(exec);
}

double LocalVarFunctionCallNode::evaluateToNumber(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toNumber(exec);
}

bool LocalVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return v->toBoolean(exec);
}

int32_t LocalVarFunctionCallNode::evaluateToInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toInt32(exec);
}

uint32_t LocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toUInt32(exec);
}

void FunctionCallBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_args.get());
    nodeStack.append(m_subscript.get());
    nodeStack.append(m_base.get());
}

// ECMA 11.2.3
JSValue* FunctionCallBracketNode::evaluate(ExecState* exec)
{
    JSValue* baseVal = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSValue* subscriptVal = m_subscript->evaluate(exec);

    JSObject* baseObj = baseVal->toObject(exec);
    uint32_t i;
    PropertySlot slot;

    JSValue* funcVal;
    if (subscriptVal->getUInt32(i)) {
        if (baseObj->getPropertySlot(exec, i, slot))
            funcVal = slot.getValue(exec, baseObj, i);
        else
            funcVal = jsUndefined();
    } else {
        Identifier ident(subscriptVal->toString(exec));
        if (baseObj->getPropertySlot(exec, ident, slot))
            funcVal = baseObj->get(exec, ident);
        else
            funcVal = jsUndefined();
    }

    KJS_CHECKEXCEPTIONVALUE

    if (!funcVal->isObject())
        return throwError(exec, TypeError, "Value %s (result of expression %s[%s]) is not object.", funcVal, m_base.get(), m_subscript.get());

    JSObject* func = static_cast<JSObject*>(funcVal);

    if (!func->implementsCall())
        return throwError(exec, TypeError, "Object %s (result of expression %s[%s]) does not allow calls.", funcVal, m_base.get(), m_subscript.get());

    List argList;
    m_args->evaluateList(exec, argList);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* thisObj = baseObj;
    ASSERT(thisObj);
    ASSERT(thisObj->isObject());
    ASSERT(!thisObj->isActivationObject());

    return func->call(exec, thisObj, argList);
}

static const char* dotExprNotAnObjectString() KJS_FAST_CALL;
static const char* dotExprNotAnObjectString()
{
    return "Value %s (result of expression %s.%s) is not object.";
}

static const char* dotExprDoesNotAllowCallsString() KJS_FAST_CALL;
static const char* dotExprDoesNotAllowCallsString()
{
    return "Object %s (result of expression %s.%s) does not allow calls.";
}

void FunctionCallDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_args.get());
    nodeStack.append(m_base.get());
}

// ECMA 11.2.3
JSValue* FunctionCallDotNode::inlineEvaluate(ExecState* exec)
{
    JSValue* baseVal = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* baseObj = baseVal->toObject(exec);
    PropertySlot slot;
    JSValue* funcVal = baseObj->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, baseObj, m_ident) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE

    if (!funcVal->isObject())
        return throwError(exec, TypeError, dotExprNotAnObjectString(), funcVal, m_base.get(), m_ident);

    JSObject* func = static_cast<JSObject*>(funcVal);

    if (!func->implementsCall())
        return throwError(exec, TypeError, dotExprDoesNotAllowCallsString(), funcVal, m_base.get(), m_ident);

    List argList;
    m_args->evaluateList(exec, argList);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* thisObj = baseObj;
    ASSERT(thisObj);
    ASSERT(thisObj->isObject());
    ASSERT(!thisObj->isActivationObject());

    return func->call(exec, thisObj, argList);
}

JSValue* FunctionCallDotNode::evaluate(ExecState* exec)
{
    return inlineEvaluate(exec);
}

double FunctionCallDotNode::evaluateToNumber(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toNumber(exec);
}

bool FunctionCallDotNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return v->toBoolean(exec);
}

int32_t FunctionCallDotNode::evaluateToInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toInt32(exec);
}

uint32_t FunctionCallDotNode::evaluateToUInt32(ExecState* exec)
{
    JSValue* v = inlineEvaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return v->toUInt32(exec);
}

// ECMA 11.3

// ------------------------------ PostfixResolveNode ----------------------------------

// Increment
void PostIncResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
{
    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker()) {
        if (isConstant(localStorage, index))
            new (this) PostIncConstNode(index);
        else
            new (this) PostIncLocalVarNode(index);
    }
}

JSValue* PostIncResolveNode::evaluate(ExecState* exec)
{
    // Check for missed optimization opportunity.
    ASSERT(!canSkipLookup(exec, m_ident));

    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // we must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    do {
        if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
            // If m_ident is 'arguments', the base->getPropertySlot() may cause 
            // base (which must be an ActivationImp in such this case) to be torn
            // off from the activation stack, in which case we need to get it again
            // from the ScopeChainIterator.
            
            JSObject* base = *iter;
            JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
            base->put(exec, m_ident, jsNumber(v->toNumber(exec) + 1));
            return v;
        }

        ++iter;
    } while (iter != end);

    return throwUndefinedVariableError(exec, m_ident);
}

void PostIncResolveNode::optimizeForUnnecessaryResult()
{
    new (this) PreIncResolveNode(PlacementNewAdopt);
}

JSValue* PostIncLocalVarNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());

    JSValue** slot = &exec->localStorage()[m_index].value;
    JSValue* v = (*slot)->toJSNumber(exec);
    *slot = jsNumber(v->toNumber(exec) + 1);
    return v;
}

void PostIncLocalVarNode::optimizeForUnnecessaryResult()
{
    new (this) PreIncLocalVarNode(m_index);
}

// Decrement
void PostDecResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
{
    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker()) {
        if (isConstant(localStorage, index))
            new (this) PostDecConstNode(index);
        else
            new (this) PostDecLocalVarNode(index);
    }
}

JSValue* PostDecResolveNode::evaluate(ExecState* exec)
{
    // Check for missed optimization opportunity.
    ASSERT(!canSkipLookup(exec, m_ident));

    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // we must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    do {
        if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
            // See the comment in PostIncResolveNode::evaluate().

            JSObject* base = *iter;
            JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
            base->put(exec, m_ident, jsNumber(v->toNumber(exec) - 1));
            return v;
        }

        ++iter;
    } while (iter != end);

    return throwUndefinedVariableError(exec, m_ident);
}

void PostDecResolveNode::optimizeForUnnecessaryResult()
{
    new (this) PreDecResolveNode(PlacementNewAdopt);
}

JSValue* PostDecLocalVarNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());

    JSValue** slot = &exec->localStorage()[m_index].value;
    JSValue* v = (*slot)->toJSNumber(exec);
    *slot = jsNumber(v->toNumber(exec) - 1);
    return v;
}

double PostDecLocalVarNode::inlineEvaluateToNumber(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());

    JSValue** slot = &exec->localStorage()[m_index].value;
    double n = (*slot)->toNumber(exec);
    *slot = jsNumber(n - 1);
    return n;
}

double PostDecLocalVarNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToNumber(exec);
}

bool PostDecLocalVarNode::evaluateToBoolean(ExecState* exec)
{
    double result = inlineEvaluateToNumber(exec);
    return  result > 0.0 || 0.0 > result; // NaN produces false as well
}

int32_t PostDecLocalVarNode::evaluateToInt32(ExecState* exec)
{
    return JSValue::toInt32(inlineEvaluateToNumber(exec));
}

uint32_t PostDecLocalVarNode::evaluateToUInt32(ExecState* exec)
{
    return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}

void PostDecLocalVarNode::optimizeForUnnecessaryResult()
{
    new (this) PreDecLocalVarNode(m_index);
}

// ------------------------------ PostfixBracketNode ----------------------------------

void PostfixBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_subscript.get());
    nodeStack.append(m_base.get());
}

JSValue* PostIncBracketNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* subscript = m_subscript->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* base = baseValue->toObject(exec);

    uint32_t propertyIndex;
    if (subscript->getUInt32(propertyIndex)) {
        PropertySlot slot;
        JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
        KJS_CHECKEXCEPTIONVALUE

        JSValue* v2 = v->toJSNumber(exec);
        base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) + 1));

        return v2;
    }

    Identifier propertyName(subscript->toString(exec));
    PropertySlot slot;
    JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE

    JSValue* v2 = v->toJSNumber(exec);
    base->put(exec, propertyName, jsNumber(v2->toNumber(exec) + 1));
    return v2;
}

JSValue* PostDecBracketNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* subscript = m_subscript->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* base = baseValue->toObject(exec);

    uint32_t propertyIndex;
    if (subscript->getUInt32(propertyIndex)) {
        PropertySlot slot;
        JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
        KJS_CHECKEXCEPTIONVALUE

        JSValue* v2 = v->toJSNumber(exec);
        base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) - 1));
        return v2;
    }

    Identifier propertyName(subscript->toString(exec));
    PropertySlot slot;
    JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE

    JSValue* v2 = v->toJSNumber(exec);
    base->put(exec, propertyName, jsNumber(v2->toNumber(exec) - 1));
    return v2;
}

// ------------------------------ PostfixDotNode ----------------------------------

void PostfixDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_base.get());
}

JSValue* PostIncDotNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSObject* base = baseValue->toObject(exec);

    PropertySlot slot;
    JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE

    JSValue* v2 = v->toJSNumber(exec);
    base->put(exec, m_ident, jsNumber(v2->toNumber(exec) + 1));
    return v2;
}

JSValue* PostDecDotNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSObject* base = baseValue->toObject(exec);

    PropertySlot slot;
    JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE

    JSValue* v2 = v->toJSNumber(exec);
    base->put(exec, m_ident, jsNumber(v2->toNumber(exec) - 1));
    return v2;
}

// ------------------------------ PostfixErrorNode -----------------------------------

JSValue* PostfixErrorNode::evaluate(ExecState* exec)
{
    throwError(exec, ReferenceError, "Postfix %s operator applied to value that is not a reference.",
               m_operator == OpPlusPlus ? "++" : "--");
    handleException(exec);
    return jsUndefined();
}

// ------------------------------ DeleteResolveNode -----------------------------------

void DeleteResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
{
    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker())
        new (this) LocalVarDeleteNode();
}

// ECMA 11.4.1

JSValue* DeleteResolveNode::evaluate(ExecState* exec)
{
    // Check for missed optimization opportunity.
    ASSERT(!canSkipLookup(exec, m_ident));

    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // We must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    JSObject* base;
    do {
        base = *iter;
        if (base->getPropertySlot(exec, m_ident, slot))
            return jsBoolean(base->deleteProperty(exec, m_ident));

        ++iter;
    } while (iter != end);

    return jsBoolean(true);
}

JSValue* LocalVarDeleteNode::evaluate(ExecState*)
{
    return jsBoolean(false);
}

// ------------------------------ DeleteBracketNode -----------------------------------

void DeleteBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_subscript.get());
    nodeStack.append(m_base.get());
}

JSValue* DeleteBracketNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* subscript = m_subscript->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* base = baseValue->toObject(exec);

    uint32_t propertyIndex;
    if (subscript->getUInt32(propertyIndex))
        return jsBoolean(base->deleteProperty(exec, propertyIndex));

    Identifier propertyName(subscript->toString(exec));
    return jsBoolean(base->deleteProperty(exec, propertyName));
}

// ------------------------------ DeleteDotNode -----------------------------------

void DeleteDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_base.get());
}

JSValue* DeleteDotNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    JSObject* base = baseValue->toObject(exec);
    KJS_CHECKEXCEPTIONVALUE

    return jsBoolean(base->deleteProperty(exec, m_ident));
}

// ------------------------------ DeleteValueNode -----------------------------------

void DeleteValueNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr.get());
}

JSValue* DeleteValueNode::evaluate(ExecState* exec)
{
    m_expr->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    // delete on a non-location expression ignores the value and returns true
    return jsBoolean(true);
}

// ------------------------------ VoidNode -------------------------------------

void VoidNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr.get());
}

// ECMA 11.4.2
JSValue* VoidNode::evaluate(ExecState* exec)
{
    m_expr->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    return jsUndefined();
}

// ECMA 11.4.3

// ------------------------------ TypeOfValueNode -----------------------------------

void TypeOfValueNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr.get());
}

static JSValue* typeStringForValue(JSValue* v) KJS_FAST_CALL;
static JSValue* typeStringForValue(JSValue* v)
{
    switch (v->type()) {
        case UndefinedType:
            return jsString("undefined");
        case NullType:
            return jsString("object");
        case BooleanType:
            return jsString("boolean");
        case NumberType:
            return jsString("number");
        case StringType:
            return jsString("string");
        default:
            if (v->isObject()) {
                // Return "undefined" for objects that should be treated
                // as null when doing comparisons.
                if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
                    return jsString("undefined");
                else if (static_cast<JSObject*>(v)->implementsCall())
                    return jsString("function");
            }

            return jsString("object");
    }
}

void TypeOfResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
{
    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker())
        new (this) LocalVarTypeOfNode(index);
}

JSValue* LocalVarTypeOfNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());

    return typeStringForValue(exec->localStorage()[m_index].value);
}

JSValue* TypeOfResolveNode::evaluate(ExecState* exec)
{
    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // We must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    JSObject* base;
    do {
        base = *iter;
        if (base->getPropertySlot(exec, m_ident, slot)) {
            JSValue* v = slot.getValue(exec, base, m_ident);
            return typeStringForValue(v);
        }

        ++iter;
    } while (iter != end);

    return jsString("undefined");
}

// ------------------------------ TypeOfValueNode -----------------------------------

JSValue* TypeOfValueNode::evaluate(ExecState* exec)
{
    JSValue* v = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    return typeStringForValue(v);
}

// ECMA 11.4.4 and 11.4.5

// ------------------------------ PrefixResolveNode ----------------------------------

void PreIncResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
{
    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker()) {
        if (isConstant(localStorage, index))
            new (this) PreIncConstNode(index);
        else
            new (this) PreIncLocalVarNode(index);
    }
}

JSValue* PreIncLocalVarNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());
    JSValue** slot = &exec->localStorage()[m_index].value;

    double n = (*slot)->toNumber(exec);
    JSValue* n2 = jsNumber(n + 1);
    *slot = n2;
    return n2;
}

JSValue* PreIncResolveNode::evaluate(ExecState* exec)
{
    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // we must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    do {
        if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
            // See the comment in PostIncResolveNode::evaluate().

            JSObject* base = *iter;
            JSValue* v = slot.getValue(exec, base, m_ident);

            double n = v->toNumber(exec);
            JSValue* n2 = jsNumber(n + 1);
            base->put(exec, m_ident, n2);

            return n2;
        }

        ++iter;
    } while (iter != end);

    return throwUndefinedVariableError(exec, m_ident);
}

void PreDecResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
{
    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker()) {
        if (isConstant(localStorage, index))
            new (this) PreDecConstNode(index);
        else
            new (this) PreDecLocalVarNode(index);
    }
}

JSValue* PreDecLocalVarNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());
    JSValue** slot = &exec->localStorage()[m_index].value;

    double n = (*slot)->toNumber(exec);
    JSValue* n2 = jsNumber(n - 1);
    *slot = n2;
    return n2;
}

JSValue* PreDecResolveNode::evaluate(ExecState* exec)
{
    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // we must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    do {
        if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
            // See the comment in PostIncResolveNode::evaluate().

            JSObject* base = *iter;
            JSValue* v = slot.getValue(exec, base, m_ident);

            double n = v->toNumber(exec);
            JSValue* n2 = jsNumber(n - 1);
            base->put(exec, m_ident, n2);

            return n2;
        }

        ++iter;
    } while (iter != end);

    return throwUndefinedVariableError(exec, m_ident);
}

// ------------------------------ PreIncConstNode ----------------------------------

JSValue* PreIncConstNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());
    return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) + 1);
}

// ------------------------------ PreDecConstNode ----------------------------------

JSValue* PreDecConstNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());
    return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) - 1);
}

// ------------------------------ PostIncConstNode ----------------------------------

JSValue* PostIncConstNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());
    return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
}

// ------------------------------ PostDecConstNode ----------------------------------

JSValue* PostDecConstNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());
    return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
}

// ------------------------------ PrefixBracketNode ----------------------------------

void PrefixBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_subscript.get());
    nodeStack.append(m_base.get());
}

JSValue* PreIncBracketNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* subscript = m_subscript->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* base = baseValue->toObject(exec);

    uint32_t propertyIndex;
    if (subscript->getUInt32(propertyIndex)) {
        PropertySlot slot;
        JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
        KJS_CHECKEXCEPTIONVALUE

        JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
        base->put(exec, propertyIndex, n2);

        return n2;
    }

    Identifier propertyName(subscript->toString(exec));
    PropertySlot slot;
    JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE

    JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
    base->put(exec, propertyName, n2);

    return n2;
}

JSValue* PreDecBracketNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* subscript = m_subscript->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* base = baseValue->toObject(exec);

    uint32_t propertyIndex;
    if (subscript->getUInt32(propertyIndex)) {
        PropertySlot slot;
        JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
        KJS_CHECKEXCEPTIONVALUE

        JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
        base->put(exec, propertyIndex, n2);

        return n2;
    }

    Identifier propertyName(subscript->toString(exec));
    PropertySlot slot;
    JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE

    JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
    base->put(exec, propertyName, n2);

    return n2;
}

// ------------------------------ PrefixDotNode ----------------------------------

void PrefixDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_base.get());
}

JSValue* PreIncDotNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSObject* base = baseValue->toObject(exec);

    PropertySlot slot;
    JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE

    double n = v->toNumber(exec);
    JSValue* n2 = jsNumber(n + 1);
    base->put(exec, m_ident, n2);

    return n2;
}

JSValue* PreDecDotNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSObject* base = baseValue->toObject(exec);

    PropertySlot slot;
    JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE

    double n = v->toNumber(exec);
    JSValue* n2 = jsNumber(n - 1);
    base->put(exec, m_ident, n2);

    return n2;
}

// ------------------------------ PrefixErrorNode -----------------------------------

JSValue* PrefixErrorNode::evaluate(ExecState* exec)
{
    throwError(exec, ReferenceError, "Prefix %s operator applied to value that is not a reference.",
               m_operator == OpPlusPlus ? "++" : "--");
    handleException(exec);
    return jsUndefined();
}

// ------------------------------ UnaryPlusNode --------------------------------

void UnaryPlusNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr.get());
}

// ECMA 11.4.6
JSValue* UnaryPlusNode::evaluate(ExecState* exec)
{
    JSValue* v = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    return v->toJSNumber(exec);
}

bool UnaryPlusNode::evaluateToBoolean(ExecState* exec)
{
    return m_expr->evaluateToBoolean(exec);
}

double UnaryPlusNode::evaluateToNumber(ExecState* exec)
{
    return m_expr->evaluateToNumber(exec);
}

int32_t UnaryPlusNode::evaluateToInt32(ExecState* exec)
{
    return m_expr->evaluateToInt32(exec);
}

uint32_t UnaryPlusNode::evaluateToUInt32(ExecState* exec)
{
    return m_expr->evaluateToInt32(exec);
}

// ------------------------------ NegateNode -----------------------------------

void NegateNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr.get());
}

// ECMA 11.4.7
JSValue* NegateNode::evaluate(ExecState* exec)
{
    // No need to check exception, caller will do so right after evaluate()
    return jsNumber(-m_expr->evaluateToNumber(exec));
}

double NegateNode::evaluateToNumber(ExecState* exec)
{
    // No need to check exception, caller will do so right after evaluateToNumber()
    return -m_expr->evaluateToNumber(exec);
}

// ------------------------------ BitwiseNotNode -------------------------------

void BitwiseNotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr.get());
}

// ECMA 11.4.8
int32_t BitwiseNotNode::inlineEvaluateToInt32(ExecState* exec)
{
    return ~m_expr->evaluateToInt32(exec);
}

JSValue* BitwiseNotNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToInt32(exec));
}

double BitwiseNotNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

bool BitwiseNotNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

int32_t BitwiseNotNode::evaluateToInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

uint32_t BitwiseNotNode::evaluateToUInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

// ------------------------------ LogicalNotNode -------------------------------

void LogicalNotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr.get());
}

// ECMA 11.4.9
JSValue* LogicalNotNode::evaluate(ExecState* exec)
{
    return jsBoolean(!m_expr->evaluateToBoolean(exec));
}

bool LogicalNotNode::evaluateToBoolean(ExecState* exec)
{
    return !m_expr->evaluateToBoolean(exec);
}

// ------------------------------ Multiplicative Nodes -----------------------------------

void MultNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_term1.get());
    nodeStack.append(m_term2.get());
}

// ECMA 11.5.1
double MultNode::inlineEvaluateToNumber(ExecState* exec)
{
    double n1 = m_term1->evaluateToNumber(exec);
    KJS_CHECKEXCEPTIONNUMBER
    double n2 = m_term2->evaluateToNumber(exec);
    return n1 * n2;
}

JSValue* MultNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToNumber(exec));
}

double MultNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToNumber(exec);
}

bool MultNode::evaluateToBoolean(ExecState* exec)
{
    double result = inlineEvaluateToNumber(exec);
    return  result > 0.0 || 0.0 > result; // NaN produces false as well
}

int32_t MultNode::evaluateToInt32(ExecState* exec)
{
    return JSValue::toInt32(inlineEvaluateToNumber(exec));
}

uint32_t MultNode::evaluateToUInt32(ExecState* exec)
{
    return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}

void DivNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_term1.get());
    nodeStack.append(m_term2.get());
}

// ECMA 11.5.2
double DivNode::inlineEvaluateToNumber(ExecState* exec)
{
    double n1 = m_term1->evaluateToNumber(exec);
    KJS_CHECKEXCEPTIONNUMBER
    double n2 = m_term2->evaluateToNumber(exec);
    return n1 / n2;
}

JSValue* DivNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToNumber(exec));
}

double DivNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToNumber(exec);
}

int32_t DivNode::evaluateToInt32(ExecState* exec)
{
    return JSValue::toInt32(inlineEvaluateToNumber(exec));
}

uint32_t DivNode::evaluateToUInt32(ExecState* exec)
{
    return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}

void ModNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_term1.get());
    nodeStack.append(m_term2.get());
}

// ECMA 11.5.3
double ModNode::inlineEvaluateToNumber(ExecState* exec)
{
    double n1 = m_term1->evaluateToNumber(exec);
    KJS_CHECKEXCEPTIONNUMBER
    double n2 = m_term2->evaluateToNumber(exec);
    return fmod(n1, n2);
}

JSValue* ModNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToNumber(exec));
}

double ModNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToNumber(exec);
}

bool ModNode::evaluateToBoolean(ExecState* exec)
{
    double result = inlineEvaluateToNumber(exec);
    return  result > 0.0 || 0.0 > result; // NaN produces false as well
}

int32_t ModNode::evaluateToInt32(ExecState* exec)
{
    return JSValue::toInt32(inlineEvaluateToNumber(exec));
}

uint32_t ModNode::evaluateToUInt32(ExecState* exec)
{
    return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}

// ------------------------------ Additive Nodes --------------------------------------

static JSValue* throwOutOfMemoryError(ExecState* exec)
{
    JSObject* error = Error::create(exec, GeneralError, "Out of memory");
    exec->setException(error);
    return error;
}

static double throwOutOfMemoryErrorToNumber(ExecState* exec)
{
    JSObject* error = Error::create(exec, GeneralError, "Out of memory");
    exec->setException(error);
    return 0.0;
}

// ECMA 11.6
static JSValue* addSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
{
    // exception for the Date exception in defaultValue()
    JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
    JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);

    if (p1->isString() || p2->isString()) {
        UString value = p1->toString(exec) + p2->toString(exec);
        if (value.isNull())
            return throwOutOfMemoryError(exec);
        return jsString(value);
    }

    return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
}

static double addSlowCaseToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
{
    // exception for the Date exception in defaultValue()
    JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
    JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);

    if (p1->isString() || p2->isString()) {
        UString value = p1->toString(exec) + p2->toString(exec);
        if (value.isNull())
            return throwOutOfMemoryErrorToNumber(exec);
        return value.toDouble();
    }

    return p1->toNumber(exec) + p2->toNumber(exec);
}

// Fast-path choices here are based on frequency data from SunSpider:
//    <times> Add case: <t1> <t2>
//    ---------------------------
//    5627160 Add case: 1 1
//    247427  Add case: 5 5
//    20901   Add case: 5 6
//    13978   Add case: 5 1
//    4000    Add case: 1 5
//    1       Add case: 3 5

static inline JSValue* add(ExecState* exec, JSValue* v1, JSValue* v2)
{
    JSType t1 = v1->type();
    JSType t2 = v2->type();
    const unsigned bothTypes = (t1 << 3) | t2;

    if (bothTypes == ((NumberType << 3) | NumberType))
        return jsNumber(v1->toNumber(exec) + v2->toNumber(exec));
    if (bothTypes == ((StringType << 3) | StringType)) {
        UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
        if (value.isNull())
            return throwOutOfMemoryError(exec);
        return jsString(value);
    }

    // All other cases are pretty uncommon
    return addSlowCase(exec, v1, v2);
}

static inline double addToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
{
    JSType t1 = v1->type();
    JSType t2 = v2->type();
    const unsigned bothTypes = (t1 << 3) | t2;

    if (bothTypes == ((NumberType << 3) | NumberType))
        return v1->toNumber(exec) + v2->toNumber(exec);
    if (bothTypes == ((StringType << 3) | StringType)) {
        UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
        if (value.isNull())
            return throwOutOfMemoryErrorToNumber(exec);
        return value.toDouble();
    }

    // All other cases are pretty uncommon
    return addSlowCaseToNumber(exec, v1, v2);
}

void AddNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_term1.get());
    nodeStack.append(m_term2.get());
}

// ECMA 11.6.1
JSValue* AddNode::evaluate(ExecState* exec)
{
    JSValue* v1 = m_term1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSValue* v2 = m_term2->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    return add(exec, v1, v2);
}

double AddNode::inlineEvaluateToNumber(ExecState* exec)
{
    JSValue* v1 = m_term1->evaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER

    JSValue* v2 = m_term2->evaluate(exec);
    KJS_CHECKEXCEPTIONNUMBER

    return addToNumber(exec, v1, v2);
}

double AddNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToNumber(exec);
}

int32_t AddNode::evaluateToInt32(ExecState* exec)
{
    return JSValue::toInt32(inlineEvaluateToNumber(exec));
}

uint32_t AddNode::evaluateToUInt32(ExecState* exec)
{
    return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}

double AddNumbersNode::inlineEvaluateToNumber(ExecState* exec)
{
    double n1 = m_term1->evaluateToNumber(exec);
    KJS_CHECKEXCEPTIONNUMBER
    double n2 = m_term2->evaluateToNumber(exec);
    return n1 + n2;
}

JSValue* AddNumbersNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToNumber(exec));
}

double AddNumbersNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToNumber(exec);
}

int32_t AddNumbersNode::evaluateToInt32(ExecState* exec)
{
    return JSValue::toInt32(inlineEvaluateToNumber(exec));
}

uint32_t AddNumbersNode::evaluateToUInt32(ExecState* exec)
{
    return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}

JSValue* AddStringsNode::evaluate(ExecState* exec)
{
    JSValue* v1 = m_term1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSValue* v2 = m_term2->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    return jsString(static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value());
}

JSValue* AddStringLeftNode::evaluate(ExecState* exec)
{
    JSValue* v1 = m_term1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSValue* v2 = m_term2->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
    return jsString(static_cast<StringImp*>(v1)->value() + p2->toString(exec));
}

JSValue* AddStringRightNode::evaluate(ExecState* exec)
{
    JSValue* v1 = m_term1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSValue* v2 = m_term2->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
    return jsString(p1->toString(exec) + static_cast<StringImp*>(v2)->value());
}

void SubNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_term1.get());
    nodeStack.append(m_term2.get());
}

// ECMA 11.6.2
double SubNode::inlineEvaluateToNumber(ExecState* exec)
{
    double n1 = m_term1->evaluateToNumber(exec);
    KJS_CHECKEXCEPTIONNUMBER
    double n2 = m_term2->evaluateToNumber(exec);
    return n1 - n2;
}

JSValue* SubNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToNumber(exec));
}

double SubNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToNumber(exec);
}

int32_t SubNode::evaluateToInt32(ExecState* exec)
{
    return JSValue::toInt32(inlineEvaluateToNumber(exec));
}

uint32_t SubNode::evaluateToUInt32(ExecState* exec)
{
    return JSValue::toUInt32(inlineEvaluateToNumber(exec));
}

// ------------------------------ Shift Nodes ------------------------------------

void LeftShiftNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_term1.get());
    nodeStack.append(m_term2.get());
}

// ECMA 11.7.1
int32_t LeftShiftNode::inlineEvaluateToInt32(ExecState* exec)
{
    int i1 = m_term1->evaluateToInt32(exec);
    KJS_CHECKEXCEPTIONNUMBER
    unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
    return (i1 << i2);
}

JSValue* LeftShiftNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToInt32(exec));
}

double LeftShiftNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

int32_t LeftShiftNode::evaluateToInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

uint32_t LeftShiftNode::evaluateToUInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

void RightShiftNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_term1.get());
    nodeStack.append(m_term2.get());
}

// ECMA 11.7.2
int32_t RightShiftNode::inlineEvaluateToInt32(ExecState* exec)
{
    int i1 = m_term1->evaluateToInt32(exec);
    KJS_CHECKEXCEPTIONNUMBER
    unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
    return (i1 >> i2);
}

JSValue* RightShiftNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToInt32(exec));
}

double RightShiftNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

int32_t RightShiftNode::evaluateToInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

uint32_t RightShiftNode::evaluateToUInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

void UnsignedRightShiftNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_term1.get());
    nodeStack.append(m_term2.get());
}

// ECMA 11.7.3
uint32_t UnsignedRightShiftNode::inlineEvaluateToUInt32(ExecState* exec)
{
    unsigned int i1 = m_term1->evaluateToUInt32(exec);
    KJS_CHECKEXCEPTIONNUMBER
    unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
    return (i1 >> i2);
}

JSValue* UnsignedRightShiftNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToUInt32(exec));
}

double UnsignedRightShiftNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToUInt32(exec);
}

int32_t UnsignedRightShiftNode::evaluateToInt32(ExecState* exec)
{
    return inlineEvaluateToUInt32(exec);
}

uint32_t UnsignedRightShiftNode::evaluateToUInt32(ExecState* exec)
{
    return inlineEvaluateToUInt32(exec);
}

// ------------------------------ Relational Nodes -------------------------------

static inline bool lessThan(ExecState* exec, JSValue* v1, JSValue* v2)
{
    double n1;
    double n2;
    JSValue* p1;
    JSValue* p2;
    bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
    bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);

    if (wasNotString1 | wasNotString2)
        return n1 < n2;

    return static_cast<const StringImp*>(p1)->value() < static_cast<const StringImp*>(p2)->value();
}

static inline bool lessThanEq(ExecState* exec, JSValue* v1, JSValue* v2)
{
    double n1;
    double n2;
    JSValue* p1;
    JSValue* p2;
    bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
    bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);

    if (wasNotString1 | wasNotString2)
        return n1 <= n2;

    return !(static_cast<const StringImp*>(p2)->value() < static_cast<const StringImp*>(p1)->value());
}

void LessNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.8.1
bool LessNode::inlineEvaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return lessThan(exec, v1, v2);
}

JSValue* LessNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool LessNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

bool LessNumbersNode::inlineEvaluateToBoolean(ExecState* exec)
{
    double n1 = m_expr1->evaluateToNumber(exec);
    KJS_CHECKEXCEPTIONVALUE
    double n2 = m_expr2->evaluateToNumber(exec);
    return n1 < n2;
}

JSValue* LessNumbersNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool LessNumbersNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

bool LessStringsNode::inlineEvaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* v2 = m_expr2->evaluate(exec);
    return static_cast<StringImp*>(v1)->value() < static_cast<StringImp*>(v2)->value();
}

JSValue* LessStringsNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool LessStringsNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

void GreaterNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.8.2
bool GreaterNode::inlineEvaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return lessThan(exec, v2, v1);
}

JSValue* GreaterNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool GreaterNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

void LessEqNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.8.3
bool LessEqNode::inlineEvaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return lessThanEq(exec, v1, v2);
}

JSValue* LessEqNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool LessEqNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

void GreaterEqNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.8.4
bool GreaterEqNode::inlineEvaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return lessThanEq(exec, v2, v1);
}

JSValue* GreaterEqNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool GreaterEqNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

void InstanceOfNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.8.6
JSValue* InstanceOfNode::evaluate(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    if (!v2->isObject())
        return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, m_expr2.get());

    JSObject* o2 = static_cast<JSObject*>(v2);

    // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
    // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
    // property. It seems that all objects have the property, but not all implement it, so in this
    // case we return false (consistent with Mozilla).
    if (!o2->implementsHasInstance())
        return jsBoolean(false);

    return jsBoolean(o2->hasInstance(exec, v1));
}

bool InstanceOfNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN

    if (!v2->isObject()) {
        throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'instanceof' operator.", v2, m_expr2.get());
        return false;
    }

    JSObject* o2 = static_cast<JSObject*>(v2);

    // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
    // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
    // property. It seems that all objects have the property, but not all implement it, so in this
    // case we return false (consistent with Mozilla).
    if (!o2->implementsHasInstance())
        return false;

    return o2->hasInstance(exec, v1);
}

void InNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.8.7
JSValue* InNode::evaluate(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    if (!v2->isObject())
        return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());

    return jsBoolean(static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec))));
}

bool InNode::evaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN

    if (!v2->isObject()) {
        throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
        return false;
    }

    return static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec)));
}

// ------------------------------ Equality Nodes ------------------------------------

void EqualNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.9.1
bool EqualNode::inlineEvaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN

    return equal(exec, v1, v2);
}

JSValue* EqualNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool EqualNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

void NotEqualNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.9.2
bool NotEqualNode::inlineEvaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN

    return !equal(exec,v1, v2);
}

JSValue* NotEqualNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool NotEqualNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

void StrictEqualNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.9.4
bool StrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN

    return strictEqual(exec,v1, v2);
}

JSValue* StrictEqualNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool StrictEqualNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

void NotStrictEqualNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.9.5
bool NotStrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONBOOLEAN

    return !strictEqual(exec,v1, v2);
}

JSValue* NotStrictEqualNode::evaluate(ExecState* exec)
{
    return jsBoolean(inlineEvaluateToBoolean(exec));
}

bool NotStrictEqualNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToBoolean(exec);
}

// ------------------------------ Bit Operation Nodes ----------------------------------

void BitAndNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.10
JSValue* BitAndNode::evaluate(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    return jsNumberFromAnd(exec, v1, v2);
}

int32_t BitAndNode::inlineEvaluateToInt32(ExecState* exec)
{
    int32_t i1 = m_expr1->evaluateToInt32(exec);
    KJS_CHECKEXCEPTIONNUMBER
    int32_t i2 = m_expr2->evaluateToInt32(exec);
    return (i1 & i2);
}

double BitAndNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

bool BitAndNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

int32_t BitAndNode::evaluateToInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

uint32_t BitAndNode::evaluateToUInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

void BitXOrNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

int32_t BitXOrNode::inlineEvaluateToInt32(ExecState* exec)
{
    int i1 = m_expr1->evaluateToInt32(exec);
    KJS_CHECKEXCEPTIONNUMBER
    int i2 = m_expr2->evaluateToInt32(exec);
    return (i1 ^ i2);
}

JSValue* BitXOrNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToInt32(exec));
}

double BitXOrNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

bool BitXOrNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

int32_t BitXOrNode::evaluateToInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

uint32_t BitXOrNode::evaluateToUInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

void BitOrNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

int32_t BitOrNode::inlineEvaluateToInt32(ExecState* exec)
{
    int i1 = m_expr1->evaluateToInt32(exec);
    KJS_CHECKEXCEPTIONNUMBER
    int i2 = m_expr2->evaluateToInt32(exec);
    return (i1 | i2);
}

JSValue* BitOrNode::evaluate(ExecState* exec)
{
    return jsNumber(inlineEvaluateToInt32(exec));
}

double BitOrNode::evaluateToNumber(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

bool BitOrNode::evaluateToBoolean(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

int32_t BitOrNode::evaluateToInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

uint32_t BitOrNode::evaluateToUInt32(ExecState* exec)
{
    return inlineEvaluateToInt32(exec);
}

// ------------------------------ Binary Logical Nodes ----------------------------

void LogicalAndNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.11
JSValue* LogicalAndNode::evaluate(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    bool b1 = v1->toBoolean(exec);
    KJS_CHECKEXCEPTIONVALUE
    if (!b1)
        return v1;
    JSValue* v2 = m_expr2->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    return v2;
}

bool LogicalAndNode::evaluateToBoolean(ExecState* exec)
{
    bool b = m_expr1->evaluateToBoolean(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return b && m_expr2->evaluateToBoolean(exec);
}

void LogicalOrNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

JSValue* LogicalOrNode::evaluate(ExecState* exec)
{
    JSValue* v1 = m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    if (v1->toBoolean(exec))
        return v1;
    return m_expr2->evaluate(exec);
}

bool LogicalOrNode::evaluateToBoolean(ExecState* exec)
{
    bool b = m_expr1->evaluateToBoolean(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return b || m_expr2->evaluateToBoolean(exec);
}

// ------------------------------ ConditionalNode ------------------------------

void ConditionalNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
    nodeStack.append(m_logical.get());
}

// ECMA 11.12
JSValue* ConditionalNode::evaluate(ExecState* exec)
{
    bool b = m_logical->evaluateToBoolean(exec);
    KJS_CHECKEXCEPTIONVALUE
    return b ? m_expr1->evaluate(exec) : m_expr2->evaluate(exec);
}

bool ConditionalNode::evaluateToBoolean(ExecState* exec)
{
    bool b = m_logical->evaluateToBoolean(exec);
    KJS_CHECKEXCEPTIONBOOLEAN
    return b ? m_expr1->evaluateToBoolean(exec) : m_expr2->evaluateToBoolean(exec);
}

double ConditionalNode::evaluateToNumber(ExecState* exec)
{
    bool b = m_logical->evaluateToBoolean(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return b ? m_expr1->evaluateToNumber(exec) : m_expr2->evaluateToNumber(exec);
}

int32_t ConditionalNode::evaluateToInt32(ExecState* exec)
{
    bool b = m_logical->evaluateToBoolean(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return b ? m_expr1->evaluateToInt32(exec) : m_expr2->evaluateToInt32(exec);
}

uint32_t ConditionalNode::evaluateToUInt32(ExecState* exec)
{
    bool b = m_logical->evaluateToBoolean(exec);
    KJS_CHECKEXCEPTIONNUMBER
    return b ? m_expr1->evaluateToUInt32(exec) : m_expr2->evaluateToUInt32(exec);
}

// ECMA 11.13

static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper) KJS_FAST_CALL;
static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper)
{
    JSValue* v;
    int i1;
    int i2;
    unsigned int ui;
    switch (oper) {
        case OpMultEq:
            v = jsNumber(current->toNumber(exec) * right->evaluateToNumber(exec));
            break;
        case OpDivEq:
            v = jsNumber(current->toNumber(exec) / right->evaluateToNumber(exec));
            break;
        case OpPlusEq:
            v = add(exec, current, right->evaluate(exec));
            break;
        case OpMinusEq:
            v = jsNumber(current->toNumber(exec) - right->evaluateToNumber(exec));
            break;
        case OpLShift:
            i1 = current->toInt32(exec);
            i2 = right->evaluateToInt32(exec);
            v = jsNumber(i1 << i2);
            break;
        case OpRShift:
            i1 = current->toInt32(exec);
            i2 = right->evaluateToInt32(exec);
            v = jsNumber(i1 >> i2);
            break;
        case OpURShift:
            ui = current->toUInt32(exec);
            i2 = right->evaluateToInt32(exec);
            v = jsNumber(ui >> i2);
            break;
        case OpAndEq:
            i1 = current->toInt32(exec);
            i2 = right->evaluateToInt32(exec);
            v = jsNumber(i1 & i2);
            break;
        case OpXOrEq:
            i1 = current->toInt32(exec);
            i2 = right->evaluateToInt32(exec);
            v = jsNumber(i1 ^ i2);
            break;
        case OpOrEq:
            i1 = current->toInt32(exec);
            i2 = right->evaluateToInt32(exec);
            v = jsNumber(i1 | i2);
            break;
        case OpModEq: {
            double d1 = current->toNumber(exec);
            double d2 = right->evaluateToNumber(exec);
            v = jsNumber(fmod(d1, d2));
        }
            break;
        default:
            ASSERT_NOT_REACHED();
            v = jsUndefined();
    }

    return v;
}

// ------------------------------ ReadModifyResolveNode -----------------------------------

void ReadModifyResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
{
    nodeStack.append(m_right.get());
    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker()) {
        if (isConstant(localStorage, index))
            new (this) ReadModifyConstNode(index);
        else
            new (this) ReadModifyLocalVarNode(index);
    }
}

// ------------------------------ AssignResolveNode -----------------------------------

void AssignResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
{
    nodeStack.append(m_right.get());
    size_t index = symbolTable.get(m_ident.ustring().rep());
    if (index != missingSymbolMarker()) {
        if (isConstant(localStorage, index))
            new (this) AssignConstNode;
        else
            new (this) AssignLocalVarNode(index);
    }
}

// ------------------------------ ReadModifyLocalVarNode -----------------------------------

JSValue* ReadModifyLocalVarNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());

    ASSERT(m_operator != OpEqual);
    JSValue* v = valueForReadModifyAssignment(exec, exec->localStorage()[m_index].value, m_right.get(), m_operator);

    KJS_CHECKEXCEPTIONVALUE
    
    // We can't store a pointer into localStorage() and use it throughout the function
    // body, because valueForReadModifyAssignment() might cause an ActivationImp tear-off,
    // changing the value of localStorage().
    
    exec->localStorage()[m_index].value = v;
    return v;
}

// ------------------------------ AssignLocalVarNode -----------------------------------

JSValue* AssignLocalVarNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());
    JSValue* v = m_right->evaluate(exec);

    KJS_CHECKEXCEPTIONVALUE

    exec->localStorage()[m_index].value = v;

    return v;
}

// ------------------------------ ReadModifyConstNode -----------------------------------

JSValue* ReadModifyConstNode::evaluate(ExecState* exec)
{
    ASSERT(exec->variableObject() == exec->scopeChain().top());
    JSValue* left = exec->localStorage()[m_index].value;
    ASSERT(m_operator != OpEqual);
    JSValue* result = valueForReadModifyAssignment(exec, left, m_right.get(), m_operator);
    KJS_CHECKEXCEPTIONVALUE
    return result;
}

// ------------------------------ AssignConstNode -----------------------------------

JSValue* AssignConstNode::evaluate(ExecState* exec)
{
    return m_right->evaluate(exec);
}

JSValue* ReadModifyResolveNode::evaluate(ExecState* exec)
{
    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // We must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    JSObject* base;
    do {
        base = *iter;
        if (base->getPropertySlot(exec, m_ident, slot)) {
            // See the comment in PostIncResolveNode::evaluate().

            base = *iter;
            goto found;
        }

        ++iter;
    } while (iter != end);

    ASSERT(m_operator != OpEqual);
    return throwUndefinedVariableError(exec, m_ident);

found:
    JSValue* v;

    ASSERT(m_operator != OpEqual);
    JSValue* v1 = slot.getValue(exec, base, m_ident);
    KJS_CHECKEXCEPTIONVALUE
    v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);

    KJS_CHECKEXCEPTIONVALUE
    
    // Since valueForReadModifyAssignment() might cause an ActivationImp tear-off,
    // we need to get the base from the ScopeChainIterator again.
    
    (*iter)->put(exec, m_ident, v);
    return v;
}

JSValue* AssignResolveNode::evaluate(ExecState* exec)
{
    const ScopeChain& chain = exec->scopeChain();
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // we must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    JSObject* base;
    do {
        base = *iter;
        if (base->getPropertySlot(exec, m_ident, slot)) {
            // See the comment in PostIncResolveNode::evaluate().

            base = *iter;
            goto found;
        }

        ++iter;
    } while (iter != end);

found:
    JSValue* v = m_right->evaluate(exec);

    KJS_CHECKEXCEPTIONVALUE

    base->put(exec, m_ident, v);
    return v;
}

// ------------------------------ ReadModifyDotNode -----------------------------------

void AssignDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_right.get());
    nodeStack.append(m_base.get());
}

JSValue* AssignDotNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSObject* base = baseValue->toObject(exec);

    JSValue* v = m_right->evaluate(exec);

    KJS_CHECKEXCEPTIONVALUE

    base->put(exec, m_ident, v);
    return v;
}

void ReadModifyDotNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_right.get());
    nodeStack.append(m_base.get());
}

JSValue* ReadModifyDotNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSObject* base = baseValue->toObject(exec);

    JSValue* v;

    ASSERT(m_operator != OpEqual);
    PropertySlot slot;
    JSValue* v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE
    v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);

    KJS_CHECKEXCEPTIONVALUE

    base->put(exec, m_ident, v);
    return v;
}

// ------------------------------ AssignErrorNode -----------------------------------

JSValue* AssignErrorNode::evaluate(ExecState* exec)
{
    throwError(exec, ReferenceError, "Left side of assignment is not a reference.");
    handleException(exec);
    return jsUndefined();
}

// ------------------------------ AssignBracketNode -----------------------------------

void AssignBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_right.get());
    nodeStack.append(m_subscript.get());
    nodeStack.append(m_base.get());
}

JSValue* AssignBracketNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* subscript = m_subscript->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* base = baseValue->toObject(exec);

    uint32_t propertyIndex;
    if (subscript->getUInt32(propertyIndex)) {
        JSValue* v = m_right->evaluate(exec);
        KJS_CHECKEXCEPTIONVALUE

        base->put(exec, propertyIndex, v);
        return v;
    }

    Identifier propertyName(subscript->toString(exec));
    JSValue* v = m_right->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    base->put(exec, propertyName, v);
    return v;
}
void ReadModifyBracketNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_right.get());
    nodeStack.append(m_subscript.get());
    nodeStack.append(m_base.get());
}

JSValue* ReadModifyBracketNode::evaluate(ExecState* exec)
{
    JSValue* baseValue = m_base->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    JSValue* subscript = m_subscript->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    JSObject* base = baseValue->toObject(exec);

    uint32_t propertyIndex;
    if (subscript->getUInt32(propertyIndex)) {
        JSValue* v;
        ASSERT(m_operator != OpEqual);
        PropertySlot slot;
        JSValue* v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
        KJS_CHECKEXCEPTIONVALUE
        v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);

        KJS_CHECKEXCEPTIONVALUE

        base->put(exec, propertyIndex, v);
        return v;
    }

    Identifier propertyName(subscript->toString(exec));
    JSValue* v;

    ASSERT(m_operator != OpEqual);
    PropertySlot slot;
    JSValue* v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
    KJS_CHECKEXCEPTIONVALUE
    v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);

    KJS_CHECKEXCEPTIONVALUE

    base->put(exec, propertyName, v);
    return v;
}

// ------------------------------ CommaNode ------------------------------------

void CommaNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 11.14
JSValue* CommaNode::evaluate(ExecState* exec)
{
    m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE
    return m_expr2->evaluate(exec);
}

// ------------------------------ ConstDeclNode ----------------------------------

ConstDeclNode::ConstDeclNode(const Identifier& ident, ExpressionNode* init)
    : m_ident(ident)
    , m_init(init)
{
}

void ConstDeclNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_next)
        nodeStack.append(m_next.get());
    if (m_init)
        nodeStack.append(m_init.get());
}

void ConstDeclNode::handleSlowCase(ExecState* exec, const ScopeChain& chain, JSValue* val)
{
    ScopeChainIterator iter = chain.begin();
    ScopeChainIterator end = chain.end();

    // We must always have something in the scope chain
    ASSERT(iter != end);

    PropertySlot slot;
    JSObject* base;

    do {
        base = *iter;
        if (base->getPropertySlot(exec, m_ident, slot))
            break;

        ++iter;
    } while (iter != end);

    unsigned flags = 0;
    base->getPropertyAttributes(m_ident, flags);
    flags |= ReadOnly;

    base->put(exec, m_ident, val, flags);
}

// ECMA 12.2
inline void ConstDeclNode::evaluateSingle(ExecState* exec)
{
    ASSERT(exec->variableObject()->hasOwnProperty(exec, m_ident) || exec->codeType() == EvalCode); // Guaranteed by processDeclarations.
    const ScopeChain& chain = exec->scopeChain();
    JSObject* variableObject = exec->variableObject();

    ASSERT(!chain.isEmpty());

    bool inGlobalScope = ++chain.begin() == chain.end();

    if (m_init) {
        if (inGlobalScope) {
            JSValue* val = m_init->evaluate(exec);
            int flags = Internal;
            if (exec->codeType() != EvalCode)
                flags |= DontDelete;
            flags |= ReadOnly;
            variableObject->put(exec, m_ident, val, flags);
        } else {
            JSValue* val = m_init->evaluate(exec);
            KJS_CHECKEXCEPTIONVOID

            // if the variable object is the top of the scope chain, then that must
            // be where this variable is declared, processVarDecls would have put
            // it there. Don't search the scope chain, to optimize this very common case.
            if (chain.top() != variableObject)
                return handleSlowCase(exec, chain, val);

            unsigned flags = 0;
            variableObject->getPropertyAttributes(m_ident, flags);
            flags |= ReadOnly;

            variableObject->put(exec, m_ident, val, flags);
        }
    }
}

JSValue* ConstDeclNode::evaluate(ExecState* exec)
{
    evaluateSingle(exec);

    if (ConstDeclNode* n = m_next.get()) {
        do {
            n->evaluateSingle(exec);
            KJS_CHECKEXCEPTIONVALUE
            n = n->m_next.get();
        } while (n);
    }
    return jsUndefined();
}

// ------------------------------ ConstStatementNode -----------------------------

void ConstStatementNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    ASSERT(m_next);
    nodeStack.append(m_next.get());
}

// ECMA 12.2
JSValue* ConstStatementNode::execute(ExecState* exec)
{
    m_next->evaluate(exec);
    KJS_CHECKEXCEPTION

    return exec->setNormalCompletion();
}

// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------

static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
{
    StatementVector::iterator it = statements.end();
    StatementVector::iterator begin = statements.begin();
    while (it != begin) {
        --it;
        stack.append((*it).get());
    }
}

static inline Node* statementListInitializeVariableAccessStack(StatementVector& statements, DeclarationStacks::NodeStack& stack)
{
    if (statements.isEmpty())
        return 0;

    StatementVector::iterator it = statements.end();
    StatementVector::iterator begin = statements.begin();
    StatementVector::iterator beginPlusOne = begin + 1;

    while (it != beginPlusOne) {
        --it;
        stack.append((*it).get());
    }

    return (*begin).get();
}

static inline JSValue* statementListExecute(StatementVector& statements, ExecState* exec)
{
    JSValue* value = 0;
    size_t size = statements.size();
    for (size_t i = 0; i != size; ++i) {
        JSValue* statementValue = statements[i]->execute(exec);
        if (statementValue)
            value = statementValue;
        if (exec->completionType() != Normal)
            return value;
    }
    return exec->setNormalCompletion(value);
}

// ------------------------------ BlockNode ------------------------------------

BlockNode::BlockNode(SourceElements* children)
{
    if (children)
        children->releaseContentsIntoVector(m_children);
}

void BlockNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    statementListPushFIFO(m_children, nodeStack);
}

// ECMA 12.1
JSValue* BlockNode::execute(ExecState* exec)
{
    return statementListExecute(m_children, exec);
}

// ------------------------------ EmptyStatementNode ---------------------------

// ECMA 12.3
JSValue* EmptyStatementNode::execute(ExecState* exec)
{
    return exec->setNormalCompletion();
}

// ------------------------------ ExprStatementNode ----------------------------

void ExprStatementNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    ASSERT(m_expr);
    nodeStack.append(m_expr.get());
}

// ECMA 12.4
JSValue* ExprStatementNode::execute(ExecState* exec)
{
    JSValue* value = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTION

    return exec->setNormalCompletion(value);
}

// ------------------------------ VarStatementNode ----------------------------

void VarStatementNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    ASSERT(m_expr);
    nodeStack.append(m_expr.get());
}

JSValue* VarStatementNode::execute(ExecState* exec)
{
    m_expr->evaluate(exec);
    KJS_CHECKEXCEPTION

    return exec->setNormalCompletion();
}

// ------------------------------ IfNode ---------------------------------------

void IfNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_ifBlock.get());
    nodeStack.append(m_condition.get());
}

// ECMA 12.5
JSValue* IfNode::execute(ExecState* exec)
{
    bool b = m_condition->evaluateToBoolean(exec);
    KJS_CHECKEXCEPTION

    if (b)
        return m_ifBlock->execute(exec);
    return exec->setNormalCompletion();
}

void IfElseNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
{
    nodeStack.append(m_elseBlock.get());
    IfNode::optimizeVariableAccess(symbolTable, localStorage, nodeStack);
}

// ECMA 12.5
JSValue* IfElseNode::execute(ExecState* exec)
{
    bool b = m_condition->evaluateToBoolean(exec);
    KJS_CHECKEXCEPTION

    if (b)
        return m_ifBlock->execute(exec);
    return m_elseBlock->execute(exec);
}

// ------------------------------ DoWhileNode ----------------------------------

void DoWhileNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_statement.get());
    nodeStack.append(m_expr.get());
}

// ECMA 12.6.1
JSValue* DoWhileNode::execute(ExecState* exec)
{
    JSValue* value = 0;

    while (1) {
        exec->pushIteration();
        JSValue* statementValue = m_statement->execute(exec);
        exec->popIteration();

        if (exec->dynamicGlobalObject()->timedOut())
            return exec->setInterruptedCompletion();

        if (statementValue)
            value = statementValue;

        if (exec->completionType() != Normal) {
            if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
                goto continueDoWhileLoop;
            if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
                break;
            return statementValue;
        }

    continueDoWhileLoop:
        bool b = m_expr->evaluateToBoolean(exec);
        KJS_CHECKEXCEPTION
        if (!b)
            break;
    }

    return exec->setNormalCompletion(value);
}

// ------------------------------ WhileNode ------------------------------------

void WhileNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_statement.get());
    nodeStack.append(m_expr.get());
}

// ECMA 12.6.2
JSValue* WhileNode::execute(ExecState* exec)
{
    JSValue* value = 0;

    while (1) {
        bool b = m_expr->evaluateToBoolean(exec);
        KJS_CHECKEXCEPTION
        if (!b)
            break;

        exec->pushIteration();
        JSValue* statementValue = m_statement->execute(exec);
        exec->popIteration();

        if (exec->dynamicGlobalObject()->timedOut())
            return exec->setInterruptedCompletion();

        if (statementValue)
            value = statementValue;

        if (exec->completionType() != Normal) {
            if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
                continue;
            if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
                break;
            return statementValue;
        }
    }

    return exec->setNormalCompletion(value);
}

// ------------------------------ ForNode --------------------------------------

void ForNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_statement.get());
    nodeStack.append(m_expr3.get());
    nodeStack.append(m_expr2.get());
    nodeStack.append(m_expr1.get());
}

// ECMA 12.6.3
JSValue* ForNode::execute(ExecState* exec)
{
    JSValue* value = 0;

    m_expr1->evaluate(exec);
    KJS_CHECKEXCEPTION

    while (1) {
        bool b = m_expr2->evaluateToBoolean(exec);
        KJS_CHECKEXCEPTION
        if (!b)
            break;

        exec->pushIteration();
        JSValue* statementValue = m_statement->execute(exec);
        exec->popIteration();
        if (statementValue)
            value = statementValue;

        if (exec->dynamicGlobalObject()->timedOut())
            return exec->setInterruptedCompletion();

        if (exec->completionType() != Normal) {
            if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
                goto continueForLoop;
            if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
                break;
            return statementValue;
        }

    continueForLoop:
        m_expr3->evaluate(exec);
        KJS_CHECKEXCEPTION
    }

    return exec->setNormalCompletion(value);
}

// ------------------------------ ForInNode ------------------------------------

ForInNode::ForInNode(ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
    : m_init(0L)
    , m_lexpr(l)
    , m_expr(expr)
    , m_statement(statement)
    , m_identIsVarDecl(false)
{
}

ForInNode::ForInNode(const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement)
    : m_ident(ident)
    , m_lexpr(new ResolveNode(ident))
    , m_expr(expr)
    , m_statement(statement)
    , m_identIsVarDecl(true)
{
    if (in)
        m_init = new AssignResolveNode(ident, in);
    // for( var foo = bar in baz )
}

void ForInNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_statement.get());
    nodeStack.append(m_expr.get());
    nodeStack.append(m_lexpr.get());
    if (m_init)
        nodeStack.append(m_init.get());
}

// ECMA 12.6.4
JSValue* ForInNode::execute(ExecState* exec)
{
    JSValue* value = 0;

    if (m_init) {
        m_init->evaluate(exec);
        KJS_CHECKEXCEPTION
    }

    JSValue* e = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTION

    // For Null and Undefined, we want to make sure not to go through
    // the loop at all, because toObject will throw an exception.
    if (e->isUndefinedOrNull())
        return exec->setNormalCompletion();

    JSObject* v = e->toObject(exec);
    PropertyNameArray propertyNames;
    v->getPropertyNames(exec, propertyNames);

    PropertyNameArray::const_iterator end = propertyNames.end();
    for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != end; ++it) {
        const Identifier& name = *it;
        if (!v->hasProperty(exec, name))
            continue;

        JSValue* str = jsOwnedString(name.ustring());

        if (m_lexpr->isResolveNode()) {
            const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();

            const ScopeChain& chain = exec->scopeChain();
            ScopeChainIterator iter = chain.begin();
            ScopeChainIterator end = chain.end();

            // we must always have something in the scope chain
            ASSERT(iter != end);

            PropertySlot slot;
            JSObject* o;
            do {
                o = *iter;
                if (o->getPropertySlot(exec, ident, slot)) {
                    o->put(exec, ident, str);
                    break;
                }
                ++iter;
            } while (iter != end);

            if (iter == end)
                o->put(exec, ident, str);
        } else if (m_lexpr->isDotAccessorNode()) {
            const Identifier& ident = static_cast<DotAccessorNode*>(m_lexpr.get())->identifier();
            JSValue* v = static_cast<DotAccessorNode*>(m_lexpr.get())->base()->evaluate(exec);
            KJS_CHECKEXCEPTION
            JSObject* o = v->toObject(exec);

            o->put(exec, ident, str);
        } else {
            ASSERT(m_lexpr->isBracketAccessorNode());
            JSValue* v = static_cast<BracketAccessorNode*>(m_lexpr.get())->base()->evaluate(exec);
            KJS_CHECKEXCEPTION
            JSValue* v2 = static_cast<BracketAccessorNode*>(m_lexpr.get())->subscript()->evaluate(exec);
            KJS_CHECKEXCEPTION
            JSObject* o = v->toObject(exec);

            uint32_t i;
            if (v2->getUInt32(i))
                o->put(exec, i, str);
            o->put(exec, Identifier(v2->toString(exec)), str);
        }

        KJS_CHECKEXCEPTION

        exec->pushIteration();
        JSValue* statementValue = m_statement->execute(exec);
        exec->popIteration();
        if (statementValue)
            value = statementValue;

        if (exec->completionType() != Normal) {
            if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
                continue;
            if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
                break;
            return statementValue;
        }
    }

    return exec->setNormalCompletion(value);
}

// ------------------------------ ContinueNode ---------------------------------

// ECMA 12.7
JSValue* ContinueNode::execute(ExecState* exec)
{
    if (m_ident.isEmpty() && !exec->inIteration())
        return setErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
    if (!m_ident.isEmpty() && !exec->seenLabels().contains(m_ident))
        return setErrorCompletion(exec, SyntaxError, "Label %s not found.", m_ident);
    return exec->setContinueCompletion(&m_ident);
}

// ------------------------------ BreakNode ------------------------------------

// ECMA 12.8
JSValue* BreakNode::execute(ExecState* exec)
{
    if (m_ident.isEmpty() && !exec->inIteration() && !exec->inSwitch())
        return setErrorCompletion(exec, SyntaxError, "Invalid break statement.");
    if (!m_ident.isEmpty() && !exec->seenLabels().contains(m_ident))
        return setErrorCompletion(exec, SyntaxError, "Label %s not found.");
    return exec->setBreakCompletion(&m_ident);
}

// ------------------------------ ReturnNode -----------------------------------

void ReturnNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_value)
        nodeStack.append(m_value.get());
}

// ECMA 12.9
JSValue* ReturnNode::execute(ExecState* exec)
{
    CodeType codeType = exec->codeType();
    if (codeType != FunctionCode)
        return setErrorCompletion(exec, SyntaxError, "Invalid return statement.");

    if (!m_value)
        return exec->setReturnValueCompletion(jsUndefined());

    JSValue* v = m_value->evaluate(exec);
    KJS_CHECKEXCEPTION

    return exec->setReturnValueCompletion(v);
}

// ------------------------------ WithNode -------------------------------------

void WithNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    // Can't optimize within statement because "with" introduces a dynamic scope.
    nodeStack.append(m_expr.get());
}

// ECMA 12.10
JSValue* WithNode::execute(ExecState* exec)
{
    JSValue* v = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTION
    JSObject* o = v->toObject(exec);
    KJS_CHECKEXCEPTION
    exec->dynamicGlobalObject()->tearOffActivation(exec);
    exec->pushScope(o);
    JSValue* value = m_statement->execute(exec);
    exec->popScope();

    return value;
}

// ------------------------------ CaseClauseNode -------------------------------

void CaseClauseNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_expr)
        nodeStack.append(m_expr.get());
    statementListPushFIFO(m_children, nodeStack);
}

// ECMA 12.11
JSValue* CaseClauseNode::evaluate(ExecState* exec)
{
    JSValue* v = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTIONVALUE

    return v;
}

// ECMA 12.11
JSValue* CaseClauseNode::executeStatements(ExecState* exec)
{
    return statementListExecute(m_children, exec);
}

// ------------------------------ ClauseListNode -------------------------------

void ClauseListNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_next)
        nodeStack.append(m_next.get());
    nodeStack.append(m_clause.get());
}

// ------------------------------ CaseBlockNode --------------------------------

CaseBlockNode::CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2)
    : m_list1(list1)
    , m_defaultClause(defaultClause)
    , m_list2(list2)
{
}

void CaseBlockNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    if (m_list2)
        nodeStack.append(m_list2.get());
    if (m_defaultClause)
        nodeStack.append(m_defaultClause.get());
    if (m_list1)
        nodeStack.append(m_list1.get());
}

// ECMA 12.11
JSValue* CaseBlockNode::executeBlock(ExecState* exec, JSValue* input)
{
    ClauseListNode* a = m_list1.get();
    while (a) {
        CaseClauseNode* clause = a->getClause();
        a = a->getNext();
        JSValue* v = clause->evaluate(exec);
        KJS_CHECKEXCEPTION
        if (strictEqual(exec, input, v)) {
            JSValue* res = clause->executeStatements(exec);
            if (exec->completionType() != Normal)
                return res;
            for (; a; a = a->getNext()) {
                JSValue* res = a->getClause()->executeStatements(exec);
                if (exec->completionType() != Normal)
                    return res;
            }
            break;
        }
    }

    ClauseListNode* b = m_list2.get();
    while (b) {
        CaseClauseNode* clause = b->getClause();
        b = b->getNext();
        JSValue* v = clause->evaluate(exec);
        KJS_CHECKEXCEPTION
        if (strictEqual(exec, input, v)) {
            JSValue* res = clause->executeStatements(exec);
            if (exec->completionType() != Normal)
                return res;
            goto step18;
        }
    }

    // default clause
    if (m_defaultClause) {
        JSValue* res = m_defaultClause->executeStatements(exec);
        if (exec->completionType() != Normal)
            return res;
    }
    b = m_list2.get();
step18:
    while (b) {
        CaseClauseNode* clause = b->getClause();
        JSValue* res = clause->executeStatements(exec);
        if (exec->completionType() != Normal)
            return res;
        b = b->getNext();
    }

    // bail out on error
    KJS_CHECKEXCEPTION

    return exec->setNormalCompletion();
}

// ------------------------------ SwitchNode -----------------------------------

void SwitchNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_block.get());
    nodeStack.append(m_expr.get());
}

// ECMA 12.11
JSValue* SwitchNode::execute(ExecState* exec)
{
    JSValue* v = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTION

    exec->pushSwitch();
    JSValue* result = m_block->executeBlock(exec, v);
    exec->popSwitch();

    if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
        exec->setCompletionType(Normal);
    return result;
}

// ------------------------------ LabelNode ------------------------------------

void LabelNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_statement.get());
}

// ECMA 12.12
JSValue* LabelNode::execute(ExecState* exec)
{
    if (!exec->seenLabels().push(m_label))
        return setErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", m_label);
    JSValue* result = m_statement->execute(exec);
    exec->seenLabels().pop();

    if (exec->completionType() == Break && exec->breakOrContinueTarget() == m_label)
        exec->setCompletionType(Normal);
    return result;
}

// ------------------------------ ThrowNode ------------------------------------

void ThrowNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    nodeStack.append(m_expr.get());
}

// ECMA 12.13
JSValue* ThrowNode::execute(ExecState* exec)
{
    JSValue* v = m_expr->evaluate(exec);
    KJS_CHECKEXCEPTION

    handleException(exec, v);
    return exec->setThrowCompletion(v);
}

// ------------------------------ TryNode --------------------------------------

void TryNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
{
    // Can't optimize within catchBlock because "catch" introduces a dynamic scope.
    if (m_finallyBlock)
        nodeStack.append(m_finallyBlock.get());
    nodeStack.append(m_tryBlock.get());
}

// ECMA 12.14
JSValue* TryNode::execute(ExecState* exec)
{
    JSValue* result = m_tryBlock->execute(exec);

    if (m_catchBlock && exec->completionType() == Throw) {
        JSObject* obj = new JSObject;
        obj->put(exec, m_exceptionIdent, result, DontDelete);
        exec->dynamicGlobalObject()->tearOffActivation(exec);
        exec->pushScope(obj);
        result = m_catchBlock->execute(exec);
        exec->popScope();
    }

    if (m_finallyBlock) {
        ComplType savedCompletionType = exec->completionType();
        JSValue* finallyResult = m_finallyBlock->execute(exec);
        if (exec->completionType() != Normal)
            result = finallyResult;
        else
            exec->setCompletionType(savedCompletionType);
    }

    return result;
}

// ------------------------------ FunctionBodyNode -----------------------------

ScopeNode::ScopeNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
    : BlockNode(children)
    , m_sourceURL(parser().sourceURL())
    , m_sourceId(parser().sourceId())
{
    if (varStack)
        m_varStack = *varStack;
    if (funcStack)
        m_functionStack = *funcStack;
}

// ------------------------------ ProgramNode -----------------------------

ProgramNode::ProgramNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
    : ScopeNode(children, varStack, funcStack)
{
}

ProgramNode* ProgramNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
{
    return new ProgramNode(children, varStack, funcStack);
}

// ------------------------------ EvalNode -----------------------------

EvalNode::EvalNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
    : ScopeNode(children, varStack, funcStack)
{
}

EvalNode* EvalNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
{
    return new EvalNode(children, varStack, funcStack);
}

// ------------------------------ FunctionBodyNode -----------------------------

FunctionBodyNode::FunctionBodyNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
    : ScopeNode(children, varStack, funcStack)
    , m_initialized(false)
{
}

FunctionBodyNode* FunctionBodyNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack)
{
    if (Debugger::debuggersPresent)
        return new FunctionBodyNodeWithDebuggerHooks(children, varStack, funcStack);
    return new FunctionBodyNode(children, varStack, funcStack);
}

void FunctionBodyNode::initializeSymbolTable(ExecState* exec)
{
    SymbolTable& symbolTable = exec->variableObject()->symbolTable();
    ASSERT(symbolTable.isEmpty());

    size_t localStorageIndex = 0;

    // Order must match the order in processDeclarations.

    for (size_t i = 0, size = m_parameters.size(); i < size; ++i, ++localStorageIndex) {
        UString::Rep* rep = m_parameters[i].ustring().rep();
        symbolTable.set(rep, localStorageIndex);
    }

    for (size_t i = 0, size = m_functionStack.size(); i < size; ++i, ++localStorageIndex) {
        UString::Rep* rep = m_functionStack[i]->m_ident.ustring().rep();
        symbolTable.set(rep, localStorageIndex);
    }

    for (size_t i = 0, size = m_varStack.size(); i < size; ++i, ++localStorageIndex) {
        Identifier& ident = m_varStack[i].first;
        if (ident == exec->propertyNames().arguments)
            continue;
        symbolTable.add(ident.ustring().rep(), localStorageIndex);
    }
}

void ProgramNode::initializeSymbolTable(ExecState* exec)
{
    // If a previous script defined a symbol with the same name as one of our
    // symbols, to avoid breaking previously optimized nodes, we need to reuse
    // the symbol's existing storage index. So, we can't be as efficient as
    // FunctionBodyNode::initializeSymbolTable, which knows that no bindings
    // have yet been made.

    JSVariableObject* variableObject = exec->variableObject();
    SymbolTable& symbolTable = variableObject->symbolTable();

    size_t localStorageIndex = symbolTable.size();
    size_t size;

    // Order must match the order in processDeclarations.

    size = m_functionStack.size();
    m_functionIndexes.resize(size);
    for (size_t i = 0; i < size; ++i) {
        UString::Rep* rep = m_functionStack[i]->m_ident.ustring().rep();
        pair<SymbolTable::iterator, bool> result = symbolTable.add(rep, localStorageIndex);
        m_functionIndexes[i] = result.first->second;
        if (result.second)
            ++localStorageIndex;
    }

    size = m_varStack.size();
    m_varIndexes.resize(size);
    for (size_t i = 0; i < size; ++i) {
        const Identifier& ident = m_varStack[i].first;
        if (variableObject->hasProperty(exec, ident)) {
            m_varIndexes[i] = missingSymbolMarker(); // Signal not to initialize this declaration.
            continue;
        }

        UString::Rep* rep = ident.ustring().rep();
        pair<SymbolTable::iterator, bool> result = symbolTable.add(rep, localStorageIndex);
        if (!result.second) {
            m_varIndexes[i] = missingSymbolMarker(); // Signal not to initialize this declaration.
            continue;
        }

        m_varIndexes[i] = result.first->second;
        ++localStorageIndex;
    }
}

void ScopeNode::optimizeVariableAccess(ExecState* exec)
{
    NodeStack nodeStack;
    Node* node = statementListInitializeVariableAccessStack(m_children, nodeStack);
    if (!node)
        return;

    const SymbolTable& symbolTable = exec->variableObject()->symbolTable();
    const LocalStorage& localStorage = exec->variableObject()->localStorage();
    while (true) {
        node->optimizeVariableAccess(symbolTable, localStorage, nodeStack);

        size_t size = nodeStack.size();
        if (!size)
            break;
        --size;
        node = nodeStack[size];
        nodeStack.shrink(size);
    }
}

void FunctionBodyNode::processDeclarations(ExecState* exec)
{
    if (!m_initialized)
        initializeSymbolTable(exec);

    if (!m_functionStack.isEmpty())
        exec->dynamicGlobalObject()->tearOffActivation(exec);

    LocalStorage& localStorage = exec->variableObject()->localStorage();

    // We can't just resize localStorage here because that would temporarily
    // leave uninitialized entries, which would crash GC during the mark phase.
    size_t totalSize = m_varStack.size() + m_parameters.size() + m_functionStack.size();
    if (totalSize > localStorage.capacity()) // Doing this check inline avoids function call overhead.
        localStorage.reserveCapacity(totalSize);

    int minAttributes = Internal | DontDelete;

    // In order for our localStorage indexes to be correct, we must match the
    // order of addition in initializeSymbolTable().

    const List& args = *exec->arguments();
    for (size_t i = 0, size = m_parameters.size(); i < size; ++i)
        localStorage.uncheckedAppend(LocalStorageEntry(args[i], DontDelete));

    for (size_t i = 0, size = m_functionStack.size(); i < size; ++i) {
        FuncDeclNode* node = m_functionStack[i];
        localStorage.uncheckedAppend(LocalStorageEntry(node->makeFunction(exec), minAttributes));
    }

    for (size_t i = 0, size = m_varStack.size(); i < size; ++i) {
        int attributes = minAttributes;
        if (m_varStack[i].second & DeclarationStacks::IsConstant)
            attributes |= ReadOnly;
        localStorage.uncheckedAppend(LocalStorageEntry(jsUndefined(), attributes));
    }

    if (!m_initialized) {
        optimizeVariableAccess(exec);
        m_initialized = true;
    }
}

static void gccIsCrazy() KJS_FAST_CALL;
static void gccIsCrazy()
{
}

void ProgramNode::processDeclarations(ExecState* exec)
{
    // If you remove this call, some SunSpider tests, including
    // bitops-nsieve-bits.js, will regress substantially on Mac, due to a ~40%
    // increase in L2 cache misses. FIXME: <rdar://problem/5657439> WTF?
    gccIsCrazy();

    initializeSymbolTable(exec);

    LocalStorage& localStorage = exec->variableObject()->localStorage();

    // We can't just resize localStorage here because that would temporarily
    // leave uninitialized entries, which would crash GC during the mark phase.
    localStorage.reserveCapacity(localStorage.size() + m_varStack.size() + m_functionStack.size());

    int minAttributes = Internal | DontDelete;

    // In order for our localStorage indexes to be correct, we must match the
    // order of addition in initializeSymbolTable().

    for (size_t i = 0, size = m_functionStack.size(); i < size; ++i) {
        FuncDeclNode* node = m_functionStack[i];
        LocalStorageEntry entry = LocalStorageEntry(node->makeFunction(exec), minAttributes);
        size_t index = m_functionIndexes[i];

        if (index == localStorage.size())
            localStorage.uncheckedAppend(entry);
        else {
            ASSERT(index < localStorage.size());
            localStorage[index] = entry;
        }
    }

    for (size_t i = 0, size = m_varStack.size(); i < size; ++i) {
        size_t index = m_varIndexes[i];
        if (index == missingSymbolMarker())
            continue;

        int attributes = minAttributes;
        if (m_varStack[i].second & DeclarationStacks::IsConstant)
            attributes |= ReadOnly;
        LocalStorageEntry entry = LocalStorageEntry(jsUndefined(), attributes);

        ASSERT(index == localStorage.size());
        localStorage.uncheckedAppend(entry);
    }

    optimizeVariableAccess(exec);
}

void EvalNode::processDeclarations(ExecState* exec)
{
    // We could optimize access to pre-existing symbols here, but SunSpider
    // reports that to be a net loss.

    size_t i;
    size_t size;

    JSVariableObject* variableObject = exec->variableObject();

    int minAttributes = Internal;

    for (i = 0, size = m_varStack.size(); i < size; ++i) {
        Identifier& ident = m_varStack[i].first;
        if (variableObject->hasProperty(exec, ident))
            continue;
        int attributes = minAttributes;
        if (m_varStack[i].second & DeclarationStacks::IsConstant)
            attributes |= ReadOnly;
        variableObject->put(exec, ident, jsUndefined(), attributes);
    }

    for (i = 0, size = m_functionStack.size(); i < size; ++i) {
        FuncDeclNode* node = m_functionStack[i];
        variableObject->put(exec, node->m_ident, node->makeFunction(exec), minAttributes);
    }
}

UString FunctionBodyNode::paramString() const
{
    UString s("");
    size_t count = m_parameters.size();
    for (size_t pos = 0; pos < count; ++pos) {
        if (!s.isEmpty())
            s += ", ";
        s += m_parameters[pos].ustring();
    }

    return s;
}

JSValue* ProgramNode::execute(ExecState* exec)
{
    processDeclarations(exec);
    return ScopeNode::execute(exec);
}

JSValue* EvalNode::execute(ExecState* exec)
{
    processDeclarations(exec);
    return ScopeNode::execute(exec);
}

JSValue* FunctionBodyNode::execute(ExecState* exec)
{
    processDeclarations(exec);
    return ScopeNode::execute(exec);
}

// ------------------------------ FunctionBodyNodeWithDebuggerHooks ---------------------------------

FunctionBodyNodeWithDebuggerHooks::FunctionBodyNodeWithDebuggerHooks(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack)
    : FunctionBodyNode(children, varStack, funcStack)
{
}

JSValue* FunctionBodyNodeWithDebuggerHooks::execute(ExecState* exec)
{
    if (Debugger* dbg = exec->dynamicGlobalObject()->debugger()) {
        if (!dbg->callEvent(exec, sourceId(), lineNo(), exec->function(), *exec->arguments())) {
            dbg->imp()->abort();
            return exec->setInterruptedCompletion();
        }
    }

    JSValue* result = FunctionBodyNode::execute(exec);

    if (Debugger* dbg = exec->dynamicGlobalObject()->debugger()) {
        if (exec->completionType() == Throw)
            exec->setException(result);
        if (!dbg->returnEvent(exec, sourceId(), lineNo(), exec->function())) {
            dbg->imp()->abort();
            return exec->setInterruptedCompletion();
        }
    }

    return result;
}

// ------------------------------ FuncDeclNode ---------------------------------

void FuncDeclNode::addParams()
{
    for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
        m_body->parameters().append(p->ident());
}

FunctionImp* FuncDeclNode::makeFunction(ExecState* exec)
{
    FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), exec->scopeChain());

    JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
    proto->putDirect(exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
    func->putDirect(exec->propertyNames().prototype, proto, Internal | DontDelete);
    func->putDirect(exec->propertyNames().length, jsNumber(m_body->parameters().size()), ReadOnly | DontDelete | DontEnum);
    return func;
}

JSValue* FuncDeclNode::execute(ExecState* exec)
{
    return exec->setNormalCompletion();
}

// ------------------------------ FuncExprNode ---------------------------------

// ECMA 13
void FuncExprNode::addParams()
{
    for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
        m_body->parameters().append(p->ident());
}

JSValue* FuncExprNode::evaluate(ExecState* exec)
{
    exec->dynamicGlobalObject()->tearOffActivation(exec);

    bool named = !m_ident.isNull();
    JSObject* functionScopeObject = 0;

    if (named) {
        // named FunctionExpressions can recursively call themselves,
        // but they won't register with the current scope chain and should
        // be contained as single property in an anonymous object.
        functionScopeObject = new JSObject;
        exec->pushScope(functionScopeObject);
    }

    FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), exec->scopeChain());
    JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
    proto->putDirect(exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
    func->putDirect(exec->propertyNames().prototype, proto, Internal | DontDelete);

    if (named) {
        functionScopeObject->putDirect(m_ident, func, Internal | ReadOnly | (exec->codeType() == EvalCode ? 0 : DontDelete));
        exec->popScope();
    }

    return func;
}

} // namespace KJS
