2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6 * Copyright (C) 2007 Maks Orlovich
7 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
29 #include "CodeGenerator.h"
30 #include "ExecState.h"
31 #include "JSGlobalObject.h"
33 #include "PropertyNameArray.h"
34 #include "array_object.h"
36 #include "function_object.h"
38 #include "operations.h"
39 #include "regexp_object.h"
41 #include <wtf/Assertions.h>
42 #include <wtf/HashCountedSet.h>
43 #include <wtf/HashSet.h>
44 #include <wtf/MathExtras.h>
48 class FunctionBodyNodeWithDebuggerHooks : public FunctionBodyNode {
50 FunctionBodyNodeWithDebuggerHooks(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
51 virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
56 __builtin_expect ((x), 0)
61 #define KJS_CHECKEXCEPTION \
62 if (UNLIKELY(exec->hadException())) \
63 return rethrowException(exec);
65 #define KJS_CHECKEXCEPTIONVALUE \
66 if (UNLIKELY(exec->hadException())) { \
67 handleException(exec); \
68 return jsUndefined(); \
71 #define KJS_CHECKEXCEPTIONNUMBER \
72 if (UNLIKELY(exec->hadException())) { \
73 handleException(exec); \
77 #define KJS_CHECKEXCEPTIONBOOLEAN \
78 if (UNLIKELY(exec->hadException())) { \
79 handleException(exec); \
83 #define KJS_CHECKEXCEPTIONVOID \
84 if (UNLIKELY(exec->hadException())) { \
85 handleException(exec); \
90 static inline bool canSkipLookup(OldInterpreterExecState* exec, const Identifier& ident)
92 // Static lookup in EvalCode is impossible because variables aren't DontDelete.
93 // Static lookup in GlobalCode may be possible, but we haven't implemented support for it yet.
94 if (exec->codeType() != FunctionCode)
97 // Static lookup is impossible when something dynamic has been added to the front of the scope chain.
98 if (exec->variableObject() != exec->scopeChain().top())
101 // Static lookup is impossible if the symbol isn't statically declared.
102 if (!exec->variableObject()->symbolTable().contains(ident.ustring().rep()))
109 static inline bool isConstant(const LocalStorage& localStorage, size_t index)
111 ASSERT(index < localStorage.size());
112 return localStorage[index].attributes & ReadOnly;
115 static inline UString::Rep* rep(const Identifier& ident)
117 return ident.ustring().rep();
120 // ------------------------------ Node -----------------------------------------
123 #ifndef LOG_CHANNEL_PREFIX
124 #define LOG_CHANNEL_PREFIX Log
126 static WTFLogChannel LogKJSNodeLeaks = { 0x00000000, "", WTFLogChannelOn };
128 struct ParserRefCountedCounter {
129 static unsigned count;
130 ParserRefCountedCounter()
133 LOG(KJSNodeLeaks, "LEAK: %u KJS::Node\n", count);
136 unsigned ParserRefCountedCounter::count = 0;
137 static ParserRefCountedCounter parserRefCountedCounter;
140 static HashSet<ParserRefCounted*>* newTrackedObjects;
141 static HashCountedSet<ParserRefCounted*>* trackedObjectExtraRefCounts;
143 ParserRefCounted::ParserRefCounted()
146 ++ParserRefCountedCounter::count;
148 if (!newTrackedObjects)
149 newTrackedObjects = new HashSet<ParserRefCounted*>;
150 newTrackedObjects->add(this);
151 ASSERT(newTrackedObjects->contains(this));
154 ParserRefCounted::~ParserRefCounted()
157 --ParserRefCountedCounter::count;
161 void ParserRefCounted::ref()
163 // bumping from 0 to 1 is just removing from the new nodes set
164 if (newTrackedObjects) {
165 HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->find(this);
166 if (it != newTrackedObjects->end()) {
167 newTrackedObjects->remove(it);
168 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
173 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
175 if (!trackedObjectExtraRefCounts)
176 trackedObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
177 trackedObjectExtraRefCounts->add(this);
180 void ParserRefCounted::deref()
182 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
184 if (!trackedObjectExtraRefCounts) {
189 HashCountedSet<ParserRefCounted*>::iterator it = trackedObjectExtraRefCounts->find(this);
190 if (it == trackedObjectExtraRefCounts->end())
193 trackedObjectExtraRefCounts->remove(it);
196 unsigned ParserRefCounted::refcount()
198 if (newTrackedObjects && newTrackedObjects->contains(this)) {
199 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
203 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
205 if (!trackedObjectExtraRefCounts)
208 return 1 + trackedObjectExtraRefCounts->count(this);
211 void ParserRefCounted::deleteNewObjects()
213 if (!newTrackedObjects)
217 HashSet<ParserRefCounted*>::iterator end = newTrackedObjects->end();
218 for (HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->begin(); it != end; ++it)
219 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(*it));
221 deleteAllValues(*newTrackedObjects);
222 delete newTrackedObjects;
223 newTrackedObjects = 0;
227 : m_expectedReturnType(ObjectType)
229 m_line = lexer().lineNo();
232 Node::Node(JSType expectedReturn)
233 : m_expectedReturnType(expectedReturn)
235 m_line = lexer().lineNo();
238 double ExpressionNode::evaluateToNumber(OldInterpreterExecState* exec)
240 JSValue* value = evaluate(exec);
241 KJS_CHECKEXCEPTIONNUMBER
242 return value->toNumber(exec);
245 bool ExpressionNode::evaluateToBoolean(OldInterpreterExecState* exec)
247 JSValue* value = evaluate(exec);
248 KJS_CHECKEXCEPTIONBOOLEAN
249 return value->toBoolean(exec);
252 int32_t ExpressionNode::evaluateToInt32(OldInterpreterExecState* exec)
254 JSValue* value = evaluate(exec);
255 KJS_CHECKEXCEPTIONNUMBER
256 return value->toInt32(exec);
259 uint32_t ExpressionNode::evaluateToUInt32(OldInterpreterExecState* exec)
261 JSValue* value = evaluate(exec);
262 KJS_CHECKEXCEPTIONNUMBER
263 return value->toUInt32(exec);
266 static void substitute(UString& string, const UString& substring) KJS_FAST_CALL;
267 static void substitute(UString& string, const UString& substring)
269 int position = string.find("%s");
270 ASSERT(position != -1);
271 UString newString = string.substr(0, position);
272 newString.append(substring);
273 newString.append(string.substr(position + 2));
277 static inline int currentSourceId(ExecState* exec) KJS_FAST_CALL;
278 static inline int currentSourceId(ExecState*)
280 ASSERT_NOT_REACHED();
284 static inline const UString currentSourceURL(ExecState* exec) KJS_FAST_CALL;
285 static inline const UString currentSourceURL(ExecState*)
287 ASSERT_NOT_REACHED();
291 JSValue* Node::setErrorCompletion(OldInterpreterExecState* exec, ErrorType e, const char* msg)
293 return exec->setThrowCompletion(Error::create(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
296 JSValue* Node::setErrorCompletion(OldInterpreterExecState* exec, ErrorType e, const char* msg, const Identifier& ident)
298 UString message = msg;
299 substitute(message, ident.ustring());
300 return exec->setThrowCompletion(Error::create(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
303 JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg)
305 return KJS::throwError(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec));
308 JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, const char* string)
310 UString message = msg;
311 substitute(message, string);
312 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
315 JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr)
317 UString message = msg;
318 substitute(message, v->toString(exec));
319 substitute(message, expr->toString());
320 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
323 JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, const Identifier& label)
325 UString message = msg;
326 substitute(message, label.ustring());
327 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
330 JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* e1, Node* e2)
332 UString message = msg;
333 substitute(message, v->toString(exec));
334 substitute(message, e1->toString());
335 substitute(message, e2->toString());
336 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
339 JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr, const Identifier& label)
341 UString message = msg;
342 substitute(message, v->toString(exec));
343 substitute(message, expr->toString());
344 substitute(message, label.ustring());
345 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
348 JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, const Identifier& label)
350 UString message = msg;
351 substitute(message, v->toString(exec));
352 substitute(message, label.ustring());
353 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
356 JSValue* Node::throwUndefinedVariableError(OldInterpreterExecState* exec, const Identifier& ident)
358 return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
361 void Node::handleException(OldInterpreterExecState* exec)
363 handleException(exec, exec->exception());
366 void Node::handleException(OldInterpreterExecState* exec, JSValue* exceptionValue)
368 if (exceptionValue->isObject()) {
369 JSObject* exception = static_cast<JSObject*>(exceptionValue);
370 if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
371 exception->put(exec, "line", jsNumber(m_line));
372 exception->put(exec, "sourceURL", jsString(currentSourceURL(exec)));
376 Debugger* dbg = exec->dynamicGlobalObject()->debugger();
377 if (dbg && !dbg->hasHandledException(exec, exceptionValue))
378 dbg->exception(exec, currentSourceId(exec), m_line, exceptionValue);
382 NEVER_INLINE JSValue* Node::rethrowException(OldInterpreterExecState* exec)
384 JSValue* exception = exec->exception();
385 exec->clearException();
386 handleException(exec, exception);
387 return exec->setThrowCompletion(exception);
390 RegisterID* Node::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg)
392 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(msg));
393 generator.emitThrow(exception);
397 RegisterID* Node::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
399 UString message = msg;
400 substitute(message, label.ustring());
401 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(message));
402 generator.emitThrow(exception);
406 // ------------------------------ StatementNode --------------------------------
408 StatementNode::StatementNode()
414 void StatementNode::setLoc(int firstLine, int lastLine)
417 m_lastLine = lastLine;
420 // ------------------------------ SourceElements --------------------------------
422 void SourceElements::append(PassRefPtr<StatementNode> statement)
424 if (statement->isEmptyStatement())
427 m_statements.append(statement);
430 // ------------------------------ BreakpointCheckStatement --------------------------------
432 BreakpointCheckStatement::BreakpointCheckStatement(PassRefPtr<StatementNode> statement)
433 : m_statement(statement)
438 JSValue* BreakpointCheckStatement::execute(OldInterpreterExecState* exec)
440 return m_statement->execute(exec);
443 void BreakpointCheckStatement::streamTo(SourceStream& stream) const
445 m_statement->streamTo(stream);
448 void BreakpointCheckStatement::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
450 nodeStack.append(m_statement.get());
453 // ------------------------------ NullNode -------------------------------------
455 RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst)
457 return generator.emitLoad(generator.finalDestination(dst), jsNull());
460 JSValue* NullNode::evaluate(OldInterpreterExecState* )
465 // ------------------------------ FalseNode ----------------------------------
467 RegisterID* FalseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
469 return generator.emitLoad(generator.finalDestination(dst), false);
472 JSValue* FalseNode::evaluate(OldInterpreterExecState*)
474 return jsBoolean(false);
477 // ------------------------------ TrueNode ----------------------------------
479 RegisterID* TrueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
481 return generator.emitLoad(generator.finalDestination(dst), true);
484 JSValue* TrueNode::evaluate(OldInterpreterExecState*)
486 return jsBoolean(true);
489 // ------------------------------ NumberNode -----------------------------------
491 RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst)
493 return generator.emitLoad(generator.finalDestination(dst), m_double);
496 JSValue* NumberNode::evaluate(OldInterpreterExecState*)
498 // Number nodes are only created when the number can't fit in a JSImmediate, so no need to check again.
499 return jsNumberCell(m_double);
502 double NumberNode::evaluateToNumber(OldInterpreterExecState*)
507 bool NumberNode::evaluateToBoolean(OldInterpreterExecState*)
509 return m_double < 0.0 || m_double > 0.0; // false for NaN as well as 0
512 int32_t NumberNode::evaluateToInt32(OldInterpreterExecState*)
514 return JSValue::toInt32(m_double);
517 uint32_t NumberNode::evaluateToUInt32(OldInterpreterExecState*)
519 return JSValue::toUInt32(m_double);
522 // ------------------------------ ImmediateNumberNode -----------------------------------
524 JSValue* ImmediateNumberNode::evaluate(OldInterpreterExecState*)
529 int32_t ImmediateNumberNode::evaluateToInt32(OldInterpreterExecState*)
531 return JSImmediate::getTruncatedInt32(m_value);
534 uint32_t ImmediateNumberNode::evaluateToUInt32(OldInterpreterExecState*)
537 if (JSImmediate::getTruncatedUInt32(m_value, i))
540 return JSValue::toUInt32SlowCase(m_double, ok);
543 // ------------------------------ StringNode -----------------------------------
545 RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
547 // FIXME: should we try to atomize constant strings?
548 return generator.emitLoad(generator.finalDestination(dst), jsOwnedString(m_value));
551 JSValue* StringNode::evaluate(OldInterpreterExecState*)
553 return jsOwnedString(m_value);
556 double StringNode::evaluateToNumber(OldInterpreterExecState*)
558 return m_value.toDouble();
561 bool StringNode::evaluateToBoolean(OldInterpreterExecState*)
563 return !m_value.isEmpty();
566 // ------------------------------ RegExpNode -----------------------------------
568 RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
570 if (!m_regExp->isValid())
571 return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", m_regExp->errorMessage());
572 return generator.emitNewRegExp(generator.finalDestination(dst), m_regExp.get());
575 JSValue* RegExpNode::evaluate(OldInterpreterExecState*)
577 ASSERT_NOT_REACHED();
581 // ------------------------------ ThisNode -------------------------------------
583 RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
585 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
589 JSValue* ThisNode::evaluate(OldInterpreterExecState* exec)
591 return exec->thisValue();
594 // ------------------------------ ResolveNode ----------------------------------
596 RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
598 if (RegisterID* local = generator.registerForLocal(m_ident))
599 return generator.moveToDestinationIfNeeded(dst, local);
601 return generator.emitResolve(generator.finalDestination(dst), m_ident);
604 // ECMA 11.1.2 & 10.1.4
605 JSValue* ResolveNode::inlineEvaluate(OldInterpreterExecState* exec)
607 // Check for missed optimization opportunity.
608 ASSERT(!canSkipLookup(exec, m_ident));
610 const ScopeChain& chain = exec->scopeChain();
611 ScopeChainIterator iter = chain.begin();
612 ScopeChainIterator end = chain.end();
614 // we must always have something in the scope chain
621 if (o->getPropertySlot(exec, m_ident, slot))
622 return slot.getValue(exec, o, m_ident);
625 } while (iter != end);
627 return throwUndefinedVariableError(exec, m_ident);
630 JSValue* ResolveNode::evaluate(OldInterpreterExecState* exec)
632 return inlineEvaluate(exec);
635 double ResolveNode::evaluateToNumber(OldInterpreterExecState* exec)
637 JSValue* v = inlineEvaluate(exec);
638 KJS_CHECKEXCEPTIONNUMBER
639 return v->toNumber(exec);
642 bool ResolveNode::evaluateToBoolean(OldInterpreterExecState* exec)
644 JSValue* v = inlineEvaluate(exec);
645 KJS_CHECKEXCEPTIONBOOLEAN
646 return v->toBoolean(exec);
649 int32_t ResolveNode::evaluateToInt32(OldInterpreterExecState* exec)
651 JSValue* v = inlineEvaluate(exec);
652 KJS_CHECKEXCEPTIONNUMBER
653 return v->toInt32(exec);
656 uint32_t ResolveNode::evaluateToUInt32(OldInterpreterExecState* exec)
658 JSValue* v = inlineEvaluate(exec);
659 KJS_CHECKEXCEPTIONNUMBER
660 return v->toUInt32(exec);
663 static size_t getSymbolTableEntry(OldInterpreterExecState* exec, const Identifier& ident, const SymbolTable& symbolTable, size_t& stackDepth)
665 int index = symbolTable.get(ident.ustring().rep()).getIndex();
666 if (index != missingSymbolMarker()) {
671 if (ident == exec->propertyNames().arguments) {
673 return missingSymbolMarker();
676 const ScopeChain& chain = exec->scopeChain();
677 ScopeChainIterator iter = chain.begin();
678 ScopeChainIterator end = chain.end();
680 for (; iter != end; ++iter, ++depth) {
681 JSObject* currentScope = *iter;
682 if (!currentScope->isVariableObject())
684 JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
685 index = currentVariableObject->symbolTable().get(ident.ustring().rep()).getIndex();
686 if (index != missingSymbolMarker()) {
690 if (currentVariableObject->isDynamicScope())
694 return missingSymbolMarker();
697 void ResolveNode::optimizeVariableAccess(OldInterpreterExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
700 int index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
701 if (index != missingSymbolMarker()) {
703 new (this) LocalVarAccessNode(index);
705 new (this) ScopedVarAccessNode(index, depth);
712 new (this) NonLocalVarAccessNode(depth);
715 JSValue* LocalVarAccessNode::inlineEvaluate(OldInterpreterExecState* exec)
717 ASSERT(exec->variableObject() == exec->scopeChain().top());
718 return exec->localStorage()[m_index].value;
721 JSValue* LocalVarAccessNode::evaluate(OldInterpreterExecState* exec)
723 return inlineEvaluate(exec);
726 double LocalVarAccessNode::evaluateToNumber(OldInterpreterExecState* exec)
728 return inlineEvaluate(exec)->toNumber(exec);
731 bool LocalVarAccessNode::evaluateToBoolean(OldInterpreterExecState* exec)
733 return inlineEvaluate(exec)->toBoolean(exec);
736 int32_t LocalVarAccessNode::evaluateToInt32(OldInterpreterExecState* exec)
738 return inlineEvaluate(exec)->toInt32(exec);
741 uint32_t LocalVarAccessNode::evaluateToUInt32(OldInterpreterExecState* exec)
743 return inlineEvaluate(exec)->toUInt32(exec);
746 static inline JSValue* getNonLocalSymbol(OldInterpreterExecState* exec, size_t, size_t scopeDepth)
748 const ScopeChain& chain = exec->scopeChain();
749 ScopeChainIterator iter = chain.begin();
750 for (size_t i = 0; i < scopeDepth; ++iter, ++i)
751 ASSERT(iter != chain.end());
753 JSObject* scope = *iter;
755 ASSERT(scope->isVariableObject());
756 ASSERT_NOT_REACHED();
760 JSValue* ScopedVarAccessNode::inlineEvaluate(OldInterpreterExecState* exec)
762 return getNonLocalSymbol(exec, m_index, m_scopeDepth);
765 JSValue* ScopedVarAccessNode::evaluate(OldInterpreterExecState* exec)
767 return inlineEvaluate(exec);
770 double ScopedVarAccessNode::evaluateToNumber(OldInterpreterExecState* exec)
772 return inlineEvaluate(exec)->toNumber(exec);
775 bool ScopedVarAccessNode::evaluateToBoolean(OldInterpreterExecState* exec)
777 return inlineEvaluate(exec)->toBoolean(exec);
780 int32_t ScopedVarAccessNode::evaluateToInt32(OldInterpreterExecState* exec)
782 return inlineEvaluate(exec)->toInt32(exec);
785 uint32_t ScopedVarAccessNode::evaluateToUInt32(OldInterpreterExecState* exec)
787 return inlineEvaluate(exec)->toUInt32(exec);
790 JSValue* NonLocalVarAccessNode::inlineEvaluate(OldInterpreterExecState* exec)
792 // Check for missed optimization opportunity.
793 ASSERT(!canSkipLookup(exec, m_ident));
795 const ScopeChain& chain = exec->scopeChain();
796 ScopeChainIterator iter = chain.begin();
797 ScopeChainIterator end = chain.end();
798 for (size_t i = 0; i < m_scopeDepth; ++i, ++iter)
801 // we must always have something in the scope chain
808 if (o->getPropertySlot(exec, m_ident, slot))
809 return slot.getValue(exec, o, m_ident);
812 } while (iter != end);
814 return throwUndefinedVariableError(exec, m_ident);
817 JSValue* NonLocalVarAccessNode::evaluate(OldInterpreterExecState* exec)
819 return inlineEvaluate(exec);
822 double NonLocalVarAccessNode::evaluateToNumber(OldInterpreterExecState* exec)
824 return inlineEvaluate(exec)->toNumber(exec);
827 bool NonLocalVarAccessNode::evaluateToBoolean(OldInterpreterExecState* exec)
829 return inlineEvaluate(exec)->toBoolean(exec);
832 int32_t NonLocalVarAccessNode::evaluateToInt32(OldInterpreterExecState* exec)
834 return inlineEvaluate(exec)->toInt32(exec);
837 uint32_t NonLocalVarAccessNode::evaluateToUInt32(OldInterpreterExecState* exec)
839 return inlineEvaluate(exec)->toUInt32(exec);
842 // ------------------------------ ElementNode ----------------------------------
844 void ElementNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
847 nodeStack.append(m_next.get());
849 nodeStack.append(m_node.get());
853 JSValue* ElementNode::evaluate(OldInterpreterExecState* exec)
855 JSObject* array = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
857 for (ElementNode* n = this; n; n = n->m_next.get()) {
858 JSValue* val = n->m_node->evaluate(exec);
859 KJS_CHECKEXCEPTIONVALUE
860 length += n->m_elision;
861 array->put(exec, length++, val);
866 // ------------------------------ ArrayNode ------------------------------------
869 RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst)
871 RefPtr<RegisterID> newArray = generator.emitNewArray(generator.tempDestination(dst));
875 for (ElementNode* n = m_element.get(); n; n = n->m_next.get()) {
876 value = generator.emitNode(n->m_node.get());
877 length += n->m_elision;
878 generator.emitPutByIndex(newArray.get(), length++, value);
881 value = generator.emitLoad(generator.newTemporary(), jsNumber(m_elision + length));
882 generator.emitPutById(newArray.get(), generator.propertyNames().length, value);
884 return generator.moveToDestinationIfNeeded(dst, newArray.get());
887 void ArrayNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
890 nodeStack.append(m_element.get());
894 JSValue* ArrayNode::evaluate(OldInterpreterExecState* exec)
900 array = static_cast<JSObject*>(m_element->evaluate(exec));
901 KJS_CHECKEXCEPTIONVALUE
902 length = m_optional ? array->get(exec, exec->propertyNames().length)->toInt32(exec) : 0;
904 JSValue* newArr = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
905 array = static_cast<JSObject*>(newArr);
910 array->put(exec, exec->propertyNames().length, jsNumber(m_elision + length));
915 // ------------------------------ ObjectLiteralNode ----------------------------
917 RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst)
920 return generator.emitNode(dst, m_list.get());
922 return generator.emitNewObject(generator.finalDestination(dst));
925 void ObjectLiteralNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
928 nodeStack.append(m_list.get());
932 JSValue* ObjectLiteralNode::evaluate(OldInterpreterExecState* exec)
935 return m_list->evaluate(exec);
937 return exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
940 // ------------------------------ PropertyListNode -----------------------------
942 RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
944 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
946 generator.emitNewObject(newObj.get());
948 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
949 RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
951 switch (p->m_node->m_type) {
952 case PropertyNode::Constant: {
953 generator.emitPutById(newObj.get(), p->m_node->name(), value);
956 case PropertyNode::Getter: {
957 generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
960 case PropertyNode::Setter: {
961 generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
965 ASSERT_NOT_REACHED();
969 return generator.moveToDestinationIfNeeded(dst, newObj.get());
972 void PropertyListNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
975 nodeStack.append(m_next.get());
976 nodeStack.append(m_node.get());
980 JSValue* PropertyListNode::evaluate(OldInterpreterExecState* exec)
982 JSObject* obj = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
984 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
985 JSValue* v = p->m_node->m_assign->evaluate(exec);
986 KJS_CHECKEXCEPTIONVALUE
988 switch (p->m_node->m_type) {
989 case PropertyNode::Getter:
990 ASSERT(v->isObject());
991 obj->defineGetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
993 case PropertyNode::Setter:
994 ASSERT(v->isObject());
995 obj->defineSetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
997 case PropertyNode::Constant:
998 obj->put(exec, p->m_node->name(), v);
1006 // ------------------------------ PropertyNode -----------------------------
1008 void PropertyNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1010 nodeStack.append(m_assign.get());
1014 JSValue* PropertyNode::evaluate(OldInterpreterExecState*)
1020 // ------------------------------ BracketAccessorNode --------------------------------
1022 RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1024 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1025 RegisterID* property = generator.emitNode(m_subscript.get());
1027 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
1030 void BracketAccessorNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1032 nodeStack.append(m_subscript.get());
1033 nodeStack.append(m_base.get());
1037 JSValue* BracketAccessorNode::inlineEvaluate(OldInterpreterExecState* exec)
1039 JSValue* v1 = m_base->evaluate(exec);
1040 KJS_CHECKEXCEPTIONVALUE
1041 JSValue* v2 = m_subscript->evaluate(exec);
1042 KJS_CHECKEXCEPTIONVALUE
1043 JSObject* o = v1->toObject(exec);
1045 if (v2->getUInt32(i))
1046 return o->get(exec, i);
1047 return o->get(exec, Identifier(v2->toString(exec)));
1050 JSValue* BracketAccessorNode::evaluate(OldInterpreterExecState* exec)
1052 return inlineEvaluate(exec);
1055 double BracketAccessorNode::evaluateToNumber(OldInterpreterExecState* exec)
1057 JSValue* v = inlineEvaluate(exec);
1058 KJS_CHECKEXCEPTIONNUMBER
1059 return v->toNumber(exec);
1062 bool BracketAccessorNode::evaluateToBoolean(OldInterpreterExecState* exec)
1064 JSValue* v = inlineEvaluate(exec);
1065 KJS_CHECKEXCEPTIONBOOLEAN
1066 return v->toBoolean(exec);
1069 int32_t BracketAccessorNode::evaluateToInt32(OldInterpreterExecState* exec)
1071 JSValue* v = inlineEvaluate(exec);
1072 KJS_CHECKEXCEPTIONNUMBER
1073 return v->toInt32(exec);
1076 uint32_t BracketAccessorNode::evaluateToUInt32(OldInterpreterExecState* exec)
1078 JSValue* v = inlineEvaluate(exec);
1079 KJS_CHECKEXCEPTIONNUMBER
1080 return v->toUInt32(exec);
1083 // ------------------------------ DotAccessorNode --------------------------------
1085 RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1087 RegisterID* base = generator.emitNode(m_base.get());
1088 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
1091 void DotAccessorNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1093 nodeStack.append(m_base.get());
1097 JSValue* DotAccessorNode::inlineEvaluate(OldInterpreterExecState* exec)
1099 JSValue* v = m_base->evaluate(exec);
1100 KJS_CHECKEXCEPTIONVALUE
1101 return v->toObject(exec)->get(exec, m_ident);
1104 JSValue* DotAccessorNode::evaluate(OldInterpreterExecState* exec)
1106 return inlineEvaluate(exec);
1109 double DotAccessorNode::evaluateToNumber(OldInterpreterExecState* exec)
1111 JSValue* v = inlineEvaluate(exec);
1112 KJS_CHECKEXCEPTIONNUMBER
1113 return v->toNumber(exec);
1116 bool DotAccessorNode::evaluateToBoolean(OldInterpreterExecState* exec)
1118 JSValue* v = inlineEvaluate(exec);
1119 KJS_CHECKEXCEPTIONBOOLEAN
1120 return v->toBoolean(exec);
1123 int32_t DotAccessorNode::evaluateToInt32(OldInterpreterExecState* exec)
1125 JSValue* v = inlineEvaluate(exec);
1126 KJS_CHECKEXCEPTIONNUMBER
1127 return v->toInt32(exec);
1130 uint32_t DotAccessorNode::evaluateToUInt32(OldInterpreterExecState* exec)
1132 JSValue* v = inlineEvaluate(exec);
1133 KJS_CHECKEXCEPTIONNUMBER
1134 return v->toUInt32(exec);
1137 // ------------------------------ ArgumentListNode -----------------------------
1139 RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1142 return generator.emitNode(dst, m_expr.get());
1145 void ArgumentListNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1148 nodeStack.append(m_next.get());
1150 nodeStack.append(m_expr.get());
1154 void ArgumentListNode::evaluateList(OldInterpreterExecState* exec, List& list)
1156 for (ArgumentListNode* n = this; n; n = n->m_next.get()) {
1157 JSValue* v = n->m_expr->evaluate(exec);
1158 KJS_CHECKEXCEPTIONVOID
1163 // ------------------------------ ArgumentsNode --------------------------------
1165 void ArgumentsNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1168 nodeStack.append(m_listNode.get());
1171 // ------------------------------ NewExprNode ----------------------------------
1173 RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1175 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
1176 return generator.emitConstruct(generator.finalDestination(dst), r0.get(), m_args.get());
1179 void NewExprNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1182 nodeStack.append(m_args.get());
1183 nodeStack.append(m_expr.get());
1188 JSValue* NewExprNode::inlineEvaluate(OldInterpreterExecState* exec)
1190 JSValue* v = m_expr->evaluate(exec);
1191 KJS_CHECKEXCEPTIONVALUE
1195 m_args->evaluateList(exec, argList);
1196 KJS_CHECKEXCEPTIONVALUE
1200 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, m_expr.get());
1202 ConstructData constructData;
1203 if (v->getConstructData(constructData) == ConstructTypeNone)
1204 return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, m_expr.get());
1206 return static_cast<JSObject*>(v)->construct(exec, argList);
1209 JSValue* NewExprNode::evaluate(OldInterpreterExecState* exec)
1211 return inlineEvaluate(exec);
1214 double NewExprNode::evaluateToNumber(OldInterpreterExecState* exec)
1216 JSValue* v = inlineEvaluate(exec);
1217 KJS_CHECKEXCEPTIONNUMBER
1218 return v->toNumber(exec);
1221 bool NewExprNode::evaluateToBoolean(OldInterpreterExecState* exec)
1223 JSValue* v = inlineEvaluate(exec);
1224 KJS_CHECKEXCEPTIONBOOLEAN
1225 return v->toBoolean(exec);
1228 int32_t NewExprNode::evaluateToInt32(OldInterpreterExecState* exec)
1230 JSValue* v = inlineEvaluate(exec);
1231 KJS_CHECKEXCEPTIONNUMBER
1232 return v->toInt32(exec);
1235 uint32_t NewExprNode::evaluateToUInt32(OldInterpreterExecState* exec)
1237 JSValue* v = inlineEvaluate(exec);
1238 KJS_CHECKEXCEPTIONNUMBER
1239 return v->toUInt32(exec);
1242 template <ExpressionNode::CallerType callerType, bool scopeDepthIsZero>
1243 inline JSValue* ExpressionNode::resolveAndCall(OldInterpreterExecState* exec, const Identifier& ident, ArgumentsNode* args, size_t scopeDepth)
1245 const ScopeChain& chain = exec->scopeChain();
1246 ScopeChainIterator iter = chain.begin();
1247 ScopeChainIterator end = chain.end();
1249 if (!scopeDepthIsZero) {
1250 for (size_t i = 0; i < scopeDepth; ++iter, ++i)
1251 ASSERT(iter != chain.end());
1254 // we must always have something in the scope chain
1255 ASSERT(iter != end);
1261 if (base->getPropertySlot(exec, ident, slot)) {
1262 JSValue* v = slot.getValue(exec, base, ident);
1263 KJS_CHECKEXCEPTIONVALUE
1266 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
1268 JSObject* func = static_cast<JSObject*>(v);
1270 if (!func->implementsCall())
1271 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
1274 args->evaluateList(exec, argList);
1275 KJS_CHECKEXCEPTIONVALUE
1277 if (callerType == EvalOperator) {
1278 if (base == exec->lexicalGlobalObject() && func == exec->lexicalGlobalObject()->evalFunction()) {
1279 ASSERT_NOT_REACHED();
1283 JSObject* thisObj = base->toThisObject(exec);
1284 return func->call(exec, thisObj, argList);
1287 } while (iter != end);
1289 return throwUndefinedVariableError(exec, ident);
1292 RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1294 RefPtr<RegisterID> base = generator.tempDestination(dst);
1295 RegisterID* func = generator.newTemporary();
1296 generator.emitResolveWithBase(base.get(), func, CommonIdentifiers::shared()->eval);
1297 return generator.emitCallEval(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get());
1300 void EvalFunctionCallNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1302 nodeStack.append(m_args.get());
1305 JSValue* EvalFunctionCallNode::evaluate(OldInterpreterExecState* exec)
1307 return resolveAndCall<EvalOperator, true>(exec, exec->propertyNames().eval, m_args.get());
1310 RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1312 RegisterID* r0 = generator.emitNode(m_expr.get());
1313 return generator.emitCall(generator.finalDestination(dst), r0, 0, m_args.get());
1316 void FunctionCallValueNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1318 nodeStack.append(m_args.get());
1319 nodeStack.append(m_expr.get());
1323 JSValue* FunctionCallValueNode::evaluate(OldInterpreterExecState* exec)
1325 JSValue* v = m_expr->evaluate(exec);
1326 KJS_CHECKEXCEPTIONVALUE
1328 if (!v->isObject()) {
1329 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_expr.get());
1332 JSObject* func = static_cast<JSObject*>(v);
1334 if (!func->implementsCall()) {
1335 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_expr.get());
1339 m_args->evaluateList(exec, argList);
1340 KJS_CHECKEXCEPTIONVALUE
1342 JSObject* thisObj = exec->globalThisValue();
1343 return func->call(exec, thisObj, argList);
1346 RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1348 if (RegisterID* local = generator.registerForLocal(m_ident))
1349 return generator.emitCall(generator.finalDestination(dst), local, 0, m_args.get());
1353 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
1354 RegisterID* func = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
1355 return generator.emitCall(generator.finalDestination(dst), func, 0, m_args.get());
1358 RefPtr<RegisterID> base = generator.tempDestination(dst);
1359 RegisterID* func = generator.newTemporary();
1360 generator.emitResolveFunction(base.get(), func, m_ident);
1361 return generator.emitCall(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get());
1364 void FunctionCallResolveNode::optimizeVariableAccess(OldInterpreterExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
1366 nodeStack.append(m_args.get());
1369 int index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
1370 if (index != missingSymbolMarker()) {
1372 new (this) LocalVarFunctionCallNode(index);
1374 new (this) ScopedVarFunctionCallNode(index, depth);
1381 new (this) NonLocalVarFunctionCallNode(depth);
1385 JSValue* FunctionCallResolveNode::inlineEvaluate(OldInterpreterExecState* exec)
1387 // Check for missed optimization opportunity.
1388 ASSERT(!canSkipLookup(exec, m_ident));
1390 return resolveAndCall<FunctionCall, true>(exec, m_ident, m_args.get());
1393 JSValue* FunctionCallResolveNode::evaluate(OldInterpreterExecState* exec)
1395 return inlineEvaluate(exec);
1398 double FunctionCallResolveNode::evaluateToNumber(OldInterpreterExecState* exec)
1400 JSValue* v = inlineEvaluate(exec);
1401 KJS_CHECKEXCEPTIONNUMBER
1402 return v->toNumber(exec);
1405 bool FunctionCallResolveNode::evaluateToBoolean(OldInterpreterExecState* exec)
1407 JSValue* v = inlineEvaluate(exec);
1408 KJS_CHECKEXCEPTIONBOOLEAN
1409 return v->toBoolean(exec);
1412 int32_t FunctionCallResolveNode::evaluateToInt32(OldInterpreterExecState* exec)
1414 JSValue* v = inlineEvaluate(exec);
1415 KJS_CHECKEXCEPTIONNUMBER
1416 return v->toInt32(exec);
1419 uint32_t FunctionCallResolveNode::evaluateToUInt32(OldInterpreterExecState* exec)
1421 JSValue* v = inlineEvaluate(exec);
1422 KJS_CHECKEXCEPTIONNUMBER
1423 return v->toUInt32(exec);
1426 JSValue* LocalVarFunctionCallNode::inlineEvaluate(OldInterpreterExecState* exec)
1428 ASSERT(exec->variableObject() == exec->scopeChain().top());
1430 JSValue* v = exec->localStorage()[m_index].value;
1433 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
1435 JSObject* func = static_cast<JSObject*>(v);
1436 if (!func->implementsCall())
1437 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
1440 m_args->evaluateList(exec, argList);
1441 KJS_CHECKEXCEPTIONVALUE
1443 JSObject* thisObj = exec->globalThisValue();
1444 return func->call(exec, thisObj, argList);
1447 JSValue* LocalVarFunctionCallNode::evaluate(OldInterpreterExecState* exec)
1449 return inlineEvaluate(exec);
1452 double LocalVarFunctionCallNode::evaluateToNumber(OldInterpreterExecState* exec)
1454 JSValue* v = inlineEvaluate(exec);
1455 KJS_CHECKEXCEPTIONNUMBER
1456 return v->toNumber(exec);
1459 bool LocalVarFunctionCallNode::evaluateToBoolean(OldInterpreterExecState* exec)
1461 JSValue* v = inlineEvaluate(exec);
1462 KJS_CHECKEXCEPTIONBOOLEAN
1463 return v->toBoolean(exec);
1466 int32_t LocalVarFunctionCallNode::evaluateToInt32(OldInterpreterExecState* exec)
1468 JSValue* v = inlineEvaluate(exec);
1469 KJS_CHECKEXCEPTIONNUMBER
1470 return v->toInt32(exec);
1473 uint32_t LocalVarFunctionCallNode::evaluateToUInt32(OldInterpreterExecState* exec)
1475 JSValue* v = inlineEvaluate(exec);
1476 KJS_CHECKEXCEPTIONNUMBER
1477 return v->toUInt32(exec);
1480 JSValue* ScopedVarFunctionCallNode::inlineEvaluate(OldInterpreterExecState* exec)
1482 ASSERT(exec->variableObject() == exec->scopeChain().top());
1484 JSValue* v = getNonLocalSymbol(exec, m_index, m_scopeDepth);
1487 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
1489 JSObject* func = static_cast<JSObject*>(v);
1490 if (!func->implementsCall())
1491 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
1494 m_args->evaluateList(exec, argList);
1495 KJS_CHECKEXCEPTIONVALUE
1497 JSObject* thisObj = exec->globalThisValue();
1498 return func->call(exec, thisObj, argList);
1501 JSValue* ScopedVarFunctionCallNode::evaluate(OldInterpreterExecState* exec)
1503 return inlineEvaluate(exec);
1506 double ScopedVarFunctionCallNode::evaluateToNumber(OldInterpreterExecState* exec)
1508 JSValue* v = inlineEvaluate(exec);
1509 KJS_CHECKEXCEPTIONNUMBER
1510 return v->toNumber(exec);
1513 bool ScopedVarFunctionCallNode::evaluateToBoolean(OldInterpreterExecState* exec)
1515 JSValue* v = inlineEvaluate(exec);
1516 KJS_CHECKEXCEPTIONBOOLEAN
1517 return v->toBoolean(exec);
1520 int32_t ScopedVarFunctionCallNode::evaluateToInt32(OldInterpreterExecState* exec)
1522 JSValue* v = inlineEvaluate(exec);
1523 KJS_CHECKEXCEPTIONNUMBER
1524 return v->toInt32(exec);
1527 uint32_t ScopedVarFunctionCallNode::evaluateToUInt32(OldInterpreterExecState* exec)
1529 JSValue* v = inlineEvaluate(exec);
1530 KJS_CHECKEXCEPTIONNUMBER
1531 return v->toUInt32(exec);
1534 JSValue* NonLocalVarFunctionCallNode::inlineEvaluate(OldInterpreterExecState* exec)
1536 // Check for missed optimization opportunity.
1537 ASSERT(!canSkipLookup(exec, m_ident));
1539 return resolveAndCall<FunctionCall, false>(exec, m_ident, m_args.get(), m_scopeDepth);
1542 JSValue* NonLocalVarFunctionCallNode::evaluate(OldInterpreterExecState* exec)
1544 return inlineEvaluate(exec);
1547 double NonLocalVarFunctionCallNode::evaluateToNumber(OldInterpreterExecState* exec)
1549 JSValue* v = inlineEvaluate(exec);
1550 KJS_CHECKEXCEPTIONNUMBER
1551 return v->toNumber(exec);
1554 bool NonLocalVarFunctionCallNode::evaluateToBoolean(OldInterpreterExecState* exec)
1556 JSValue* v = inlineEvaluate(exec);
1557 KJS_CHECKEXCEPTIONBOOLEAN
1558 return v->toBoolean(exec);
1561 int32_t NonLocalVarFunctionCallNode::evaluateToInt32(OldInterpreterExecState* exec)
1563 JSValue* v = inlineEvaluate(exec);
1564 KJS_CHECKEXCEPTIONNUMBER
1565 return v->toInt32(exec);
1568 uint32_t NonLocalVarFunctionCallNode::evaluateToUInt32(OldInterpreterExecState* exec)
1570 JSValue* v = inlineEvaluate(exec);
1571 KJS_CHECKEXCEPTIONNUMBER
1572 return v->toUInt32(exec);
1575 RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1577 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1578 RegisterID* property = generator.emitNode(m_subscript.get());
1579 RegisterID* function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
1580 return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get());
1583 void FunctionCallBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1585 nodeStack.append(m_args.get());
1586 nodeStack.append(m_subscript.get());
1587 nodeStack.append(m_base.get());
1591 JSValue* FunctionCallBracketNode::evaluate(OldInterpreterExecState* exec)
1593 JSValue* baseVal = m_base->evaluate(exec);
1594 KJS_CHECKEXCEPTIONVALUE
1596 JSValue* subscriptVal = m_subscript->evaluate(exec);
1598 JSObject* baseObj = baseVal->toObject(exec);
1603 if (subscriptVal->getUInt32(i)) {
1604 if (baseObj->getPropertySlot(exec, i, slot))
1605 funcVal = slot.getValue(exec, baseObj, i);
1607 funcVal = jsUndefined();
1609 Identifier ident(subscriptVal->toString(exec));
1610 if (baseObj->getPropertySlot(exec, ident, slot))
1611 funcVal = baseObj->get(exec, ident);
1613 funcVal = jsUndefined();
1616 KJS_CHECKEXCEPTIONVALUE
1618 if (!funcVal->isObject())
1619 return throwError(exec, TypeError, "Value %s (result of expression %s[%s]) is not object.", funcVal, m_base.get(), m_subscript.get());
1621 JSObject* func = static_cast<JSObject*>(funcVal);
1623 if (!func->implementsCall())
1624 return throwError(exec, TypeError, "Object %s (result of expression %s[%s]) does not allow calls.", funcVal, m_base.get(), m_subscript.get());
1627 m_args->evaluateList(exec, argList);
1628 KJS_CHECKEXCEPTIONVALUE
1630 JSObject* thisObj = baseObj;
1632 ASSERT(thisObj->isObject());
1633 ASSERT(!thisObj->isActivationObject());
1635 // No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
1636 return func->call(exec, thisObj, argList);
1639 static const char* dotExprNotAnObjectString() KJS_FAST_CALL;
1640 static const char* dotExprNotAnObjectString()
1642 return "Value %s (result of expression %s.%s) is not object.";
1645 static const char* dotExprDoesNotAllowCallsString() KJS_FAST_CALL;
1646 static const char* dotExprDoesNotAllowCallsString()
1648 return "Object %s (result of expression %s.%s) does not allow calls.";
1651 RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1653 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1654 RegisterID* function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
1655 return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get());
1658 void FunctionCallDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1660 nodeStack.append(m_args.get());
1661 nodeStack.append(m_base.get());
1665 JSValue* FunctionCallDotNode::inlineEvaluate(OldInterpreterExecState* exec)
1667 JSValue* baseVal = m_base->evaluate(exec);
1668 KJS_CHECKEXCEPTIONVALUE
1670 JSObject* baseObj = baseVal->toObject(exec);
1672 JSValue* funcVal = baseObj->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, baseObj, m_ident) : jsUndefined();
1673 KJS_CHECKEXCEPTIONVALUE
1675 if (!funcVal->isObject())
1676 return throwError(exec, TypeError, dotExprNotAnObjectString(), funcVal, m_base.get(), m_ident);
1678 JSObject* func = static_cast<JSObject*>(funcVal);
1680 if (!func->implementsCall())
1681 return throwError(exec, TypeError, dotExprDoesNotAllowCallsString(), funcVal, m_base.get(), m_ident);
1684 m_args->evaluateList(exec, argList);
1685 KJS_CHECKEXCEPTIONVALUE
1687 JSObject* thisObj = baseObj;
1689 ASSERT(thisObj->isObject());
1690 ASSERT(!thisObj->isActivationObject());
1692 // No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
1693 return func->call(exec, thisObj, argList);
1696 JSValue* FunctionCallDotNode::evaluate(OldInterpreterExecState* exec)
1698 return inlineEvaluate(exec);
1701 double FunctionCallDotNode::evaluateToNumber(OldInterpreterExecState* exec)
1703 JSValue* v = inlineEvaluate(exec);
1704 KJS_CHECKEXCEPTIONNUMBER
1705 return v->toNumber(exec);
1708 bool FunctionCallDotNode::evaluateToBoolean(OldInterpreterExecState* exec)
1710 JSValue* v = inlineEvaluate(exec);
1711 KJS_CHECKEXCEPTIONBOOLEAN
1712 return v->toBoolean(exec);
1715 int32_t FunctionCallDotNode::evaluateToInt32(OldInterpreterExecState* exec)
1717 JSValue* v = inlineEvaluate(exec);
1718 KJS_CHECKEXCEPTIONNUMBER
1719 return v->toInt32(exec);
1722 uint32_t FunctionCallDotNode::evaluateToUInt32(OldInterpreterExecState* exec)
1724 JSValue* v = inlineEvaluate(exec);
1725 KJS_CHECKEXCEPTIONNUMBER
1726 return v->toUInt32(exec);
1731 // ------------------------------ PostfixResolveNode ----------------------------------
1733 RegisterID* PostIncResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1735 // FIXME: I think we can detect the absense of dependent expressions here,
1736 // and emit a PreInc instead of a PostInc. A post-pass to eliminate dead
1737 // code would work, too.
1738 if (RegisterID* local = generator.registerForLocal(m_ident)) {
1739 if (generator.isLocalConstant(m_ident))
1740 return generator.emitToJSNumber(generator.finalDestination(dst), local);
1742 return generator.emitPostInc(generator.finalDestination(dst), local);
1745 RefPtr<RegisterID> value = generator.newTemporary();
1746 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
1747 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
1748 generator.emitPutById(base.get(), m_ident, value.get());
1753 void PostIncResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
1755 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
1756 if (index != missingSymbolMarker()) {
1757 if (isConstant(localStorage, index))
1758 new (this) PostIncConstNode(index);
1760 new (this) PostIncLocalVarNode(index);
1764 JSValue* PostIncResolveNode::evaluate(OldInterpreterExecState* exec)
1766 // Check for missed optimization opportunity.
1767 ASSERT(!canSkipLookup(exec, m_ident));
1769 const ScopeChain& chain = exec->scopeChain();
1770 ScopeChainIterator iter = chain.begin();
1771 ScopeChainIterator end = chain.end();
1773 // we must always have something in the scope chain
1774 ASSERT(iter != end);
1778 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
1779 // If m_ident is 'arguments', the base->getPropertySlot() may cause
1780 // base (which must be an ActivationImp in such this case) to be torn
1781 // off from the activation stack, in which case we need to get it again
1782 // from the ScopeChainIterator.
1784 JSObject* base = *iter;
1785 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
1786 base->put(exec, m_ident, jsNumber(v->toNumber(exec) + 1));
1791 } while (iter != end);
1793 return throwUndefinedVariableError(exec, m_ident);
1796 void PostIncResolveNode::optimizeForUnnecessaryResult()
1798 new (this) PreIncResolveNode(PlacementNewAdopt);
1801 JSValue* PostIncLocalVarNode::evaluate(OldInterpreterExecState* exec)
1803 ASSERT(exec->variableObject() == exec->scopeChain().top());
1805 JSValue** slot = &exec->localStorage()[m_index].value;
1806 JSValue* v = (*slot)->toJSNumber(exec);
1807 *slot = jsNumber(v->toNumber(exec) + 1);
1811 void PostIncLocalVarNode::optimizeForUnnecessaryResult()
1813 new (this) PreIncLocalVarNode(m_index);
1817 RegisterID* PostDecResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1819 // FIXME: I think we can detect the absense of dependent expressions here,
1820 // and emit a PreDec instead of a PostDec. A post-pass to eliminate dead
1821 // code would work, too.
1822 if (RegisterID* local = generator.registerForLocal(m_ident)) {
1823 if (generator.isLocalConstant(m_ident))
1824 return generator.emitToJSNumber(generator.finalDestination(dst), local);
1826 return generator.emitPostDec(generator.finalDestination(dst), local);
1829 RefPtr<RegisterID> value = generator.newTemporary();
1830 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
1831 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
1832 generator.emitPutById(base.get(), m_ident, value.get());
1836 void PostDecResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
1838 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
1839 if (index != missingSymbolMarker()) {
1840 if (isConstant(localStorage, index))
1841 new (this) PostDecConstNode(index);
1843 new (this) PostDecLocalVarNode(index);
1847 JSValue* PostDecResolveNode::evaluate(OldInterpreterExecState* exec)
1849 // Check for missed optimization opportunity.
1850 ASSERT(!canSkipLookup(exec, m_ident));
1852 const ScopeChain& chain = exec->scopeChain();
1853 ScopeChainIterator iter = chain.begin();
1854 ScopeChainIterator end = chain.end();
1856 // we must always have something in the scope chain
1857 ASSERT(iter != end);
1861 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
1862 // See the comment in PostIncResolveNode::evaluate().
1864 JSObject* base = *iter;
1865 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
1866 base->put(exec, m_ident, jsNumber(v->toNumber(exec) - 1));
1871 } while (iter != end);
1873 return throwUndefinedVariableError(exec, m_ident);
1876 void PostDecResolveNode::optimizeForUnnecessaryResult()
1878 new (this) PreDecResolveNode(PlacementNewAdopt);
1881 JSValue* PostDecLocalVarNode::evaluate(OldInterpreterExecState* exec)
1883 ASSERT(exec->variableObject() == exec->scopeChain().top());
1885 JSValue** slot = &exec->localStorage()[m_index].value;
1886 JSValue* v = (*slot)->toJSNumber(exec);
1887 *slot = jsNumber(v->toNumber(exec) - 1);
1891 double PostDecLocalVarNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
1893 ASSERT(exec->variableObject() == exec->scopeChain().top());
1895 JSValue** slot = &exec->localStorage()[m_index].value;
1896 double n = (*slot)->toNumber(exec);
1897 *slot = jsNumber(n - 1);
1901 double PostDecLocalVarNode::evaluateToNumber(OldInterpreterExecState* exec)
1903 return inlineEvaluateToNumber(exec);
1906 bool PostDecLocalVarNode::evaluateToBoolean(OldInterpreterExecState* exec)
1908 double result = inlineEvaluateToNumber(exec);
1909 return result > 0.0 || 0.0 > result; // NaN produces false as well
1912 int32_t PostDecLocalVarNode::evaluateToInt32(OldInterpreterExecState* exec)
1914 return JSValue::toInt32(inlineEvaluateToNumber(exec));
1917 uint32_t PostDecLocalVarNode::evaluateToUInt32(OldInterpreterExecState* exec)
1919 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
1922 void PostDecLocalVarNode::optimizeForUnnecessaryResult()
1924 new (this) PreDecLocalVarNode(m_index);
1927 // ------------------------------ PostfixBracketNode ----------------------------------
1929 void PostfixBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1931 nodeStack.append(m_subscript.get());
1932 nodeStack.append(m_base.get());
1935 RegisterID* PostIncBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1937 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1938 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
1939 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
1940 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
1941 generator.emitPutByVal(base.get(), property.get(), value.get());
1945 JSValue* PostIncBracketNode::evaluate(OldInterpreterExecState* exec)
1947 JSValue* baseValue = m_base->evaluate(exec);
1948 KJS_CHECKEXCEPTIONVALUE
1949 JSValue* subscript = m_subscript->evaluate(exec);
1950 KJS_CHECKEXCEPTIONVALUE
1952 JSObject* base = baseValue->toObject(exec);
1954 uint32_t propertyIndex;
1955 if (subscript->getUInt32(propertyIndex)) {
1957 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1958 KJS_CHECKEXCEPTIONVALUE
1960 JSValue* v2 = v->toJSNumber(exec);
1961 base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) + 1));
1966 Identifier propertyName(subscript->toString(exec));
1968 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1969 KJS_CHECKEXCEPTIONVALUE
1971 JSValue* v2 = v->toJSNumber(exec);
1972 base->put(exec, propertyName, jsNumber(v2->toNumber(exec) + 1));
1976 RegisterID* PostDecBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1978 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1979 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
1980 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
1981 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
1982 generator.emitPutByVal(base.get(), property.get(), value.get());
1986 JSValue* PostDecBracketNode::evaluate(OldInterpreterExecState* exec)
1988 JSValue* baseValue = m_base->evaluate(exec);
1989 KJS_CHECKEXCEPTIONVALUE
1990 JSValue* subscript = m_subscript->evaluate(exec);
1991 KJS_CHECKEXCEPTIONVALUE
1993 JSObject* base = baseValue->toObject(exec);
1995 uint32_t propertyIndex;
1996 if (subscript->getUInt32(propertyIndex)) {
1998 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1999 KJS_CHECKEXCEPTIONVALUE
2001 JSValue* v2 = v->toJSNumber(exec);
2002 base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) - 1));
2006 Identifier propertyName(subscript->toString(exec));
2008 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2009 KJS_CHECKEXCEPTIONVALUE
2011 JSValue* v2 = v->toJSNumber(exec);
2012 base->put(exec, propertyName, jsNumber(v2->toNumber(exec) - 1));
2016 // ------------------------------ PostfixDotNode ----------------------------------
2018 void PostfixDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2020 nodeStack.append(m_base.get());
2023 RegisterID* PostIncDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2025 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2026 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
2027 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
2028 generator.emitPutById(base.get(), m_ident, value.get());
2032 JSValue* PostIncDotNode::evaluate(OldInterpreterExecState* exec)
2034 JSValue* baseValue = m_base->evaluate(exec);
2035 KJS_CHECKEXCEPTIONVALUE
2036 JSObject* base = baseValue->toObject(exec);
2039 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2040 KJS_CHECKEXCEPTIONVALUE
2042 JSValue* v2 = v->toJSNumber(exec);
2043 base->put(exec, m_ident, jsNumber(v2->toNumber(exec) + 1));
2047 RegisterID* PostDecDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2049 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2050 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
2051 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
2052 generator.emitPutById(base.get(), m_ident, value.get());
2056 JSValue* PostDecDotNode::evaluate(OldInterpreterExecState* exec)
2058 JSValue* baseValue = m_base->evaluate(exec);
2059 KJS_CHECKEXCEPTIONVALUE
2060 JSObject* base = baseValue->toObject(exec);
2063 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2064 KJS_CHECKEXCEPTIONVALUE
2066 JSValue* v2 = v->toJSNumber(exec);
2067 base->put(exec, m_ident, jsNumber(v2->toNumber(exec) - 1));
2071 // ------------------------------ PostfixErrorNode -----------------------------------
2073 RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
2075 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference.");
2078 JSValue* PostfixErrorNode::evaluate(OldInterpreterExecState* exec)
2080 throwError(exec, ReferenceError, "Postfix %s operator applied to value that is not a reference.",
2081 m_operator == OpPlusPlus ? "++" : "--");
2082 handleException(exec);
2083 return jsUndefined();
2086 // ------------------------------ DeleteResolveNode -----------------------------------
2088 RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2090 if (generator.registerForLocal(m_ident))
2091 return generator.emitLoad(generator.finalDestination(dst), false);
2093 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
2094 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
2097 void DeleteResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
2099 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
2100 if (index != missingSymbolMarker())
2101 new (this) LocalVarDeleteNode();
2106 JSValue* DeleteResolveNode::evaluate(OldInterpreterExecState* exec)
2108 // Check for missed optimization opportunity.
2109 ASSERT(!canSkipLookup(exec, m_ident));
2111 const ScopeChain& chain = exec->scopeChain();
2112 ScopeChainIterator iter = chain.begin();
2113 ScopeChainIterator end = chain.end();
2115 // We must always have something in the scope chain
2116 ASSERT(iter != end);
2122 if (base->getPropertySlot(exec, m_ident, slot))
2123 return jsBoolean(base->deleteProperty(exec, m_ident));
2126 } while (iter != end);
2128 return jsBoolean(true);
2131 JSValue* LocalVarDeleteNode::evaluate(OldInterpreterExecState*)
2133 return jsBoolean(false);
2136 // ------------------------------ DeleteBracketNode -----------------------------------
2138 RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2140 RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
2141 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript.get());
2142 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
2145 void DeleteBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2147 nodeStack.append(m_subscript.get());
2148 nodeStack.append(m_base.get());
2151 JSValue* DeleteBracketNode::evaluate(OldInterpreterExecState* exec)
2153 JSValue* baseValue = m_base->evaluate(exec);
2154 KJS_CHECKEXCEPTIONVALUE
2155 JSValue* subscript = m_subscript->evaluate(exec);
2156 KJS_CHECKEXCEPTIONVALUE
2158 JSObject* base = baseValue->toObject(exec);
2160 uint32_t propertyIndex;
2161 if (subscript->getUInt32(propertyIndex))
2162 return jsBoolean(base->deleteProperty(exec, propertyIndex));
2164 Identifier propertyName(subscript->toString(exec));
2165 return jsBoolean(base->deleteProperty(exec, propertyName));
2168 // ------------------------------ DeleteDotNode -----------------------------------
2170 RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2172 RegisterID* r0 = generator.emitNode(m_base.get());
2173 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
2176 void DeleteDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2178 nodeStack.append(m_base.get());
2181 JSValue* DeleteDotNode::evaluate(OldInterpreterExecState* exec)
2183 JSValue* baseValue = m_base->evaluate(exec);
2184 JSObject* base = baseValue->toObject(exec);
2185 KJS_CHECKEXCEPTIONVALUE
2187 return jsBoolean(base->deleteProperty(exec, m_ident));
2190 // ------------------------------ DeleteValueNode -----------------------------------
2192 RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2194 generator.emitNode(m_expr.get());
2196 // delete on a non-location expression ignores the value and returns true
2197 return generator.emitLoad(generator.finalDestination(dst), true);
2200 void DeleteValueNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2202 nodeStack.append(m_expr.get());
2205 JSValue* DeleteValueNode::evaluate(OldInterpreterExecState* exec)
2207 m_expr->evaluate(exec);
2208 KJS_CHECKEXCEPTIONVALUE
2210 // delete on a non-location expression ignores the value and returns true
2211 return jsBoolean(true);
2214 // ------------------------------ VoidNode -------------------------------------
2216 RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2218 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
2219 return generator.emitLoad(generator.finalDestination(dst, r0.get()), jsUndefined());
2222 void VoidNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2224 nodeStack.append(m_expr.get());
2228 JSValue* VoidNode::evaluate(OldInterpreterExecState* exec)
2230 m_expr->evaluate(exec);
2231 KJS_CHECKEXCEPTIONVALUE
2233 return jsUndefined();
2238 // ------------------------------ TypeOfValueNode -----------------------------------
2240 void TypeOfValueNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2242 nodeStack.append(m_expr.get());
2245 static JSValue* typeStringForValue(JSValue* v) KJS_FAST_CALL;
2246 static JSValue* typeStringForValue(JSValue* v)
2248 switch (v->type()) {
2250 return jsString("undefined");
2252 return jsString("object");
2254 return jsString("boolean");
2256 return jsString("number");
2258 return jsString("string");
2260 if (v->isObject()) {
2261 // Return "undefined" for objects that should be treated
2262 // as null when doing comparisons.
2263 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
2264 return jsString("undefined");
2265 else if (static_cast<JSObject*>(v)->implementsCall())
2266 return jsString("function");
2269 return jsString("object");
2273 void TypeOfResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
2275 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
2276 if (index != missingSymbolMarker())
2277 new (this) LocalVarTypeOfNode(index);
2280 JSValue* LocalVarTypeOfNode::evaluate(OldInterpreterExecState* exec)
2282 ASSERT(exec->variableObject() == exec->scopeChain().top());
2284 return typeStringForValue(exec->localStorage()[m_index].value);
2287 RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2289 if (RegisterID* local = generator.registerForLocal(m_ident))
2290 return generator.emitTypeOf(generator.finalDestination(dst), local);
2292 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
2293 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
2294 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
2297 JSValue* TypeOfResolveNode::evaluate(OldInterpreterExecState* exec)
2299 const ScopeChain& chain = exec->scopeChain();
2300 ScopeChainIterator iter = chain.begin();
2301 ScopeChainIterator end = chain.end();
2303 // We must always have something in the scope chain
2304 ASSERT(iter != end);
2310 if (base->getPropertySlot(exec, m_ident, slot)) {
2311 JSValue* v = slot.getValue(exec, base, m_ident);
2312 return typeStringForValue(v);
2316 } while (iter != end);
2318 return jsString("undefined");
2321 // ------------------------------ TypeOfValueNode -----------------------------------
2323 RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2325 RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
2326 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
2329 JSValue* TypeOfValueNode::evaluate(OldInterpreterExecState* exec)
2331 JSValue* v = m_expr->evaluate(exec);
2332 KJS_CHECKEXCEPTIONVALUE
2334 return typeStringForValue(v);
2337 // ECMA 11.4.4 and 11.4.5
2339 // ------------------------------ PrefixResolveNode ----------------------------------
2341 RegisterID* PreIncResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2343 if (RegisterID* local = generator.registerForLocal(m_ident)) {
2344 if (generator.isLocalConstant(m_ident)) {
2345 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), 1.0);
2346 return generator.emitAdd(r0.get(), local, r0.get());
2349 generator.emitPreInc(local);
2350 return generator.moveToDestinationIfNeeded(dst, local);
2353 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2354 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
2355 generator.emitPreInc(propDst.get());
2356 generator.emitPutById(base.get(), m_ident, propDst.get());
2357 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2360 void PreIncResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
2362 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
2363 if (index != missingSymbolMarker()) {
2364 if (isConstant(localStorage, index))
2365 new (this) PreIncConstNode(index);
2367 new (this) PreIncLocalVarNode(index);
2371 JSValue* PreIncLocalVarNode::evaluate(OldInterpreterExecState* exec)
2373 ASSERT(exec->variableObject() == exec->scopeChain().top());
2374 JSValue** slot = &exec->localStorage()[m_index].value;
2376 double n = (*slot)->toNumber(exec);
2377 JSValue* n2 = jsNumber(n + 1);
2382 JSValue* PreIncResolveNode::evaluate(OldInterpreterExecState* exec)
2384 const ScopeChain& chain = exec->scopeChain();
2385 ScopeChainIterator iter = chain.begin();
2386 ScopeChainIterator end = chain.end();
2388 // we must always have something in the scope chain
2389 ASSERT(iter != end);
2393 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
2394 // See the comment in PostIncResolveNode::evaluate().
2396 JSObject* base = *iter;
2397 JSValue* v = slot.getValue(exec, base, m_ident);
2399 double n = v->toNumber(exec);
2400 JSValue* n2 = jsNumber(n + 1);
2401 base->put(exec, m_ident, n2);
2407 } while (iter != end);
2409 return throwUndefinedVariableError(exec, m_ident);
2412 RegisterID* PreDecResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2414 if (RegisterID* local = generator.registerForLocal(m_ident)) {
2415 if (generator.isLocalConstant(m_ident)) {
2416 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), -1.0);
2417 return generator.emitAdd(r0.get(), local, r0.get());
2420 generator.emitPreDec(local);
2421 return generator.moveToDestinationIfNeeded(dst, local);
2424 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2425 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
2426 generator.emitPreDec(propDst.get());
2427 generator.emitPutById(base.get(), m_ident, propDst.get());
2428 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2431 void PreDecResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
2433 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
2434 if (index != missingSymbolMarker()) {
2435 if (isConstant(localStorage, index))
2436 new (this) PreDecConstNode(index);
2438 new (this) PreDecLocalVarNode(index);
2442 JSValue* PreDecLocalVarNode::evaluate(OldInterpreterExecState* exec)
2444 ASSERT(exec->variableObject() == exec->scopeChain().top());
2445 JSValue** slot = &exec->localStorage()[m_index].value;
2447 double n = (*slot)->toNumber(exec);
2448 JSValue* n2 = jsNumber(n - 1);
2453 JSValue* PreDecResolveNode::evaluate(OldInterpreterExecState* exec)
2455 const ScopeChain& chain = exec->scopeChain();
2456 ScopeChainIterator iter = chain.begin();
2457 ScopeChainIterator end = chain.end();
2459 // we must always have something in the scope chain
2460 ASSERT(iter != end);
2464 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
2465 // See the comment in PostIncResolveNode::evaluate().
2467 JSObject* base = *iter;
2468 JSValue* v = slot.getValue(exec, base, m_ident);
2470 double n = v->toNumber(exec);
2471 JSValue* n2 = jsNumber(n - 1);
2472 base->put(exec, m_ident, n2);
2478 } while (iter != end);
2480 return throwUndefinedVariableError(exec, m_ident);
2483 // ------------------------------ PreIncConstNode ----------------------------------
2485 JSValue* PreIncConstNode::evaluate(OldInterpreterExecState* exec)
2487 ASSERT(exec->variableObject() == exec->scopeChain().top());
2488 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) + 1);
2491 // ------------------------------ PreDecConstNode ----------------------------------
2493 JSValue* PreDecConstNode::evaluate(OldInterpreterExecState* exec)
2495 ASSERT(exec->variableObject() == exec->scopeChain().top());
2496 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) - 1);
2499 // ------------------------------ PostIncConstNode ----------------------------------
2501 JSValue* PostIncConstNode::evaluate(OldInterpreterExecState* exec)
2503 ASSERT(exec->variableObject() == exec->scopeChain().top());
2504 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
2507 // ------------------------------ PostDecConstNode ----------------------------------
2509 JSValue* PostDecConstNode::evaluate(OldInterpreterExecState* exec)
2511 ASSERT(exec->variableObject() == exec->scopeChain().top());
2512 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
2515 // ------------------------------ PrefixBracketNode ----------------------------------
2517 void PrefixBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2519 nodeStack.append(m_subscript.get());
2520 nodeStack.append(m_base.get());
2523 RegisterID* PreIncBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2525 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2526 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
2527 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2528 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
2529 generator.emitPreInc(value);
2530 generator.emitPutByVal(base.get(), property.get(), value);
2531 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2534 JSValue* PreIncBracketNode::evaluate(OldInterpreterExecState* exec)
2536 JSValue* baseValue = m_base->evaluate(exec);
2537 KJS_CHECKEXCEPTIONVALUE
2538 JSValue* subscript = m_subscript->evaluate(exec);
2539 KJS_CHECKEXCEPTIONVALUE
2541 JSObject* base = baseValue->toObject(exec);
2543 uint32_t propertyIndex;
2544 if (subscript->getUInt32(propertyIndex)) {
2546 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2547 KJS_CHECKEXCEPTIONVALUE
2549 JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
2550 base->put(exec, propertyIndex, n2);
2555 Identifier propertyName(subscript->toString(exec));
2557 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2558 KJS_CHECKEXCEPTIONVALUE
2560 JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
2561 base->put(exec, propertyName, n2);
2566 RegisterID* PreDecBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2569 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2570 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
2571 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2572 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
2573 generator.emitPreDec(value);
2574 generator.emitPutByVal(base.get(), property.get(), value);
2575 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2578 JSValue* PreDecBracketNode::evaluate(OldInterpreterExecState* exec)
2580 JSValue* baseValue = m_base->evaluate(exec);
2581 KJS_CHECKEXCEPTIONVALUE
2582 JSValue* subscript = m_subscript->evaluate(exec);
2583 KJS_CHECKEXCEPTIONVALUE
2585 JSObject* base = baseValue->toObject(exec);
2587 uint32_t propertyIndex;
2588 if (subscript->getUInt32(propertyIndex)) {
2590 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2591 KJS_CHECKEXCEPTIONVALUE
2593 JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
2594 base->put(exec, propertyIndex, n2);
2599 Identifier propertyName(subscript->toString(exec));
2601 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2602 KJS_CHECKEXCEPTIONVALUE
2604 JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
2605 base->put(exec, propertyName, n2);
2610 // ------------------------------ PrefixDotNode ----------------------------------
2612 void PrefixDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2614 nodeStack.append(m_base.get());
2617 RegisterID* PreIncDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2619 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2620 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2621 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
2622 generator.emitPreInc(value);
2623 generator.emitPutById(base.get(), m_ident, value);
2624 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2627 JSValue* PreIncDotNode::evaluate(OldInterpreterExecState* exec)
2629 JSValue* baseValue = m_base->evaluate(exec);
2630 KJS_CHECKEXCEPTIONVALUE
2631 JSObject* base = baseValue->toObject(exec);
2634 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2635 KJS_CHECKEXCEPTIONVALUE
2637 double n = v->toNumber(exec);
2638 JSValue* n2 = jsNumber(n + 1);
2639 base->put(exec, m_ident, n2);
2644 RegisterID* PreDecDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2646 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2647 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2648 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
2649 generator.emitPreDec(value);
2650 generator.emitPutById(base.get(), m_ident, value);
2651 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2654 JSValue* PreDecDotNode::evaluate(OldInterpreterExecState* exec)
2656 JSValue* baseValue = m_base->evaluate(exec);
2657 KJS_CHECKEXCEPTIONVALUE
2658 JSObject* base = baseValue->toObject(exec);
2661 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2662 KJS_CHECKEXCEPTIONVALUE
2664 double n = v->toNumber(exec);
2665 JSValue* n2 = jsNumber(n - 1);
2666 base->put(exec, m_ident, n2);
2671 // ------------------------------ PrefixErrorNode -----------------------------------
2673 RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
2675 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference.");
2678 JSValue* PrefixErrorNode::evaluate(OldInterpreterExecState* exec)
2680 throwError(exec, ReferenceError, "Prefix %s operator applied to value that is not a reference.",
2681 m_operator == OpPlusPlus ? "++" : "--");
2682 handleException(exec);
2683 return jsUndefined();
2686 // ------------------------------ UnaryPlusNode --------------------------------
2688 RegisterID* UnaryPlusNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2690 RegisterID* src = generator.emitNode(m_expr.get());
2691 return generator.emitToJSNumber(generator.finalDestination(dst), src);
2694 void UnaryPlusNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2696 nodeStack.append(m_expr.get());
2700 JSValue* UnaryPlusNode::evaluate(OldInterpreterExecState* exec)
2702 JSValue* v = m_expr->evaluate(exec);
2703 KJS_CHECKEXCEPTIONVALUE
2704 return v->toJSNumber(exec);
2707 bool UnaryPlusNode::evaluateToBoolean(OldInterpreterExecState* exec)
2709 return m_expr->evaluateToBoolean(exec);
2712 double UnaryPlusNode::evaluateToNumber(OldInterpreterExecState* exec)
2714 return m_expr->evaluateToNumber(exec);
2717 int32_t UnaryPlusNode::evaluateToInt32(OldInterpreterExecState* exec)
2719 return m_expr->evaluateToInt32(exec);
2722 uint32_t UnaryPlusNode::evaluateToUInt32(OldInterpreterExecState* exec)
2724 return m_expr->evaluateToInt32(exec);
2727 // ------------------------------ NegateNode -----------------------------------
2729 RegisterID* NegateNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2731 RegisterID* src = generator.emitNode(m_expr.get());
2732 return generator.emitNegate(generator.finalDestination(dst), src);
2735 void NegateNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2737 nodeStack.append(m_expr.get());
2741 JSValue* NegateNode::evaluate(OldInterpreterExecState* exec)
2743 // No need to check exception, caller will do so right after evaluate()
2744 return jsNumber(-m_expr->evaluateToNumber(exec));
2747 double NegateNode::evaluateToNumber(OldInterpreterExecState* exec)
2749 // No need to check exception, caller will do so right after evaluateToNumber()
2750 return -m_expr->evaluateToNumber(exec);
2753 // ------------------------------ BitwiseNotNode -------------------------------
2755 RegisterID* BitwiseNotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2757 RegisterID* src = generator.emitNode(m_expr.get());
2758 return generator.emitBitNot(generator.finalDestination(dst), src);
2761 void BitwiseNotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2763 nodeStack.append(m_expr.get());
2767 int32_t BitwiseNotNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
2769 return ~m_expr->evaluateToInt32(exec);
2772 JSValue* BitwiseNotNode::evaluate(OldInterpreterExecState* exec)
2774 return jsNumber(inlineEvaluateToInt32(exec));
2777 double BitwiseNotNode::evaluateToNumber(OldInterpreterExecState* exec)
2779 return inlineEvaluateToInt32(exec);
2782 bool BitwiseNotNode::evaluateToBoolean(OldInterpreterExecState* exec)
2784 return inlineEvaluateToInt32(exec);
2787 int32_t BitwiseNotNode::evaluateToInt32(OldInterpreterExecState* exec)
2789 return inlineEvaluateToInt32(exec);
2792 uint32_t BitwiseNotNode::evaluateToUInt32(OldInterpreterExecState* exec)
2794 return inlineEvaluateToInt32(exec);
2797 // ------------------------------ LogicalNotNode -------------------------------
2799 RegisterID* LogicalNotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2801 RegisterID* src = generator.emitNode(m_expr.get());
2802 return generator.emitNot(generator.finalDestination(dst), src);
2805 void LogicalNotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2807 nodeStack.append(m_expr.get());
2811 JSValue* LogicalNotNode::evaluate(OldInterpreterExecState* exec)
2813 return jsBoolean(!m_expr->evaluateToBoolean(exec));
2816 bool LogicalNotNode::evaluateToBoolean(OldInterpreterExecState* exec)
2818 return !m_expr->evaluateToBoolean(exec);
2821 // ------------------------------ Multiplicative Nodes -----------------------------------
2823 RegisterID* MultNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2825 RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
2826 RegisterID* src2 = generator.emitNode(m_term2.get());
2827 return generator.emitMul(generator.finalDestination(dst, src1.get()), src1.get(), src2);
2830 void MultNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2832 nodeStack.append(m_term1.get());
2833 nodeStack.append(m_term2.get());
2837 double MultNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
2839 double n1 = m_term1->evaluateToNumber(exec);
2840 KJS_CHECKEXCEPTIONNUMBER
2841 double n2 = m_term2->evaluateToNumber(exec);
2845 JSValue* MultNode::evaluate(OldInterpreterExecState* exec)
2847 return jsNumber(inlineEvaluateToNumber(exec));
2850 double MultNode::evaluateToNumber(OldInterpreterExecState* exec)
2852 return inlineEvaluateToNumber(exec);
2855 bool MultNode::evaluateToBoolean(OldInterpreterExecState* exec)
2857 double result = inlineEvaluateToNumber(exec);
2858 return result > 0.0 || 0.0 > result; // NaN produces false as well
2861 int32_t MultNode::evaluateToInt32(OldInterpreterExecState* exec)
2863 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2866 uint32_t MultNode::evaluateToUInt32(OldInterpreterExecState* exec)
2868 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2871 RegisterID* DivNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2873 RefPtr<RegisterID> dividend = generator.emitNode(m_term1.get());
2874 RegisterID* divisor = generator.emitNode(m_term2.get());
2875 return generator.emitDiv(generator.finalDestination(dst, dividend.get()), dividend.get(), divisor);
2878 void DivNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2880 nodeStack.append(m_term1.get());
2881 nodeStack.append(m_term2.get());
2885 double DivNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
2887 double n1 = m_term1->evaluateToNumber(exec);
2888 KJS_CHECKEXCEPTIONNUMBER
2889 double n2 = m_term2->evaluateToNumber(exec);
2893 JSValue* DivNode::evaluate(OldInterpreterExecState* exec)
2895 return jsNumber(inlineEvaluateToNumber(exec));
2898 double DivNode::evaluateToNumber(OldInterpreterExecState* exec)
2900 return inlineEvaluateToNumber(exec);
2903 int32_t DivNode::evaluateToInt32(OldInterpreterExecState* exec)
2905 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2908 uint32_t DivNode::evaluateToUInt32(OldInterpreterExecState* exec)
2910 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2913 RegisterID* ModNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2915 RefPtr<RegisterID> dividend = generator.emitNode(m_term1.get());
2916 RegisterID* divisor = generator.emitNode(m_term2.get());
2917 return generator.emitMod(generator.finalDestination(dst, dividend.get()), dividend.get(), divisor);
2920 void ModNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2922 nodeStack.append(m_term1.get());
2923 nodeStack.append(m_term2.get());
2927 double ModNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
2929 double n1 = m_term1->evaluateToNumber(exec);
2930 KJS_CHECKEXCEPTIONNUMBER
2931 double n2 = m_term2->evaluateToNumber(exec);
2932 return fmod(n1, n2);
2935 JSValue* ModNode::evaluate(OldInterpreterExecState* exec)
2937 return jsNumber(inlineEvaluateToNumber(exec));
2940 double ModNode::evaluateToNumber(OldInterpreterExecState* exec)
2942 return inlineEvaluateToNumber(exec);
2945 bool ModNode::evaluateToBoolean(OldInterpreterExecState* exec)
2947 double result = inlineEvaluateToNumber(exec);
2948 return result > 0.0 || 0.0 > result; // NaN produces false as well
2951 int32_t ModNode::evaluateToInt32(OldInterpreterExecState* exec)
2953 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2956 uint32_t ModNode::evaluateToUInt32(OldInterpreterExecState* exec)
2958 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2961 // ------------------------------ Additive Nodes --------------------------------------
2963 static double throwOutOfMemoryErrorToNumber(OldInterpreterExecState* exec)
2965 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
2966 exec->setException(error);
2971 static JSValue* addSlowCase(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
2973 // exception for the Date exception in defaultValue()
2974 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
2975 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
2977 if (p1->isString() || p2->isString()) {
2978 UString value = p1->toString(exec) + p2->toString(exec);
2980 return throwOutOfMemoryError(exec);
2981 return jsString(value);
2984 return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
2987 static double addSlowCaseToNumber(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
2989 // exception for the Date exception in defaultValue()
2990 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
2991 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
2993 if (p1->isString() || p2->isString()) {
2994 UString value = p1->toString(exec) + p2->toString(exec);
2996 return throwOutOfMemoryErrorToNumber(exec);
2997 return value.toDouble();
3000 return p1->toNumber(exec) + p2->toNumber(exec);
3003 // Fast-path choices here are based on frequency data from SunSpider:
3004 // <times> Add case: <t1> <t2>
3005 // ---------------------------
3006 // 5627160 Add case: 1 1
3007 // 247427 Add case: 5 5
3008 // 20901 Add case: 5 6
3009 // 13978 Add case: 5 1
3010 // 4000 Add case: 1 5
3013 static inline JSValue* add(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3015 JSType t1 = v1->type();
3016 JSType t2 = v2->type();
3017 const unsigned bothTypes = (t1 << 3) | t2;
3019 if (bothTypes == ((NumberType << 3) | NumberType))
3020 return jsNumber(v1->toNumber(exec) + v2->toNumber(exec));
3021 if (bothTypes == ((StringType << 3) | StringType)) {
3022 UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
3024 return throwOutOfMemoryError(exec);
3025 return jsString(value);
3028 // All other cases are pretty uncommon
3029 return addSlowCase(exec, v1, v2);
3032 static inline double addToNumber(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3034 JSType t1 = v1->type();
3035 JSType t2 = v2->type();
3036 const unsigned bothTypes = (t1 << 3) | t2;
3038 if (bothTypes == ((NumberType << 3) | NumberType))
3039 return v1->toNumber(exec) + v2->toNumber(exec);
3040 if (bothTypes == ((StringType << 3) | StringType)) {
3041 UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
3043 return throwOutOfMemoryErrorToNumber(exec);
3044 return value.toDouble();
3047 // All other cases are pretty uncommon
3048 return addSlowCaseToNumber(exec, v1, v2);
3051 RegisterID* AddNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3053 RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
3054 RegisterID* src2 = generator.emitNode(m_term2.get());
3055 return generator.emitAdd(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3058 void AddNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3060 nodeStack.append(m_term1.get());
3061 nodeStack.append(m_term2.get());
3065 JSValue* AddNode::evaluate(OldInterpreterExecState* exec)
3067 JSValue* v1 = m_term1->evaluate(exec);
3068 KJS_CHECKEXCEPTIONVALUE
3070 JSValue* v2 = m_term2->evaluate(exec);
3071 KJS_CHECKEXCEPTIONVALUE
3073 return add(exec, v1, v2);
3076 double AddNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
3078 JSValue* v1 = m_term1->evaluate(exec);
3079 KJS_CHECKEXCEPTIONNUMBER
3081 JSValue* v2 = m_term2->evaluate(exec);
3082 KJS_CHECKEXCEPTIONNUMBER
3084 return addToNumber(exec, v1, v2);
3087 double AddNode::evaluateToNumber(OldInterpreterExecState* exec)
3089 return inlineEvaluateToNumber(exec);
3092 int32_t AddNode::evaluateToInt32(OldInterpreterExecState* exec)
3094 return JSValue::toInt32(inlineEvaluateToNumber(exec));
3097 uint32_t AddNode::evaluateToUInt32(OldInterpreterExecState* exec)
3099 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
3102 double AddNumbersNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
3104 double n1 = m_term1->evaluateToNumber(exec);
3105 KJS_CHECKEXCEPTIONNUMBER
3106 double n2 = m_term2->evaluateToNumber(exec);
3110 JSValue* AddNumbersNode::evaluate(OldInterpreterExecState* exec)
3112 return jsNumber(inlineEvaluateToNumber(exec));
3115 double AddNumbersNode::evaluateToNumber(OldInterpreterExecState* exec)
3117 return inlineEvaluateToNumber(exec);
3120 int32_t AddNumbersNode::evaluateToInt32(OldInterpreterExecState* exec)
3122 return JSValue::toInt32(inlineEvaluateToNumber(exec));
3125 uint32_t AddNumbersNode::evaluateToUInt32(OldInterpreterExecState* exec)
3127 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
3130 JSValue* AddStringsNode::evaluate(OldInterpreterExecState* exec)
3132 JSValue* v1 = m_term1->evaluate(exec);
3133 KJS_CHECKEXCEPTIONVALUE
3135 JSValue* v2 = m_term2->evaluate(exec);
3136 KJS_CHECKEXCEPTIONVALUE
3138 return jsString(static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value());
3141 JSValue* AddStringLeftNode::evaluate(OldInterpreterExecState* exec)
3143 JSValue* v1 = m_term1->evaluate(exec);
3144 KJS_CHECKEXCEPTIONVALUE
3146 JSValue* v2 = m_term2->evaluate(exec);
3147 KJS_CHECKEXCEPTIONVALUE
3149 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
3150 return jsString(static_cast<StringImp*>(v1)->value() + p2->toString(exec));
3153 JSValue* AddStringRightNode::evaluate(OldInterpreterExecState* exec)
3155 JSValue* v1 = m_term1->evaluate(exec);
3156 KJS_CHECKEXCEPTIONVALUE
3158 JSValue* v2 = m_term2->evaluate(exec);
3159 KJS_CHECKEXCEPTIONVALUE
3161 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
3162 return jsString(p1->toString(exec) + static_cast<StringImp*>(v2)->value());
3165 RegisterID* SubNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3167 RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
3168 RegisterID* src2 = generator.emitNode(m_term2.get());
3169 return generator.emitSub(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3172 void SubNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3174 nodeStack.append(m_term1.get());
3175 nodeStack.append(m_term2.get());
3179 double SubNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
3181 double n1 = m_term1->evaluateToNumber(exec);
3182 KJS_CHECKEXCEPTIONNUMBER
3183 double n2 = m_term2->evaluateToNumber(exec);
3187 JSValue* SubNode::evaluate(OldInterpreterExecState* exec)
3189 return jsNumber(inlineEvaluateToNumber(exec));
3192 double SubNode::evaluateToNumber(OldInterpreterExecState* exec)
3194 return inlineEvaluateToNumber(exec);
3197 int32_t SubNode::evaluateToInt32(OldInterpreterExecState* exec)
3199 return JSValue::toInt32(inlineEvaluateToNumber(exec));
3202 uint32_t SubNode::evaluateToUInt32(OldInterpreterExecState* exec)
3204 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
3207 // ------------------------------ Shift Nodes ------------------------------------
3209 RegisterID* LeftShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3211 RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
3212 RegisterID* shift = generator.emitNode(m_term2.get());
3213 return generator.emitLeftShift(generator.finalDestination(dst, val.get()), val.get(), shift);
3216 void LeftShiftNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3218 nodeStack.append(m_term1.get());
3219 nodeStack.append(m_term2.get());
3223 int32_t LeftShiftNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
3225 int i1 = m_term1->evaluateToInt32(exec);
3226 KJS_CHECKEXCEPTIONNUMBER
3227 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
3231 JSValue* LeftShiftNode::evaluate(OldInterpreterExecState* exec)
3233 return jsNumber(inlineEvaluateToInt32(exec));
3236 double LeftShiftNode::evaluateToNumber(OldInterpreterExecState* exec)
3238 return inlineEvaluateToInt32(exec);
3241 int32_t LeftShiftNode::evaluateToInt32(OldInterpreterExecState* exec)
3243 return inlineEvaluateToInt32(exec);
3246 uint32_t LeftShiftNode::evaluateToUInt32(OldInterpreterExecState* exec)
3248 return inlineEvaluateToInt32(exec);
3251 RegisterID* RightShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3253 RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
3254 RegisterID* shift = generator.emitNode(m_term2.get());
3255 return generator.emitRightShift(generator.finalDestination(dst, val.get()), val.get(), shift);
3258 void RightShiftNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3260 nodeStack.append(m_term1.get());
3261 nodeStack.append(m_term2.get());
3265 int32_t RightShiftNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
3267 int i1 = m_term1->evaluateToInt32(exec);
3268 KJS_CHECKEXCEPTIONNUMBER
3269 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
3273 JSValue* RightShiftNode::evaluate(OldInterpreterExecState* exec)
3275 return jsNumber(inlineEvaluateToInt32(exec));
3278 double RightShiftNode::evaluateToNumber(OldInterpreterExecState* exec)
3280 return inlineEvaluateToInt32(exec);
3283 int32_t RightShiftNode::evaluateToInt32(OldInterpreterExecState* exec)
3285 return inlineEvaluateToInt32(exec);
3288 uint32_t RightShiftNode::evaluateToUInt32(OldInterpreterExecState* exec)
3290 return inlineEvaluateToInt32(exec);
3293 RegisterID* UnsignedRightShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3295 RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
3296 RegisterID* shift = generator.emitNode(m_term2.get());
3297 return generator.emitUnsignedRightShift(generator.finalDestination(dst, val.get()), val.get(), shift);
3300 void UnsignedRightShiftNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3302 nodeStack.append(m_term1.get());
3303 nodeStack.append(m_term2.get());
3307 uint32_t UnsignedRightShiftNode::inlineEvaluateToUInt32(OldInterpreterExecState* exec)
3309 unsigned int i1 = m_term1->evaluateToUInt32(exec);
3310 KJS_CHECKEXCEPTIONNUMBER
3311 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
3315 JSValue* UnsignedRightShiftNode::evaluate(OldInterpreterExecState* exec)
3317 return jsNumber(inlineEvaluateToUInt32(exec));
3320 double UnsignedRightShiftNode::evaluateToNumber(OldInterpreterExecState* exec)
3322 return inlineEvaluateToUInt32(exec);
3325 int32_t UnsignedRightShiftNode::evaluateToInt32(OldInterpreterExecState* exec)
3327 return inlineEvaluateToUInt32(exec);
3330 uint32_t UnsignedRightShiftNode::evaluateToUInt32(OldInterpreterExecState* exec)
3332 return inlineEvaluateToUInt32(exec);
3335 // ------------------------------ Relational Nodes -------------------------------
3337 static inline bool lessThan(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3343 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
3344 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
3346 if (wasNotString1 | wasNotString2)
3349 return static_cast<const StringImp*>(p1)->value() < static_cast<const StringImp*>(p2)->value();
3352 static inline bool lessThanEq(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3358 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
3359 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
3361 if (wasNotString1 | wasNotString2)
3364 return !(static_cast<const StringImp*>(p2)->value() < static_cast<const StringImp*>(p1)->value());
3367 RegisterID* LessNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3369 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3370 RegisterID* src2 = generator.emitNode(m_expr2.get());
3371 return generator.emitLess(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3374 void LessNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3376 nodeStack.append(m_expr2.get());
3377 nodeStack.append(m_expr1.get());
3381 bool LessNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3383 JSValue* v1 = m_expr1->evaluate(exec);
3384 KJS_CHECKEXCEPTIONBOOLEAN
3385 JSValue* v2 = m_expr2->evaluate(exec);
3386 KJS_CHECKEXCEPTIONBOOLEAN
3387 return lessThan(exec, v1, v2);
3390 JSValue* LessNode::evaluate(OldInterpreterExecState* exec)
3392 return jsBoolean(inlineEvaluateToBoolean(exec));
3395 bool LessNode::evaluateToBoolean(OldInterpreterExecState* exec)
3397 return inlineEvaluateToBoolean(exec);
3400 bool LessNumbersNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3402 double n1 = m_expr1->evaluateToNumber(exec);
3403 KJS_CHECKEXCEPTIONVALUE
3404 double n2 = m_expr2->evaluateToNumber(exec);
3408 JSValue* LessNumbersNode::evaluate(OldInterpreterExecState* exec)
3410 return jsBoolean(inlineEvaluateToBoolean(exec));
3413 bool LessNumbersNode::evaluateToBoolean(OldInterpreterExecState* exec)
3415 return inlineEvaluateToBoolean(exec);
3418 bool LessStringsNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3420 JSValue* v1 = m_expr1->evaluate(exec);
3421 KJS_CHECKEXCEPTIONVALUE
3422 JSValue* v2 = m_expr2->evaluate(exec);
3423 return static_cast<StringImp*>(v1)->value() < static_cast<StringImp*>(v2)->value();
3426 JSValue* LessStringsNode::evaluate(OldInterpreterExecState* exec)
3428 return jsBoolean(inlineEvaluateToBoolean(exec));
3431 bool LessStringsNode::evaluateToBoolean(OldInterpreterExecState* exec)
3433 return inlineEvaluateToBoolean(exec);
3436 RegisterID* GreaterNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3438 RefPtr<RegisterID> src1 = generator.emitNode(m_expr2.get());
3439 RegisterID* src2 = generator.emitNode(m_expr1.get());
3440 return generator.emitLess(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3443 void GreaterNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3445 nodeStack.append(m_expr2.get());
3446 nodeStack.append(m_expr1.get());
3450 bool GreaterNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3452 JSValue* v1 = m_expr1->evaluate(exec);
3453 KJS_CHECKEXCEPTIONBOOLEAN
3454 JSValue* v2 = m_expr2->evaluate(exec);
3455 KJS_CHECKEXCEPTIONBOOLEAN
3456 return lessThan(exec, v2, v1);
3459 JSValue* GreaterNode::evaluate(OldInterpreterExecState* exec)
3461 return jsBoolean(inlineEvaluateToBoolean(exec));
3464 bool GreaterNode::evaluateToBoolean(OldInterpreterExecState* exec)
3466 return inlineEvaluateToBoolean(exec);
3469 RegisterID* LessEqNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3471 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3472 RegisterID* src2 = generator.emitNode(m_expr2.get());
3473 return generator.emitLessEq(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3476 void LessEqNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3478 nodeStack.append(m_expr2.get());
3479 nodeStack.append(m_expr1.get());
3483 bool LessEqNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3485 JSValue* v1 = m_expr1->evaluate(exec);
3486 KJS_CHECKEXCEPTIONBOOLEAN
3487 JSValue* v2 = m_expr2->evaluate(exec);
3488 KJS_CHECKEXCEPTIONBOOLEAN
3489 return lessThanEq(exec, v1, v2);
3492 JSValue* LessEqNode::evaluate(OldInterpreterExecState* exec)
3494 return jsBoolean(inlineEvaluateToBoolean(exec));
3497 bool LessEqNode::evaluateToBoolean(OldInterpreterExecState* exec)
3499 return inlineEvaluateToBoolean(exec);
3502 RegisterID* GreaterEqNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3504 RefPtr<RegisterID> src1 = generator.emitNode(m_expr2.get());
3505 RegisterID* src2 = generator.emitNode(m_expr1.get());
3506 return generator.emitLessEq(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3509 void GreaterEqNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3511 nodeStack.append(m_expr2.get());
3512 nodeStack.append(m_expr1.get());
3516 bool GreaterEqNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3518 JSValue* v1 = m_expr1->evaluate(exec);
3519 KJS_CHECKEXCEPTIONBOOLEAN
3520 JSValue* v2 = m_expr2->evaluate(exec);
3521 KJS_CHECKEXCEPTIONBOOLEAN
3522 return lessThanEq(exec, v2, v1);
3525 JSValue* GreaterEqNode::evaluate(OldInterpreterExecState* exec)
3527 return jsBoolean(inlineEvaluateToBoolean(exec));
3530 bool GreaterEqNode::evaluateToBoolean(OldInterpreterExecState* exec)
3532 return inlineEvaluateToBoolean(exec);
3535 RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3537 RefPtr<RegisterID> value = generator.emitNode(m_expr1.get());
3538 RegisterID* base = generator.emitNode(m_expr2.get());
3539 return generator.emitInstanceOf(generator.finalDestination(dst, value.get()), value.get(), base);
3542 void InstanceOfNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3544 nodeStack.append(m_expr2.get());
3545 nodeStack.append(m_expr1.get());
3549 JSValue* InstanceOfNode::evaluate(OldInterpreterExecState* exec)
3551 JSValue* v1 = m_expr1->evaluate(exec);
3552 KJS_CHECKEXCEPTIONVALUE
3553 JSValue* v2 = m_expr2->evaluate(exec);
3554 KJS_CHECKEXCEPTIONVALUE
3556 if (!v2->isObject())
3557 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, m_expr2.get());
3559 JSObject* o2 = static_cast<JSObject*>(v2);
3561 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
3562 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
3563 // property. It seems that all objects have the property, but not all implement it, so in this
3564 // case we return false (consistent with Mozilla).
3565 if (!o2->implementsHasInstance())
3566 return jsBoolean(false);
3568 return jsBoolean(o2->hasInstance(exec, v1));
3571 bool InstanceOfNode::evaluateToBoolean(OldInterpreterExecState* exec)
3573 JSValue* v1 = m_expr1->evaluate(exec);
3574 KJS_CHECKEXCEPTIONBOOLEAN
3575 JSValue* v2 = m_expr2->evaluate(exec);
3576 KJS_CHECKEXCEPTIONBOOLEAN
3578 if (!v2->isObject()) {
3579 throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'instanceof' operator.", v2, m_expr2.get());
3583 JSObject* o2 = static_cast<JSObject*>(v2);
3585 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
3586 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
3587 // property. It seems that all objects have the property, but not all implement it, so in this
3588 // case we return false (consistent with Mozilla).
3589 if (!o2->implementsHasInstance())
3592 return o2->hasInstance(exec, v1);
3595 RegisterID* InNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3597 RefPtr<RegisterID> property = generator.emitNode(m_expr1.get());
3598 RegisterID* base = generator.emitNode(m_expr2.get());
3599 return generator.emitIn(generator.finalDestination(dst, property.get()), property.get(), base);
3602 void InNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3604 nodeStack.append(m_expr2.get());
3605 nodeStack.append(m_expr1.get());
3609 JSValue* InNode::evaluate(OldInterpreterExecState* exec)
3611 JSValue* v1 = m_expr1->evaluate(exec);
3612 KJS_CHECKEXCEPTIONVALUE
3613 JSValue* v2 = m_expr2->evaluate(exec);
3614 KJS_CHECKEXCEPTIONVALUE
3616 if (!v2->isObject())
3617 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
3619 return jsBoolean(static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec))));
3622 bool InNode::evaluateToBoolean(OldInterpreterExecState* exec)
3624 JSValue* v1 = m_expr1->evaluate(exec);
3625 KJS_CHECKEXCEPTIONBOOLEAN
3626 JSValue* v2 = m_expr2->evaluate(exec);
3627 KJS_CHECKEXCEPTIONBOOLEAN
3629 if (!v2->isObject()) {
3630 throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
3634 return static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec)));
3637 // ------------------------------ Equality Nodes ------------------------------------
3639 RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3641 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3642 RegisterID* src2 = generator.emitNode(m_expr2.get());
3643 return generator.emitEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3646 void EqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3648 nodeStack.append(m_expr2.get());
3649 nodeStack.append(m_expr1.get());
3653 bool EqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3655 JSValue* v1 = m_expr1->evaluate(exec);
3656 KJS_CHECKEXCEPTIONBOOLEAN
3657 JSValue* v2 = m_expr2->evaluate(exec);
3658 KJS_CHECKEXCEPTIONBOOLEAN
3660 return equal(exec, v1, v2);
3663 JSValue* EqualNode::evaluate(OldInterpreterExecState* exec)
3665 return jsBoolean(inlineEvaluateToBoolean(exec));
3668 bool EqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
3670 return inlineEvaluateToBoolean(exec);
3673 RegisterID* NotEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3675 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3676 RegisterID* src2 = generator.emitNode(m_expr2.get());
3677 return generator.emitNotEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3680 void NotEqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3682 nodeStack.append(m_expr2.get());
3683 nodeStack.append(m_expr1.get());
3687 bool NotEqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3689 JSValue* v1 = m_expr1->evaluate(exec);
3690 KJS_CHECKEXCEPTIONBOOLEAN
3691 JSValue* v2 = m_expr2->evaluate(exec);
3692 KJS_CHECKEXCEPTIONBOOLEAN
3694 return !equal(exec,v1, v2);
3697 JSValue* NotEqualNode::evaluate(OldInterpreterExecState* exec)
3699 return jsBoolean(inlineEvaluateToBoolean(exec));
3702 bool NotEqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
3704 return inlineEvaluateToBoolean(exec);
3707 RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3709 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3710 RegisterID* src2 = generator.emitNode(m_expr2.get());
3711 return generator.emitStrictEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3714 void StrictEqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3716 nodeStack.append(m_expr2.get());
3717 nodeStack.append(m_expr1.get());
3721 bool StrictEqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3723 JSValue* v1 = m_expr1->evaluate(exec);
3724 KJS_CHECKEXCEPTIONBOOLEAN
3725 JSValue* v2 = m_expr2->evaluate(exec);
3726 KJS_CHECKEXCEPTIONBOOLEAN
3728 return strictEqual(v1, v2);
3731 JSValue* StrictEqualNode::evaluate(OldInterpreterExecState* exec)
3733 return jsBoolean(inlineEvaluateToBoolean(exec));
3736 bool StrictEqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
3738 return inlineEvaluateToBoolean(exec);
3741 RegisterID* NotStrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3743 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3744 RegisterID* src2 = generator.emitNode(m_expr2.get());
3745 return generator.emitNotStrictEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3748 void NotStrictEqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3750 nodeStack.append(m_expr2.get());
3751 nodeStack.append(m_expr1.get());
3755 bool NotStrictEqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3757 JSValue* v1 = m_expr1->evaluate(exec);
3758 KJS_CHECKEXCEPTIONBOOLEAN
3759 JSValue* v2 = m_expr2->evaluate(exec);
3760 KJS_CHECKEXCEPTIONBOOLEAN
3762 return !strictEqual(v1, v2);
3765 JSValue* NotStrictEqualNode::evaluate(OldInterpreterExecState* exec)
3767 return jsBoolean(inlineEvaluateToBoolean(exec));
3770 bool NotStrictEqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
3772 return inlineEvaluateToBoolean(exec);
3775 // ------------------------------ Bit Operation Nodes ----------------------------------
3777 RegisterID* BitAndNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3779 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3780 RegisterID* src2 = generator.emitNode(m_expr2.get());
3781 return generator.emitBitAnd(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3784 void BitAndNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3786 nodeStack.append(m_expr2.get());
3787 nodeStack.append(m_expr1.get());
3791 JSValue* BitAndNode::evaluate(OldInterpreterExecState* exec)
3793 JSValue* v1 = m_expr1->evaluate(exec);
3794 KJS_CHECKEXCEPTIONVALUE
3795 JSValue* v2 = m_expr2->evaluate(exec);
3796 KJS_CHECKEXCEPTIONVALUE
3798 return jsNumberFromAnd(exec, v1, v2);
3801 int32_t BitAndNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
3803 int32_t i1 = m_expr1->evaluateToInt32(exec);
3804 KJS_CHECKEXCEPTIONNUMBER
3805 int32_t i2 = m_expr2->evaluateToInt32(exec);
3809 double BitAndNode::evaluateToNumber(OldInterpreterExecState* exec)
3811 return inlineEvaluateToInt32(exec);
3814 bool BitAndNode::evaluateToBoolean(OldInterpreterExecState* exec)
3816 return inlineEvaluateToInt32(exec);
3819 int32_t BitAndNode::evaluateToInt32(OldInterpreterExecState* exec)
3821 return inlineEvaluateToInt32(exec);
3824 uint32_t BitAndNode::evaluateToUInt32(OldInterpreterExecState* exec)
3826 return inlineEvaluateToInt32(exec);
3829 RegisterID* BitXOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3831 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3832 RegisterID* src2 = generator.emitNode(m_expr2.get());
3833 return generator.emitBitXOr(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3836 void BitXOrNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3838 nodeStack.append(m_expr2.get());
3839 nodeStack.append(m_expr1.get());
3842 int32_t BitXOrNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)