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 "ExecState.h"
30 #include "JSGlobalObject.h"
32 #include "PropertyNameArray.h"
33 #include "array_object.h"
35 #include "function_object.h"
37 #include "operations.h"
38 #include "regexp_object.h"
40 #include <wtf/Assertions.h>
41 #include <wtf/HashCountedSet.h>
42 #include <wtf/HashSet.h>
43 #include <wtf/MathExtras.h>
44 #if USE(MULTIPLE_THREADS)
45 #include <wtf/ThreadSpecific.h>
52 class FunctionBodyNodeWithDebuggerHooks : public FunctionBodyNode {
54 FunctionBodyNodeWithDebuggerHooks(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
55 virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
60 __builtin_expect ((x), 0)
65 #define KJS_CHECKEXCEPTION \
66 if (UNLIKELY(exec->hadException())) \
67 return rethrowException(exec);
69 #define KJS_CHECKEXCEPTIONVALUE \
70 if (UNLIKELY(exec->hadException())) { \
71 handleException(exec); \
72 return jsUndefined(); \
75 #define KJS_CHECKEXCEPTIONNUMBER \
76 if (UNLIKELY(exec->hadException())) { \
77 handleException(exec); \
81 #define KJS_CHECKEXCEPTIONBOOLEAN \
82 if (UNLIKELY(exec->hadException())) { \
83 handleException(exec); \
87 #define KJS_CHECKEXCEPTIONVOID \
88 if (UNLIKELY(exec->hadException())) { \
89 handleException(exec); \
94 static inline bool canSkipLookup(ExecState* exec, const Identifier& ident)
96 // Static lookup in EvalCode is impossible because variables aren't DontDelete.
97 // Static lookup in GlobalCode may be possible, but we haven't implemented support for it yet.
98 if (exec->codeType() != FunctionCode)
101 // Static lookup is impossible when something dynamic has been added to the front of the scope chain.
102 if (exec->variableObject() != exec->scopeChain().top())
105 // Static lookup is impossible if the symbol isn't statically declared.
106 if (!exec->variableObject()->symbolTable().contains(ident.ustring().rep()))
113 static inline bool isConstant(const LocalStorage& localStorage, size_t index)
115 ASSERT(index < localStorage.size());
116 return localStorage[index].attributes & ReadOnly;
119 // ------------------------------ Node -----------------------------------------
122 #ifndef LOG_CHANNEL_PREFIX
123 #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()
142 #if USE(MULTIPLE_THREADS)
143 static ThreadSpecific<HashSet<ParserRefCounted*> > sharedInstance;
144 return sharedInstance;
146 static HashSet<ParserRefCounted*> sharedInstance;
147 return &sharedInstance;
151 static HashCountedSet<ParserRefCounted*>* trackedObjectExtraRefCounts()
153 #if USE(MULTIPLE_THREADS)
154 static ThreadSpecific<HashCountedSet<ParserRefCounted*> > sharedInstance;
155 return sharedInstance;
157 static HashCountedSet<ParserRefCounted*> sharedInstance;
158 return &sharedInstance;
162 void initializeNodesThreading()
165 trackedObjectExtraRefCounts();
168 ParserRefCounted::ParserRefCounted()
171 ++ParserRefCountedCounter::count;
173 newTrackedObjects()->add(this);
174 ASSERT(newTrackedObjects()->contains(this));
177 ParserRefCounted::~ParserRefCounted()
180 --ParserRefCountedCounter::count;
184 void ParserRefCounted::ref()
186 HashSet<ParserRefCounted*>* localNewTrackedObjects = newTrackedObjects();
188 // bumping from 0 to 1 is just removing from the new nodes set
189 HashSet<ParserRefCounted*>::iterator it = localNewTrackedObjects->find(this);
190 if (it != localNewTrackedObjects->end()) {
191 localNewTrackedObjects->remove(it);
192 ASSERT(!trackedObjectExtraRefCounts()->contains(this));
196 ASSERT(!localNewTrackedObjects->contains(this));
198 trackedObjectExtraRefCounts()->add(this);
201 void ParserRefCounted::deref()
203 ASSERT(!newTrackedObjects()->contains(this));
204 HashCountedSet<ParserRefCounted*>* localTrackedObjectExtraRefCounts = trackedObjectExtraRefCounts();
206 HashCountedSet<ParserRefCounted*>::iterator it = localTrackedObjectExtraRefCounts->find(this);
207 if (it == localTrackedObjectExtraRefCounts->end())
210 localTrackedObjectExtraRefCounts->remove(it);
213 unsigned ParserRefCounted::refcount()
215 HashCountedSet<ParserRefCounted*>* localTrackedObjectExtraRefCounts = trackedObjectExtraRefCounts();
217 if (newTrackedObjects()->contains(this)) {
218 ASSERT(!localTrackedObjectExtraRefCounts->contains(this));
222 ASSERT(!newTrackedObjects()->contains(this));
224 if (!localTrackedObjectExtraRefCounts)
227 return 1 + localTrackedObjectExtraRefCounts->count(this);
230 void ParserRefCounted::deleteNewObjects()
232 HashSet<ParserRefCounted*>* localNewTrackedObjects = newTrackedObjects();
234 HashSet<ParserRefCounted*>::iterator end = localNewTrackedObjects->end();
235 for (HashSet<ParserRefCounted*>::iterator it = localNewTrackedObjects->begin(); it != end; ++it)
236 ASSERT(!trackedObjectExtraRefCounts()->contains(*it));
238 deleteAllValues(*localNewTrackedObjects);
239 localNewTrackedObjects->clear();
243 : m_expectedReturnType(ObjectType)
245 m_line = lexer().lineNo();
248 Node::Node(JSType expectedReturn)
249 : m_expectedReturnType(expectedReturn)
251 m_line = lexer().lineNo();
254 double ExpressionNode::evaluateToNumber(ExecState* exec)
256 JSValue* value = evaluate(exec);
257 KJS_CHECKEXCEPTIONNUMBER
258 return value->toNumber(exec);
261 bool ExpressionNode::evaluateToBoolean(ExecState* exec)
263 JSValue* value = evaluate(exec);
264 KJS_CHECKEXCEPTIONBOOLEAN
265 return value->toBoolean(exec);
268 int32_t ExpressionNode::evaluateToInt32(ExecState* exec)
270 JSValue* value = evaluate(exec);
271 KJS_CHECKEXCEPTIONNUMBER
272 return value->toInt32(exec);
275 uint32_t ExpressionNode::evaluateToUInt32(ExecState* exec)
277 JSValue* value = evaluate(exec);
278 KJS_CHECKEXCEPTIONNUMBER
279 return value->toUInt32(exec);
282 static void substitute(UString& string, const UString& substring) KJS_FAST_CALL;
283 static void substitute(UString& string, const UString& substring)
285 int position = string.find("%s");
286 ASSERT(position != -1);
287 UString newString = string.substr(0, position);
288 newString.append(substring);
289 newString.append(string.substr(position + 2));
293 static inline int currentSourceId(ExecState* exec) KJS_FAST_CALL;
294 static inline int currentSourceId(ExecState* exec)
296 return exec->scopeNode()->sourceId();
299 static inline const UString& currentSourceURL(ExecState* exec) KJS_FAST_CALL;
300 static inline const UString& currentSourceURL(ExecState* exec)
302 return exec->scopeNode()->sourceURL();
305 JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg)
307 return exec->setThrowCompletion(Error::create(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
310 JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg, const Identifier& ident)
312 UString message = msg;
313 substitute(message, ident.ustring());
314 return exec->setThrowCompletion(Error::create(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
317 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg)
319 return KJS::throwError(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec));
322 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const char* string)
324 UString message = msg;
325 substitute(message, string);
326 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
329 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr)
331 UString message = msg;
332 substitute(message, v->toString(exec));
333 substitute(message, expr->toString());
334 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
337 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const Identifier& label)
339 UString message = msg;
340 substitute(message, label.ustring());
341 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
344 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* e1, Node* e2)
346 UString message = msg;
347 substitute(message, v->toString(exec));
348 substitute(message, e1->toString());
349 substitute(message, e2->toString());
350 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
353 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr, const Identifier& label)
355 UString message = msg;
356 substitute(message, v->toString(exec));
357 substitute(message, expr->toString());
358 substitute(message, label.ustring());
359 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
362 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, const Identifier& label)
364 UString message = msg;
365 substitute(message, v->toString(exec));
366 substitute(message, label.ustring());
367 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
370 JSValue* Node::throwUndefinedVariableError(ExecState* exec, const Identifier& ident)
372 return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
375 void Node::handleException(ExecState* exec)
377 handleException(exec, exec->exception());
380 void Node::handleException(ExecState* exec, JSValue* exceptionValue)
382 if (exceptionValue->isObject()) {
383 JSObject* exception = static_cast<JSObject*>(exceptionValue);
384 if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
385 exception->put(exec, "line", jsNumber(exec, m_line));
386 exception->put(exec, "sourceURL", jsString(exec, currentSourceURL(exec)));
389 Debugger* dbg = exec->dynamicGlobalObject()->debugger();
390 if (dbg && !dbg->hasHandledException(exec, exceptionValue))
391 dbg->exception(exec, currentSourceId(exec), m_line, exceptionValue);
394 NEVER_INLINE JSValue* Node::rethrowException(ExecState* exec)
396 JSValue* exception = exec->exception();
397 exec->clearException();
398 handleException(exec, exception);
399 return exec->setThrowCompletion(exception);
402 // ------------------------------ StatementNode --------------------------------
404 StatementNode::StatementNode()
410 void StatementNode::setLoc(int firstLine, int lastLine)
413 m_lastLine = lastLine;
416 // ------------------------------ SourceElements --------------------------------
418 void SourceElements::append(PassRefPtr<StatementNode> statement)
420 if (statement->isEmptyStatement())
423 if (Debugger::debuggersPresent)
424 m_statements.append(new BreakpointCheckStatement(statement));
426 m_statements.append(statement);
429 // ------------------------------ BreakpointCheckStatement --------------------------------
431 BreakpointCheckStatement::BreakpointCheckStatement(PassRefPtr<StatementNode> statement)
432 : m_statement(statement)
437 JSValue* BreakpointCheckStatement::execute(ExecState* exec)
439 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger())
440 if (!debugger->atStatement(exec, currentSourceId(exec), m_statement->firstLine(), m_statement->lastLine()))
441 return exec->setNormalCompletion();
442 return m_statement->execute(exec);
445 void BreakpointCheckStatement::streamTo(SourceStream& stream) const
447 m_statement->streamTo(stream);
450 void BreakpointCheckStatement::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
452 nodeStack.append(m_statement.get());
455 // ------------------------------ NullNode -------------------------------------
457 JSValue* NullNode::evaluate(ExecState* )
462 // ------------------------------ FalseNode ----------------------------------
464 JSValue* FalseNode::evaluate(ExecState*)
466 return jsBoolean(false);
469 // ------------------------------ TrueNode ----------------------------------
471 JSValue* TrueNode::evaluate(ExecState*)
473 return jsBoolean(true);
476 // ------------------------------ NumberNode -----------------------------------
478 JSValue* NumberNode::evaluate(ExecState* exec)
480 // Number nodes are only created when the number can't fit in a JSImmediate, so no need to check again.
481 return jsNumberCell(exec, m_double);
484 double NumberNode::evaluateToNumber(ExecState*)
489 bool NumberNode::evaluateToBoolean(ExecState*)
491 return m_double < 0.0 || m_double > 0.0; // false for NaN as well as 0
494 int32_t NumberNode::evaluateToInt32(ExecState*)
496 return JSValue::toInt32(m_double);
499 uint32_t NumberNode::evaluateToUInt32(ExecState*)
501 return JSValue::toUInt32(m_double);
504 // ------------------------------ ImmediateNumberNode -----------------------------------
506 JSValue* ImmediateNumberNode::evaluate(ExecState*)
511 int32_t ImmediateNumberNode::evaluateToInt32(ExecState*)
513 return JSImmediate::getTruncatedInt32(m_value);
516 uint32_t ImmediateNumberNode::evaluateToUInt32(ExecState*)
519 if (JSImmediate::getTruncatedUInt32(m_value, i))
522 return JSValue::toUInt32SlowCase(m_double, ok);
525 // ------------------------------ StringNode -----------------------------------
527 JSValue* StringNode::evaluate(ExecState* exec)
529 return jsOwnedString(exec, m_value);
532 double StringNode::evaluateToNumber(ExecState*)
534 return m_value.toDouble();
537 bool StringNode::evaluateToBoolean(ExecState*)
539 return !m_value.isEmpty();
542 // ------------------------------ RegExpNode -----------------------------------
544 JSValue* RegExpNode::evaluate(ExecState* exec)
546 return exec->lexicalGlobalObject()->regExpConstructor()->createRegExpImp(exec, m_regExp);
549 // ------------------------------ ThisNode -------------------------------------
552 JSValue* ThisNode::evaluate(ExecState* exec)
554 return exec->thisValue();
557 // ------------------------------ ResolveNode ----------------------------------
559 // ECMA 11.1.2 & 10.1.4
560 JSValue* ResolveNode::inlineEvaluate(ExecState* exec)
562 // Check for missed optimization opportunity.
563 ASSERT(!canSkipLookup(exec, m_ident));
565 const ScopeChain& chain = exec->scopeChain();
566 ScopeChainIterator iter = chain.begin();
567 ScopeChainIterator end = chain.end();
569 // we must always have something in the scope chain
576 if (o->getPropertySlot(exec, m_ident, slot))
577 return slot.getValue(exec, o, m_ident);
580 } while (iter != end);
582 return throwUndefinedVariableError(exec, m_ident);
585 JSValue* ResolveNode::evaluate(ExecState* exec)
587 return inlineEvaluate(exec);
590 double ResolveNode::evaluateToNumber(ExecState* exec)
592 JSValue* v = inlineEvaluate(exec);
593 KJS_CHECKEXCEPTIONNUMBER
594 return v->toNumber(exec);
597 bool ResolveNode::evaluateToBoolean(ExecState* exec)
599 JSValue* v = inlineEvaluate(exec);
600 KJS_CHECKEXCEPTIONBOOLEAN
601 return v->toBoolean(exec);
604 int32_t ResolveNode::evaluateToInt32(ExecState* exec)
606 JSValue* v = inlineEvaluate(exec);
607 KJS_CHECKEXCEPTIONNUMBER
608 return v->toInt32(exec);
611 uint32_t ResolveNode::evaluateToUInt32(ExecState* exec)
613 JSValue* v = inlineEvaluate(exec);
614 KJS_CHECKEXCEPTIONNUMBER
615 return v->toUInt32(exec);
618 static size_t getSymbolTableEntry(ExecState* exec, const Identifier& ident, const SymbolTable& symbolTable, size_t& stackDepth)
620 size_t index = symbolTable.get(ident.ustring().rep());
621 if (index != missingSymbolMarker()) {
626 if (ident == exec->propertyNames().arguments) {
628 return missingSymbolMarker();
631 const ScopeChain& chain = exec->scopeChain();
632 ScopeChainIterator iter = chain.begin();
633 ScopeChainIterator end = chain.end();
635 for (; iter != end; ++iter, ++depth) {
636 JSObject* currentScope = *iter;
637 if (!currentScope->isVariableObject())
639 JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
640 index = currentVariableObject->symbolTable().get(ident.ustring().rep());
641 if (index != missingSymbolMarker()) {
645 if (currentVariableObject->isDynamicScope())
649 return missingSymbolMarker();
652 void ResolveNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
655 size_t index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
656 if (index != missingSymbolMarker()) {
658 new (this) LocalVarAccessNode(index);
660 new (this) ScopedVarAccessNode(index, depth);
667 new (this) NonLocalVarAccessNode(depth);
670 JSValue* LocalVarAccessNode::inlineEvaluate(ExecState* exec)
672 ASSERT(exec->variableObject() == exec->scopeChain().top());
673 return exec->localStorage()[m_index].value;
676 JSValue* LocalVarAccessNode::evaluate(ExecState* exec)
678 return inlineEvaluate(exec);
681 double LocalVarAccessNode::evaluateToNumber(ExecState* exec)
683 return inlineEvaluate(exec)->toNumber(exec);
686 bool LocalVarAccessNode::evaluateToBoolean(ExecState* exec)
688 return inlineEvaluate(exec)->toBoolean(exec);
691 int32_t LocalVarAccessNode::evaluateToInt32(ExecState* exec)
693 return inlineEvaluate(exec)->toInt32(exec);
696 uint32_t LocalVarAccessNode::evaluateToUInt32(ExecState* exec)
698 return inlineEvaluate(exec)->toUInt32(exec);
701 static inline JSValue* getNonLocalSymbol(ExecState* exec, size_t index, size_t scopeDepth)
703 const ScopeChain& chain = exec->scopeChain();
704 ScopeChainIterator iter = chain.begin();
705 for (size_t i = 0; i < scopeDepth; ++iter, ++i)
706 ASSERT(iter != chain.end());
707 JSObject* scope = *iter;
708 ASSERT(scope->isVariableObject());
709 JSVariableObject* variableObject = static_cast<JSVariableObject*>(scope);
710 return variableObject->localStorage()[index].value;
713 JSValue* ScopedVarAccessNode::inlineEvaluate(ExecState* exec)
715 return getNonLocalSymbol(exec, m_index, m_scopeDepth);
718 JSValue* ScopedVarAccessNode::evaluate(ExecState* exec)
720 return inlineEvaluate(exec);
723 double ScopedVarAccessNode::evaluateToNumber(ExecState* exec)
725 return inlineEvaluate(exec)->toNumber(exec);
728 bool ScopedVarAccessNode::evaluateToBoolean(ExecState* exec)
730 return inlineEvaluate(exec)->toBoolean(exec);
733 int32_t ScopedVarAccessNode::evaluateToInt32(ExecState* exec)
735 return inlineEvaluate(exec)->toInt32(exec);
738 uint32_t ScopedVarAccessNode::evaluateToUInt32(ExecState* exec)
740 return inlineEvaluate(exec)->toUInt32(exec);
743 JSValue* NonLocalVarAccessNode::inlineEvaluate(ExecState* exec)
745 // Check for missed optimization opportunity.
746 ASSERT(!canSkipLookup(exec, m_ident));
748 const ScopeChain& chain = exec->scopeChain();
749 ScopeChainIterator iter = chain.begin();
750 ScopeChainIterator end = chain.end();
751 for (size_t i = 0; i < m_scopeDepth; ++i, ++iter)
754 // we must always have something in the scope chain
761 if (o->getPropertySlot(exec, m_ident, slot))
762 return slot.getValue(exec, o, m_ident);
765 } while (iter != end);
767 return throwUndefinedVariableError(exec, m_ident);
770 JSValue* NonLocalVarAccessNode::evaluate(ExecState* exec)
772 return inlineEvaluate(exec);
775 double NonLocalVarAccessNode::evaluateToNumber(ExecState* exec)
777 return inlineEvaluate(exec)->toNumber(exec);
780 bool NonLocalVarAccessNode::evaluateToBoolean(ExecState* exec)
782 return inlineEvaluate(exec)->toBoolean(exec);
785 int32_t NonLocalVarAccessNode::evaluateToInt32(ExecState* exec)
787 return inlineEvaluate(exec)->toInt32(exec);
790 uint32_t NonLocalVarAccessNode::evaluateToUInt32(ExecState* exec)
792 return inlineEvaluate(exec)->toUInt32(exec);
795 // ------------------------------ ElementNode ----------------------------------
797 void ElementNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
800 nodeStack.append(m_next.get());
802 nodeStack.append(m_node.get());
806 JSValue* ElementNode::evaluate(ExecState* exec)
808 JSObject* array = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
810 for (ElementNode* n = this; n; n = n->m_next.get()) {
811 JSValue* val = n->m_node->evaluate(exec);
812 KJS_CHECKEXCEPTIONVALUE
813 length += n->m_elision;
814 array->put(exec, length++, val);
819 // ------------------------------ ArrayNode ------------------------------------
821 void ArrayNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
824 nodeStack.append(m_element.get());
828 JSValue* ArrayNode::evaluate(ExecState* exec)
834 array = static_cast<JSObject*>(m_element->evaluate(exec));
835 KJS_CHECKEXCEPTIONVALUE
836 length = m_optional ? array->get(exec, exec->propertyNames().length)->toInt32(exec) : 0;
838 JSValue* newArr = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
839 array = static_cast<JSObject*>(newArr);
844 array->put(exec, exec->propertyNames().length, jsNumber(exec, m_elision + length));
849 // ------------------------------ ObjectLiteralNode ----------------------------
851 void ObjectLiteralNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
854 nodeStack.append(m_list.get());
858 JSValue* ObjectLiteralNode::evaluate(ExecState* exec)
861 return m_list->evaluate(exec);
863 return exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
866 // ------------------------------ PropertyListNode -----------------------------
868 void PropertyListNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
871 nodeStack.append(m_next.get());
872 nodeStack.append(m_node.get());
876 JSValue* PropertyListNode::evaluate(ExecState* exec)
878 JSObject* obj = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
880 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
881 JSValue* v = p->m_node->m_assign->evaluate(exec);
882 KJS_CHECKEXCEPTIONVALUE
884 switch (p->m_node->m_type) {
885 case PropertyNode::Getter:
886 ASSERT(v->isObject());
887 obj->defineGetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
889 case PropertyNode::Setter:
890 ASSERT(v->isObject());
891 obj->defineSetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
893 case PropertyNode::Constant:
894 obj->put(exec, p->m_node->name(), v);
902 // ------------------------------ PropertyNode -----------------------------
904 void PropertyNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
906 nodeStack.append(m_assign.get());
910 JSValue* PropertyNode::evaluate(ExecState*)
916 // ------------------------------ BracketAccessorNode --------------------------------
918 void BracketAccessorNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
920 nodeStack.append(m_subscript.get());
921 nodeStack.append(m_base.get());
925 JSValue* BracketAccessorNode::inlineEvaluate(ExecState* exec)
927 JSValue* v1 = m_base->evaluate(exec);
928 KJS_CHECKEXCEPTIONVALUE
929 JSValue* v2 = m_subscript->evaluate(exec);
930 KJS_CHECKEXCEPTIONVALUE
931 JSObject* o = v1->toObject(exec);
933 if (v2->getUInt32(i))
934 return o->get(exec, i);
935 return o->get(exec, Identifier(v2->toString(exec)));
938 JSValue* BracketAccessorNode::evaluate(ExecState* exec)
940 return inlineEvaluate(exec);
943 double BracketAccessorNode::evaluateToNumber(ExecState* exec)
945 JSValue* v = inlineEvaluate(exec);
946 KJS_CHECKEXCEPTIONNUMBER
947 return v->toNumber(exec);
950 bool BracketAccessorNode::evaluateToBoolean(ExecState* exec)
952 JSValue* v = inlineEvaluate(exec);
953 KJS_CHECKEXCEPTIONBOOLEAN
954 return v->toBoolean(exec);
957 int32_t BracketAccessorNode::evaluateToInt32(ExecState* exec)
959 JSValue* v = inlineEvaluate(exec);
960 KJS_CHECKEXCEPTIONNUMBER
961 return v->toInt32(exec);
964 uint32_t BracketAccessorNode::evaluateToUInt32(ExecState* exec)
966 JSValue* v = inlineEvaluate(exec);
967 KJS_CHECKEXCEPTIONNUMBER
968 return v->toUInt32(exec);
971 // ------------------------------ DotAccessorNode --------------------------------
973 void DotAccessorNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
975 nodeStack.append(m_base.get());
979 JSValue* DotAccessorNode::inlineEvaluate(ExecState* exec)
981 JSValue* v = m_base->evaluate(exec);
982 KJS_CHECKEXCEPTIONVALUE
983 return v->toObject(exec)->get(exec, m_ident);
986 JSValue* DotAccessorNode::evaluate(ExecState* exec)
988 return inlineEvaluate(exec);
991 double DotAccessorNode::evaluateToNumber(ExecState* exec)
993 JSValue* v = inlineEvaluate(exec);
994 KJS_CHECKEXCEPTIONNUMBER
995 return v->toNumber(exec);
998 bool DotAccessorNode::evaluateToBoolean(ExecState* exec)
1000 JSValue* v = inlineEvaluate(exec);
1001 KJS_CHECKEXCEPTIONBOOLEAN
1002 return v->toBoolean(exec);
1005 int32_t DotAccessorNode::evaluateToInt32(ExecState* exec)
1007 JSValue* v = inlineEvaluate(exec);
1008 KJS_CHECKEXCEPTIONNUMBER
1009 return v->toInt32(exec);
1012 uint32_t DotAccessorNode::evaluateToUInt32(ExecState* exec)
1014 JSValue* v = inlineEvaluate(exec);
1015 KJS_CHECKEXCEPTIONNUMBER
1016 return v->toUInt32(exec);
1019 // ------------------------------ ArgumentListNode -----------------------------
1021 void ArgumentListNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1024 nodeStack.append(m_next.get());
1026 nodeStack.append(m_expr.get());
1030 void ArgumentListNode::evaluateList(ExecState* exec, List& list)
1032 for (ArgumentListNode* n = this; n; n = n->m_next.get()) {
1033 JSValue* v = n->m_expr->evaluate(exec);
1034 KJS_CHECKEXCEPTIONVOID
1039 // ------------------------------ ArgumentsNode --------------------------------
1041 void ArgumentsNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1044 nodeStack.append(m_listNode.get());
1047 // ------------------------------ NewExprNode ----------------------------------
1049 void NewExprNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1052 nodeStack.append(m_args.get());
1053 nodeStack.append(m_expr.get());
1058 JSValue* NewExprNode::inlineEvaluate(ExecState* exec)
1060 JSValue* v = m_expr->evaluate(exec);
1061 KJS_CHECKEXCEPTIONVALUE
1065 m_args->evaluateList(exec, argList);
1066 KJS_CHECKEXCEPTIONVALUE
1070 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, m_expr.get());
1072 JSObject* constr = static_cast<JSObject*>(v);
1073 if (!constr->implementsConstruct())
1074 return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, m_expr.get());
1076 return constr->construct(exec, argList);
1079 JSValue* NewExprNode::evaluate(ExecState* exec)
1081 return inlineEvaluate(exec);
1084 double NewExprNode::evaluateToNumber(ExecState* exec)
1086 JSValue* v = inlineEvaluate(exec);
1087 KJS_CHECKEXCEPTIONNUMBER
1088 return v->toNumber(exec);
1091 bool NewExprNode::evaluateToBoolean(ExecState* exec)
1093 JSValue* v = inlineEvaluate(exec);
1094 KJS_CHECKEXCEPTIONBOOLEAN
1095 return v->toBoolean(exec);
1098 int32_t NewExprNode::evaluateToInt32(ExecState* exec)
1100 JSValue* v = inlineEvaluate(exec);
1101 KJS_CHECKEXCEPTIONNUMBER
1102 return v->toInt32(exec);
1105 uint32_t NewExprNode::evaluateToUInt32(ExecState* exec)
1107 JSValue* v = inlineEvaluate(exec);
1108 KJS_CHECKEXCEPTIONNUMBER
1109 return v->toUInt32(exec);
1112 template <ExpressionNode::CallerType callerType, bool scopeDepthIsZero>
1113 inline JSValue* ExpressionNode::resolveAndCall(ExecState* exec, const Identifier& ident, ArgumentsNode* args, size_t scopeDepth)
1115 const ScopeChain& chain = exec->scopeChain();
1116 ScopeChainIterator iter = chain.begin();
1117 ScopeChainIterator end = chain.end();
1119 if (!scopeDepthIsZero) {
1120 for (size_t i = 0; i < scopeDepth; ++iter, ++i)
1121 ASSERT(iter != chain.end());
1124 // we must always have something in the scope chain
1125 ASSERT(iter != end);
1131 if (base->getPropertySlot(exec, ident, slot)) {
1132 JSValue* v = slot.getValue(exec, base, ident);
1133 KJS_CHECKEXCEPTIONVALUE
1136 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
1138 JSObject* func = static_cast<JSObject*>(v);
1140 if (!func->implementsCall())
1141 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
1144 args->evaluateList(exec, argList);
1145 KJS_CHECKEXCEPTIONVALUE
1147 if (callerType == EvalOperator) {
1148 if (base == exec->lexicalGlobalObject() && func == exec->lexicalGlobalObject()->evalFunction()) {
1149 exec->dynamicGlobalObject()->tearOffActivation(exec);
1150 return eval(exec, exec->scopeChain(), exec->variableObject(), exec->dynamicGlobalObject(), exec->thisValue(), argList);
1154 JSObject* thisObj = base->toThisObject(exec);
1155 return func->call(exec, thisObj, argList);
1158 } while (iter != end);
1160 return throwUndefinedVariableError(exec, ident);
1163 void EvalFunctionCallNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1165 nodeStack.append(m_args.get());
1168 JSValue* EvalFunctionCallNode::evaluate(ExecState* exec)
1170 return resolveAndCall<EvalOperator, true>(exec, exec->propertyNames().eval, m_args.get());
1173 void FunctionCallValueNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1175 nodeStack.append(m_args.get());
1176 nodeStack.append(m_expr.get());
1180 JSValue* FunctionCallValueNode::evaluate(ExecState* exec)
1182 JSValue* v = m_expr->evaluate(exec);
1183 KJS_CHECKEXCEPTIONVALUE
1185 if (!v->isObject()) {
1186 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_expr.get());
1189 JSObject* func = static_cast<JSObject*>(v);
1191 if (!func->implementsCall()) {
1192 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_expr.get());
1196 m_args->evaluateList(exec, argList);
1197 KJS_CHECKEXCEPTIONVALUE
1199 JSObject* thisObj = exec->globalThisValue();
1200 return func->call(exec, thisObj, argList);
1203 void FunctionCallResolveNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
1205 nodeStack.append(m_args.get());
1208 size_t index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
1209 if (index != missingSymbolMarker()) {
1211 new (this) LocalVarFunctionCallNode(index);
1213 new (this) ScopedVarFunctionCallNode(index, depth);
1220 new (this) NonLocalVarFunctionCallNode(depth);
1224 JSValue* FunctionCallResolveNode::inlineEvaluate(ExecState* exec)
1226 // Check for missed optimization opportunity.
1227 ASSERT(!canSkipLookup(exec, m_ident));
1229 return resolveAndCall<FunctionCall, true>(exec, m_ident, m_args.get());
1232 JSValue* FunctionCallResolveNode::evaluate(ExecState* exec)
1234 return inlineEvaluate(exec);
1237 double FunctionCallResolveNode::evaluateToNumber(ExecState* exec)
1239 JSValue* v = inlineEvaluate(exec);
1240 KJS_CHECKEXCEPTIONNUMBER
1241 return v->toNumber(exec);
1244 bool FunctionCallResolveNode::evaluateToBoolean(ExecState* exec)
1246 JSValue* v = inlineEvaluate(exec);
1247 KJS_CHECKEXCEPTIONBOOLEAN
1248 return v->toBoolean(exec);
1251 int32_t FunctionCallResolveNode::evaluateToInt32(ExecState* exec)
1253 JSValue* v = inlineEvaluate(exec);
1254 KJS_CHECKEXCEPTIONNUMBER
1255 return v->toInt32(exec);
1258 uint32_t FunctionCallResolveNode::evaluateToUInt32(ExecState* exec)
1260 JSValue* v = inlineEvaluate(exec);
1261 KJS_CHECKEXCEPTIONNUMBER
1262 return v->toUInt32(exec);
1265 JSValue* LocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
1267 ASSERT(exec->variableObject() == exec->scopeChain().top());
1269 JSValue* v = exec->localStorage()[m_index].value;
1272 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
1274 JSObject* func = static_cast<JSObject*>(v);
1275 if (!func->implementsCall())
1276 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
1279 m_args->evaluateList(exec, argList);
1280 KJS_CHECKEXCEPTIONVALUE
1282 JSObject* thisObj = exec->globalThisValue();
1283 return func->call(exec, thisObj, argList);
1286 JSValue* LocalVarFunctionCallNode::evaluate(ExecState* exec)
1288 return inlineEvaluate(exec);
1291 double LocalVarFunctionCallNode::evaluateToNumber(ExecState* exec)
1293 JSValue* v = inlineEvaluate(exec);
1294 KJS_CHECKEXCEPTIONNUMBER
1295 return v->toNumber(exec);
1298 bool LocalVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
1300 JSValue* v = inlineEvaluate(exec);
1301 KJS_CHECKEXCEPTIONBOOLEAN
1302 return v->toBoolean(exec);
1305 int32_t LocalVarFunctionCallNode::evaluateToInt32(ExecState* exec)
1307 JSValue* v = inlineEvaluate(exec);
1308 KJS_CHECKEXCEPTIONNUMBER
1309 return v->toInt32(exec);
1312 uint32_t LocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
1314 JSValue* v = inlineEvaluate(exec);
1315 KJS_CHECKEXCEPTIONNUMBER
1316 return v->toUInt32(exec);
1319 JSValue* ScopedVarFunctionCallNode::inlineEvaluate(ExecState* exec)
1321 ASSERT(exec->variableObject() == exec->scopeChain().top());
1323 JSValue* v = getNonLocalSymbol(exec, m_index, m_scopeDepth);
1326 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
1328 JSObject* func = static_cast<JSObject*>(v);
1329 if (!func->implementsCall())
1330 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
1333 m_args->evaluateList(exec, argList);
1334 KJS_CHECKEXCEPTIONVALUE
1336 JSObject* thisObj = exec->globalThisValue();
1337 return func->call(exec, thisObj, argList);
1340 JSValue* ScopedVarFunctionCallNode::evaluate(ExecState* exec)
1342 return inlineEvaluate(exec);
1345 double ScopedVarFunctionCallNode::evaluateToNumber(ExecState* exec)
1347 JSValue* v = inlineEvaluate(exec);
1348 KJS_CHECKEXCEPTIONNUMBER
1349 return v->toNumber(exec);
1352 bool ScopedVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
1354 JSValue* v = inlineEvaluate(exec);
1355 KJS_CHECKEXCEPTIONBOOLEAN
1356 return v->toBoolean(exec);
1359 int32_t ScopedVarFunctionCallNode::evaluateToInt32(ExecState* exec)
1361 JSValue* v = inlineEvaluate(exec);
1362 KJS_CHECKEXCEPTIONNUMBER
1363 return v->toInt32(exec);
1366 uint32_t ScopedVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
1368 JSValue* v = inlineEvaluate(exec);
1369 KJS_CHECKEXCEPTIONNUMBER
1370 return v->toUInt32(exec);
1373 JSValue* NonLocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
1375 // Check for missed optimization opportunity.
1376 ASSERT(!canSkipLookup(exec, m_ident));
1378 return resolveAndCall<FunctionCall, false>(exec, m_ident, m_args.get(), m_scopeDepth);
1381 JSValue* NonLocalVarFunctionCallNode::evaluate(ExecState* exec)
1383 return inlineEvaluate(exec);
1386 double NonLocalVarFunctionCallNode::evaluateToNumber(ExecState* exec)
1388 JSValue* v = inlineEvaluate(exec);
1389 KJS_CHECKEXCEPTIONNUMBER
1390 return v->toNumber(exec);
1393 bool NonLocalVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
1395 JSValue* v = inlineEvaluate(exec);
1396 KJS_CHECKEXCEPTIONBOOLEAN
1397 return v->toBoolean(exec);
1400 int32_t NonLocalVarFunctionCallNode::evaluateToInt32(ExecState* exec)
1402 JSValue* v = inlineEvaluate(exec);
1403 KJS_CHECKEXCEPTIONNUMBER
1404 return v->toInt32(exec);
1407 uint32_t NonLocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
1409 JSValue* v = inlineEvaluate(exec);
1410 KJS_CHECKEXCEPTIONNUMBER
1411 return v->toUInt32(exec);
1414 void FunctionCallBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1416 nodeStack.append(m_args.get());
1417 nodeStack.append(m_subscript.get());
1418 nodeStack.append(m_base.get());
1422 JSValue* FunctionCallBracketNode::evaluate(ExecState* exec)
1424 JSValue* baseVal = m_base->evaluate(exec);
1425 KJS_CHECKEXCEPTIONVALUE
1427 JSValue* subscriptVal = m_subscript->evaluate(exec);
1429 JSObject* baseObj = baseVal->toObject(exec);
1434 if (subscriptVal->getUInt32(i)) {
1435 if (baseObj->getPropertySlot(exec, i, slot))
1436 funcVal = slot.getValue(exec, baseObj, i);
1438 funcVal = jsUndefined();
1440 Identifier ident(subscriptVal->toString(exec));
1441 if (baseObj->getPropertySlot(exec, ident, slot))
1442 funcVal = baseObj->get(exec, ident);
1444 funcVal = jsUndefined();
1447 KJS_CHECKEXCEPTIONVALUE
1449 if (!funcVal->isObject())
1450 return throwError(exec, TypeError, "Value %s (result of expression %s[%s]) is not object.", funcVal, m_base.get(), m_subscript.get());
1452 JSObject* func = static_cast<JSObject*>(funcVal);
1454 if (!func->implementsCall())
1455 return throwError(exec, TypeError, "Object %s (result of expression %s[%s]) does not allow calls.", funcVal, m_base.get(), m_subscript.get());
1458 m_args->evaluateList(exec, argList);
1459 KJS_CHECKEXCEPTIONVALUE
1461 JSObject* thisObj = baseObj;
1463 ASSERT(thisObj->isObject());
1464 ASSERT(!thisObj->isActivationObject());
1466 // No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
1467 return func->call(exec, thisObj, argList);
1470 static const char* dotExprNotAnObjectString() KJS_FAST_CALL;
1471 static const char* dotExprNotAnObjectString()
1473 return "Value %s (result of expression %s.%s) is not object.";
1476 static const char* dotExprDoesNotAllowCallsString() KJS_FAST_CALL;
1477 static const char* dotExprDoesNotAllowCallsString()
1479 return "Object %s (result of expression %s.%s) does not allow calls.";
1482 void FunctionCallDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1484 nodeStack.append(m_args.get());
1485 nodeStack.append(m_base.get());
1489 JSValue* FunctionCallDotNode::inlineEvaluate(ExecState* exec)
1491 JSValue* baseVal = m_base->evaluate(exec);
1492 KJS_CHECKEXCEPTIONVALUE
1494 JSObject* baseObj = baseVal->toObject(exec);
1496 JSValue* funcVal = baseObj->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, baseObj, m_ident) : jsUndefined();
1497 KJS_CHECKEXCEPTIONVALUE
1499 if (!funcVal->isObject())
1500 return throwError(exec, TypeError, dotExprNotAnObjectString(), funcVal, m_base.get(), m_ident);
1502 JSObject* func = static_cast<JSObject*>(funcVal);
1504 if (!func->implementsCall())
1505 return throwError(exec, TypeError, dotExprDoesNotAllowCallsString(), funcVal, m_base.get(), m_ident);
1508 m_args->evaluateList(exec, argList);
1509 KJS_CHECKEXCEPTIONVALUE
1511 JSObject* thisObj = baseObj;
1513 ASSERT(thisObj->isObject());
1514 ASSERT(!thisObj->isActivationObject());
1516 // No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
1517 return func->call(exec, thisObj, argList);
1520 JSValue* FunctionCallDotNode::evaluate(ExecState* exec)
1522 return inlineEvaluate(exec);
1525 double FunctionCallDotNode::evaluateToNumber(ExecState* exec)
1527 JSValue* v = inlineEvaluate(exec);
1528 KJS_CHECKEXCEPTIONNUMBER
1529 return v->toNumber(exec);
1532 bool FunctionCallDotNode::evaluateToBoolean(ExecState* exec)
1534 JSValue* v = inlineEvaluate(exec);
1535 KJS_CHECKEXCEPTIONBOOLEAN
1536 return v->toBoolean(exec);
1539 int32_t FunctionCallDotNode::evaluateToInt32(ExecState* exec)
1541 JSValue* v = inlineEvaluate(exec);
1542 KJS_CHECKEXCEPTIONNUMBER
1543 return v->toInt32(exec);
1546 uint32_t FunctionCallDotNode::evaluateToUInt32(ExecState* exec)
1548 JSValue* v = inlineEvaluate(exec);
1549 KJS_CHECKEXCEPTIONNUMBER
1550 return v->toUInt32(exec);
1555 // ------------------------------ PostfixResolveNode ----------------------------------
1558 void PostIncResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
1560 size_t index = symbolTable.get(m_ident.ustring().rep());
1561 if (index != missingSymbolMarker()) {
1562 if (isConstant(localStorage, index))
1563 new (this) PostIncConstNode(index);
1565 new (this) PostIncLocalVarNode(index);
1569 JSValue* PostIncResolveNode::evaluate(ExecState* exec)
1571 // Check for missed optimization opportunity.
1572 ASSERT(!canSkipLookup(exec, m_ident));
1574 const ScopeChain& chain = exec->scopeChain();
1575 ScopeChainIterator iter = chain.begin();
1576 ScopeChainIterator end = chain.end();
1578 // we must always have something in the scope chain
1579 ASSERT(iter != end);
1583 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
1584 // If m_ident is 'arguments', the base->getPropertySlot() may cause
1585 // base (which must be an ActivationImp in such this case) to be torn
1586 // off from the activation stack, in which case we need to get it again
1587 // from the ScopeChainIterator.
1589 JSObject* base = *iter;
1590 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
1591 base->put(exec, m_ident, jsNumber(exec, v->toNumber(exec) + 1));
1596 } while (iter != end);
1598 return throwUndefinedVariableError(exec, m_ident);
1601 void PostIncResolveNode::optimizeForUnnecessaryResult()
1603 new (this) PreIncResolveNode(PlacementNewAdopt);
1606 JSValue* PostIncLocalVarNode::evaluate(ExecState* exec)
1608 ASSERT(exec->variableObject() == exec->scopeChain().top());
1610 JSValue** slot = &exec->localStorage()[m_index].value;
1611 JSValue* v = (*slot)->toJSNumber(exec);
1612 *slot = jsNumber(exec, v->toNumber(exec) + 1);
1616 void PostIncLocalVarNode::optimizeForUnnecessaryResult()
1618 new (this) PreIncLocalVarNode(m_index);
1622 void PostDecResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
1624 size_t index = symbolTable.get(m_ident.ustring().rep());
1625 if (index != missingSymbolMarker()) {
1626 if (isConstant(localStorage, index))
1627 new (this) PostDecConstNode(index);
1629 new (this) PostDecLocalVarNode(index);
1633 JSValue* PostDecResolveNode::evaluate(ExecState* exec)
1635 // Check for missed optimization opportunity.
1636 ASSERT(!canSkipLookup(exec, m_ident));
1638 const ScopeChain& chain = exec->scopeChain();
1639 ScopeChainIterator iter = chain.begin();
1640 ScopeChainIterator end = chain.end();
1642 // we must always have something in the scope chain
1643 ASSERT(iter != end);
1647 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
1648 // See the comment in PostIncResolveNode::evaluate().
1650 JSObject* base = *iter;
1651 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
1652 base->put(exec, m_ident, jsNumber(exec, v->toNumber(exec) - 1));
1657 } while (iter != end);
1659 return throwUndefinedVariableError(exec, m_ident);
1662 void PostDecResolveNode::optimizeForUnnecessaryResult()
1664 new (this) PreDecResolveNode(PlacementNewAdopt);
1667 JSValue* PostDecLocalVarNode::evaluate(ExecState* exec)
1669 ASSERT(exec->variableObject() == exec->scopeChain().top());
1671 JSValue** slot = &exec->localStorage()[m_index].value;
1672 JSValue* v = (*slot)->toJSNumber(exec);
1673 *slot = jsNumber(exec, v->toNumber(exec) - 1);
1677 double PostDecLocalVarNode::inlineEvaluateToNumber(ExecState* exec)
1679 ASSERT(exec->variableObject() == exec->scopeChain().top());
1681 JSValue** slot = &exec->localStorage()[m_index].value;
1682 double n = (*slot)->toNumber(exec);
1683 *slot = jsNumber(exec, n - 1);
1687 double PostDecLocalVarNode::evaluateToNumber(ExecState* exec)
1689 return inlineEvaluateToNumber(exec);
1692 bool PostDecLocalVarNode::evaluateToBoolean(ExecState* exec)
1694 double result = inlineEvaluateToNumber(exec);
1695 return result > 0.0 || 0.0 > result; // NaN produces false as well
1698 int32_t PostDecLocalVarNode::evaluateToInt32(ExecState* exec)
1700 return JSValue::toInt32(inlineEvaluateToNumber(exec));
1703 uint32_t PostDecLocalVarNode::evaluateToUInt32(ExecState* exec)
1705 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
1708 void PostDecLocalVarNode::optimizeForUnnecessaryResult()
1710 new (this) PreDecLocalVarNode(m_index);
1713 // ------------------------------ PostfixBracketNode ----------------------------------
1715 void PostfixBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1717 nodeStack.append(m_subscript.get());
1718 nodeStack.append(m_base.get());
1721 JSValue* PostIncBracketNode::evaluate(ExecState* exec)
1723 JSValue* baseValue = m_base->evaluate(exec);
1724 KJS_CHECKEXCEPTIONVALUE
1725 JSValue* subscript = m_subscript->evaluate(exec);
1726 KJS_CHECKEXCEPTIONVALUE
1728 JSObject* base = baseValue->toObject(exec);
1730 uint32_t propertyIndex;
1731 if (subscript->getUInt32(propertyIndex)) {
1733 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1734 KJS_CHECKEXCEPTIONVALUE
1736 JSValue* v2 = v->toJSNumber(exec);
1737 base->put(exec, propertyIndex, jsNumber(exec, v2->toNumber(exec) + 1));
1742 Identifier propertyName(subscript->toString(exec));
1744 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1745 KJS_CHECKEXCEPTIONVALUE
1747 JSValue* v2 = v->toJSNumber(exec);
1748 base->put(exec, propertyName, jsNumber(exec, v2->toNumber(exec) + 1));
1752 JSValue* PostDecBracketNode::evaluate(ExecState* exec)
1754 JSValue* baseValue = m_base->evaluate(exec);
1755 KJS_CHECKEXCEPTIONVALUE
1756 JSValue* subscript = m_subscript->evaluate(exec);
1757 KJS_CHECKEXCEPTIONVALUE
1759 JSObject* base = baseValue->toObject(exec);
1761 uint32_t propertyIndex;
1762 if (subscript->getUInt32(propertyIndex)) {
1764 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1765 KJS_CHECKEXCEPTIONVALUE
1767 JSValue* v2 = v->toJSNumber(exec);
1768 base->put(exec, propertyIndex, jsNumber(exec, v2->toNumber(exec) - 1));
1772 Identifier propertyName(subscript->toString(exec));
1774 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1775 KJS_CHECKEXCEPTIONVALUE
1777 JSValue* v2 = v->toJSNumber(exec);
1778 base->put(exec, propertyName, jsNumber(exec, v2->toNumber(exec) - 1));
1782 // ------------------------------ PostfixDotNode ----------------------------------
1784 void PostfixDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1786 nodeStack.append(m_base.get());
1789 JSValue* PostIncDotNode::evaluate(ExecState* exec)
1791 JSValue* baseValue = m_base->evaluate(exec);
1792 KJS_CHECKEXCEPTIONVALUE
1793 JSObject* base = baseValue->toObject(exec);
1796 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1797 KJS_CHECKEXCEPTIONVALUE
1799 JSValue* v2 = v->toJSNumber(exec);
1800 base->put(exec, m_ident, jsNumber(exec, v2->toNumber(exec) + 1));
1804 JSValue* PostDecDotNode::evaluate(ExecState* exec)
1806 JSValue* baseValue = m_base->evaluate(exec);
1807 KJS_CHECKEXCEPTIONVALUE
1808 JSObject* base = baseValue->toObject(exec);
1811 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1812 KJS_CHECKEXCEPTIONVALUE
1814 JSValue* v2 = v->toJSNumber(exec);
1815 base->put(exec, m_ident, jsNumber(exec, v2->toNumber(exec) - 1));
1819 // ------------------------------ PostfixErrorNode -----------------------------------
1821 JSValue* PostfixErrorNode::evaluate(ExecState* exec)
1823 throwError(exec, ReferenceError, "Postfix %s operator applied to value that is not a reference.",
1824 m_operator == OpPlusPlus ? "++" : "--");
1825 handleException(exec);
1826 return jsUndefined();
1829 // ------------------------------ DeleteResolveNode -----------------------------------
1831 void DeleteResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
1833 size_t index = symbolTable.get(m_ident.ustring().rep());
1834 if (index != missingSymbolMarker())
1835 new (this) LocalVarDeleteNode();
1840 JSValue* DeleteResolveNode::evaluate(ExecState* exec)
1842 // Check for missed optimization opportunity.
1843 ASSERT(!canSkipLookup(exec, m_ident));
1845 const ScopeChain& chain = exec->scopeChain();
1846 ScopeChainIterator iter = chain.begin();
1847 ScopeChainIterator end = chain.end();
1849 // We must always have something in the scope chain
1850 ASSERT(iter != end);
1856 if (base->getPropertySlot(exec, m_ident, slot))
1857 return jsBoolean(base->deleteProperty(exec, m_ident));
1860 } while (iter != end);
1862 return jsBoolean(true);
1865 JSValue* LocalVarDeleteNode::evaluate(ExecState*)
1867 return jsBoolean(false);
1870 // ------------------------------ DeleteBracketNode -----------------------------------
1872 void DeleteBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1874 nodeStack.append(m_subscript.get());
1875 nodeStack.append(m_base.get());
1878 JSValue* DeleteBracketNode::evaluate(ExecState* exec)
1880 JSValue* baseValue = m_base->evaluate(exec);
1881 KJS_CHECKEXCEPTIONVALUE
1882 JSValue* subscript = m_subscript->evaluate(exec);
1883 KJS_CHECKEXCEPTIONVALUE
1885 JSObject* base = baseValue->toObject(exec);
1887 uint32_t propertyIndex;
1888 if (subscript->getUInt32(propertyIndex))
1889 return jsBoolean(base->deleteProperty(exec, propertyIndex));
1891 Identifier propertyName(subscript->toString(exec));
1892 return jsBoolean(base->deleteProperty(exec, propertyName));
1895 // ------------------------------ DeleteDotNode -----------------------------------
1897 void DeleteDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1899 nodeStack.append(m_base.get());
1902 JSValue* DeleteDotNode::evaluate(ExecState* exec)
1904 JSValue* baseValue = m_base->evaluate(exec);
1905 JSObject* base = baseValue->toObject(exec);
1906 KJS_CHECKEXCEPTIONVALUE
1908 return jsBoolean(base->deleteProperty(exec, m_ident));
1911 // ------------------------------ DeleteValueNode -----------------------------------
1913 void DeleteValueNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1915 nodeStack.append(m_expr.get());
1918 JSValue* DeleteValueNode::evaluate(ExecState* exec)
1920 m_expr->evaluate(exec);
1921 KJS_CHECKEXCEPTIONVALUE
1923 // delete on a non-location expression ignores the value and returns true
1924 return jsBoolean(true);
1927 // ------------------------------ VoidNode -------------------------------------
1929 void VoidNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1931 nodeStack.append(m_expr.get());
1935 JSValue* VoidNode::evaluate(ExecState* exec)
1937 m_expr->evaluate(exec);
1938 KJS_CHECKEXCEPTIONVALUE
1940 return jsUndefined();
1945 // ------------------------------ TypeOfValueNode -----------------------------------
1947 void TypeOfValueNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1949 nodeStack.append(m_expr.get());
1952 static JSValue* typeStringForValue(ExecState*, JSValue*) KJS_FAST_CALL;
1953 static JSValue* typeStringForValue(ExecState* exec, JSValue* v)
1955 switch (v->type()) {
1957 return jsString(exec, "undefined");
1959 return jsString(exec, "object");
1961 return jsString(exec, "boolean");
1963 return jsString(exec, "number");
1965 return jsString(exec, "string");
1967 if (v->isObject()) {
1968 // Return "undefined" for objects that should be treated
1969 // as null when doing comparisons.
1970 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
1971 return jsString(exec, "undefined");
1972 else if (static_cast<JSObject*>(v)->implementsCall())
1973 return jsString(exec, "function");
1976 return jsString(exec, "object");
1980 void TypeOfResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
1982 size_t index = symbolTable.get(m_ident.ustring().rep());
1983 if (index != missingSymbolMarker())
1984 new (this) LocalVarTypeOfNode(index);
1987 JSValue* LocalVarTypeOfNode::evaluate(ExecState* exec)
1989 ASSERT(exec->variableObject() == exec->scopeChain().top());
1991 return typeStringForValue(exec, exec->localStorage()[m_index].value);
1994 JSValue* TypeOfResolveNode::evaluate(ExecState* exec)
1996 const ScopeChain& chain = exec->scopeChain();
1997 ScopeChainIterator iter = chain.begin();
1998 ScopeChainIterator end = chain.end();
2000 // We must always have something in the scope chain
2001 ASSERT(iter != end);
2007 if (base->getPropertySlot(exec, m_ident, slot)) {
2008 JSValue* v = slot.getValue(exec, base, m_ident);
2009 return typeStringForValue(exec, v);
2013 } while (iter != end);
2015 return jsString(exec, "undefined");
2018 // ------------------------------ TypeOfValueNode -----------------------------------
2020 JSValue* TypeOfValueNode::evaluate(ExecState* exec)
2022 JSValue* v = m_expr->evaluate(exec);
2023 KJS_CHECKEXCEPTIONVALUE
2025 return typeStringForValue(exec, v);
2028 // ECMA 11.4.4 and 11.4.5
2030 // ------------------------------ PrefixResolveNode ----------------------------------
2032 void PreIncResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
2034 size_t index = symbolTable.get(m_ident.ustring().rep());
2035 if (index != missingSymbolMarker()) {
2036 if (isConstant(localStorage, index))
2037 new (this) PreIncConstNode(index);
2039 new (this) PreIncLocalVarNode(index);
2043 JSValue* PreIncLocalVarNode::evaluate(ExecState* exec)
2045 ASSERT(exec->variableObject() == exec->scopeChain().top());
2046 JSValue** slot = &exec->localStorage()[m_index].value;
2048 double n = (*slot)->toNumber(exec);
2049 JSValue* n2 = jsNumber(exec, n + 1);
2054 JSValue* PreIncResolveNode::evaluate(ExecState* exec)
2056 const ScopeChain& chain = exec->scopeChain();
2057 ScopeChainIterator iter = chain.begin();
2058 ScopeChainIterator end = chain.end();
2060 // we must always have something in the scope chain
2061 ASSERT(iter != end);
2065 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
2066 // See the comment in PostIncResolveNode::evaluate().
2068 JSObject* base = *iter;
2069 JSValue* v = slot.getValue(exec, base, m_ident);
2071 double n = v->toNumber(exec);
2072 JSValue* n2 = jsNumber(exec, n + 1);
2073 base->put(exec, m_ident, n2);
2079 } while (iter != end);
2081 return throwUndefinedVariableError(exec, m_ident);
2084 void PreDecResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
2086 size_t index = symbolTable.get(m_ident.ustring().rep());
2087 if (index != missingSymbolMarker()) {
2088 if (isConstant(localStorage, index))
2089 new (this) PreDecConstNode(index);
2091 new (this) PreDecLocalVarNode(index);
2095 JSValue* PreDecLocalVarNode::evaluate(ExecState* exec)
2097 ASSERT(exec->variableObject() == exec->scopeChain().top());
2098 JSValue** slot = &exec->localStorage()[m_index].value;
2100 double n = (*slot)->toNumber(exec);
2101 JSValue* n2 = jsNumber(exec, n - 1);
2106 JSValue* PreDecResolveNode::evaluate(ExecState* exec)
2108 const ScopeChain& chain = exec->scopeChain();
2109 ScopeChainIterator iter = chain.begin();
2110 ScopeChainIterator end = chain.end();
2112 // we must always have something in the scope chain
2113 ASSERT(iter != end);
2117 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
2118 // See the comment in PostIncResolveNode::evaluate().
2120 JSObject* base = *iter;
2121 JSValue* v = slot.getValue(exec, base, m_ident);
2123 double n = v->toNumber(exec);
2124 JSValue* n2 = jsNumber(exec, n - 1);
2125 base->put(exec, m_ident, n2);
2131 } while (iter != end);
2133 return throwUndefinedVariableError(exec, m_ident);
2136 // ------------------------------ PreIncConstNode ----------------------------------
2138 JSValue* PreIncConstNode::evaluate(ExecState* exec)
2140 ASSERT(exec->variableObject() == exec->scopeChain().top());
2141 return jsNumber(exec, exec->localStorage()[m_index].value->toNumber(exec) + 1);
2144 // ------------------------------ PreDecConstNode ----------------------------------
2146 JSValue* PreDecConstNode::evaluate(ExecState* exec)
2148 ASSERT(exec->variableObject() == exec->scopeChain().top());
2149 return jsNumber(exec, exec->localStorage()[m_index].value->toNumber(exec) - 1);
2152 // ------------------------------ PostIncConstNode ----------------------------------
2154 JSValue* PostIncConstNode::evaluate(ExecState* exec)
2156 ASSERT(exec->variableObject() == exec->scopeChain().top());
2157 return jsNumber(exec, exec->localStorage()[m_index].value->toNumber(exec));
2160 // ------------------------------ PostDecConstNode ----------------------------------
2162 JSValue* PostDecConstNode::evaluate(ExecState* exec)
2164 ASSERT(exec->variableObject() == exec->scopeChain().top());
2165 return jsNumber(exec, exec->localStorage()[m_index].value->toNumber(exec));
2168 // ------------------------------ PrefixBracketNode ----------------------------------
2170 void PrefixBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2172 nodeStack.append(m_subscript.get());
2173 nodeStack.append(m_base.get());
2176 JSValue* PreIncBracketNode::evaluate(ExecState* exec)
2178 JSValue* baseValue = m_base->evaluate(exec);
2179 KJS_CHECKEXCEPTIONVALUE
2180 JSValue* subscript = m_subscript->evaluate(exec);
2181 KJS_CHECKEXCEPTIONVALUE
2183 JSObject* base = baseValue->toObject(exec);
2185 uint32_t propertyIndex;
2186 if (subscript->getUInt32(propertyIndex)) {
2188 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2189 KJS_CHECKEXCEPTIONVALUE
2191 JSValue* n2 = jsNumber(exec, v->toNumber(exec) + 1);
2192 base->put(exec, propertyIndex, n2);
2197 Identifier propertyName(subscript->toString(exec));
2199 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2200 KJS_CHECKEXCEPTIONVALUE
2202 JSValue* n2 = jsNumber(exec, v->toNumber(exec) + 1);
2203 base->put(exec, propertyName, n2);
2208 JSValue* PreDecBracketNode::evaluate(ExecState* exec)
2210 JSValue* baseValue = m_base->evaluate(exec);
2211 KJS_CHECKEXCEPTIONVALUE
2212 JSValue* subscript = m_subscript->evaluate(exec);
2213 KJS_CHECKEXCEPTIONVALUE
2215 JSObject* base = baseValue->toObject(exec);
2217 uint32_t propertyIndex;
2218 if (subscript->getUInt32(propertyIndex)) {
2220 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2221 KJS_CHECKEXCEPTIONVALUE
2223 JSValue* n2 = jsNumber(exec, v->toNumber(exec) - 1);
2224 base->put(exec, propertyIndex, n2);
2229 Identifier propertyName(subscript->toString(exec));
2231 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2232 KJS_CHECKEXCEPTIONVALUE
2234 JSValue* n2 = jsNumber(exec, v->toNumber(exec) - 1);
2235 base->put(exec, propertyName, n2);
2240 // ------------------------------ PrefixDotNode ----------------------------------
2242 void PrefixDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2244 nodeStack.append(m_base.get());
2247 JSValue* PreIncDotNode::evaluate(ExecState* exec)
2249 JSValue* baseValue = m_base->evaluate(exec);
2250 KJS_CHECKEXCEPTIONVALUE
2251 JSObject* base = baseValue->toObject(exec);
2254 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2255 KJS_CHECKEXCEPTIONVALUE
2257 double n = v->toNumber(exec);
2258 JSValue* n2 = jsNumber(exec, n + 1);
2259 base->put(exec, m_ident, n2);
2264 JSValue* PreDecDotNode::evaluate(ExecState* exec)
2266 JSValue* baseValue = m_base->evaluate(exec);
2267 KJS_CHECKEXCEPTIONVALUE
2268 JSObject* base = baseValue->toObject(exec);
2271 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2272 KJS_CHECKEXCEPTIONVALUE
2274 double n = v->toNumber(exec);
2275 JSValue* n2 = jsNumber(exec, n - 1);
2276 base->put(exec, m_ident, n2);
2281 // ------------------------------ PrefixErrorNode -----------------------------------
2283 JSValue* PrefixErrorNode::evaluate(ExecState* exec)
2285 throwError(exec, ReferenceError, "Prefix %s operator applied to value that is not a reference.",
2286 m_operator == OpPlusPlus ? "++" : "--");
2287 handleException(exec);
2288 return jsUndefined();
2291 // ------------------------------ UnaryPlusNode --------------------------------
2293 void UnaryPlusNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2295 nodeStack.append(m_expr.get());
2299 JSValue* UnaryPlusNode::evaluate(ExecState* exec)
2301 JSValue* v = m_expr->evaluate(exec);
2302 KJS_CHECKEXCEPTIONVALUE
2303 return v->toJSNumber(exec);
2306 bool UnaryPlusNode::evaluateToBoolean(ExecState* exec)
2308 return m_expr->evaluateToBoolean(exec);
2311 double UnaryPlusNode::evaluateToNumber(ExecState* exec)
2313 return m_expr->evaluateToNumber(exec);
2316 int32_t UnaryPlusNode::evaluateToInt32(ExecState* exec)
2318 return m_expr->evaluateToInt32(exec);
2321 uint32_t UnaryPlusNode::evaluateToUInt32(ExecState* exec)
2323 return m_expr->evaluateToInt32(exec);
2326 // ------------------------------ NegateNode -----------------------------------
2328 void NegateNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2330 nodeStack.append(m_expr.get());
2334 JSValue* NegateNode::evaluate(ExecState* exec)
2336 // No need to check exception, caller will do so right after evaluate()
2337 return jsNumber(exec, -m_expr->evaluateToNumber(exec));
2340 double NegateNode::evaluateToNumber(ExecState* exec)
2342 // No need to check exception, caller will do so right after evaluateToNumber()
2343 return -m_expr->evaluateToNumber(exec);
2346 // ------------------------------ BitwiseNotNode -------------------------------
2348 void BitwiseNotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2350 nodeStack.append(m_expr.get());
2354 int32_t BitwiseNotNode::inlineEvaluateToInt32(ExecState* exec)
2356 return ~m_expr->evaluateToInt32(exec);
2359 JSValue* BitwiseNotNode::evaluate(ExecState* exec)
2361 return jsNumber(exec, inlineEvaluateToInt32(exec));
2364 double BitwiseNotNode::evaluateToNumber(ExecState* exec)
2366 return inlineEvaluateToInt32(exec);
2369 bool BitwiseNotNode::evaluateToBoolean(ExecState* exec)
2371 return inlineEvaluateToInt32(exec);
2374 int32_t BitwiseNotNode::evaluateToInt32(ExecState* exec)
2376 return inlineEvaluateToInt32(exec);
2379 uint32_t BitwiseNotNode::evaluateToUInt32(ExecState* exec)
2381 return inlineEvaluateToInt32(exec);
2384 // ------------------------------ LogicalNotNode -------------------------------
2386 void LogicalNotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2388 nodeStack.append(m_expr.get());
2392 JSValue* LogicalNotNode::evaluate(ExecState* exec)
2394 return jsBoolean(!m_expr->evaluateToBoolean(exec));
2397 bool LogicalNotNode::evaluateToBoolean(ExecState* exec)
2399 return !m_expr->evaluateToBoolean(exec);
2402 // ------------------------------ Multiplicative Nodes -----------------------------------
2404 void MultNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2406 nodeStack.append(m_term1.get());
2407 nodeStack.append(m_term2.get());
2411 double MultNode::inlineEvaluateToNumber(ExecState* exec)
2413 double n1 = m_term1->evaluateToNumber(exec);
2414 KJS_CHECKEXCEPTIONNUMBER
2415 double n2 = m_term2->evaluateToNumber(exec);
2419 JSValue* MultNode::evaluate(ExecState* exec)
2421 return jsNumber(exec, inlineEvaluateToNumber(exec));
2424 double MultNode::evaluateToNumber(ExecState* exec)
2426 return inlineEvaluateToNumber(exec);
2429 bool MultNode::evaluateToBoolean(ExecState* exec)
2431 double result = inlineEvaluateToNumber(exec);
2432 return result > 0.0 || 0.0 > result; // NaN produces false as well
2435 int32_t MultNode::evaluateToInt32(ExecState* exec)
2437 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2440 uint32_t MultNode::evaluateToUInt32(ExecState* exec)
2442 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2445 void DivNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2447 nodeStack.append(m_term1.get());
2448 nodeStack.append(m_term2.get());
2452 double DivNode::inlineEvaluateToNumber(ExecState* exec)
2454 double n1 = m_term1->evaluateToNumber(exec);
2455 KJS_CHECKEXCEPTIONNUMBER
2456 double n2 = m_term2->evaluateToNumber(exec);
2460 JSValue* DivNode::evaluate(ExecState* exec)
2462 return jsNumber(exec, inlineEvaluateToNumber(exec));
2465 double DivNode::evaluateToNumber(ExecState* exec)
2467 return inlineEvaluateToNumber(exec);
2470 int32_t DivNode::evaluateToInt32(ExecState* exec)
2472 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2475 uint32_t DivNode::evaluateToUInt32(ExecState* exec)
2477 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2480 void ModNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2482 nodeStack.append(m_term1.get());
2483 nodeStack.append(m_term2.get());
2487 double ModNode::inlineEvaluateToNumber(ExecState* exec)
2489 double n1 = m_term1->evaluateToNumber(exec);
2490 KJS_CHECKEXCEPTIONNUMBER
2491 double n2 = m_term2->evaluateToNumber(exec);
2492 return fmod(n1, n2);
2495 JSValue* ModNode::evaluate(ExecState* exec)
2497 return jsNumber(exec, inlineEvaluateToNumber(exec));
2500 double ModNode::evaluateToNumber(ExecState* exec)
2502 return inlineEvaluateToNumber(exec);
2505 bool ModNode::evaluateToBoolean(ExecState* exec)
2507 double result = inlineEvaluateToNumber(exec);
2508 return result > 0.0 || 0.0 > result; // NaN produces false as well
2511 int32_t ModNode::evaluateToInt32(ExecState* exec)
2513 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2516 uint32_t ModNode::evaluateToUInt32(ExecState* exec)
2518 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2521 // ------------------------------ Additive Nodes --------------------------------------
2523 static JSValue* throwOutOfMemoryError(ExecState* exec)
2525 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
2526 exec->setException(error);
2530 static double throwOutOfMemoryErrorToNumber(ExecState* exec)
2532 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
2533 exec->setException(error);
2538 static JSValue* addSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
2540 // exception for the Date exception in defaultValue()
2541 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
2542 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
2544 if (p1->isString() || p2->isString()) {
2545 UString value = p1->toString(exec) + p2->toString(exec);
2547 return throwOutOfMemoryError(exec);
2548 return jsString(exec, value);
2551 return jsNumber(exec, p1->toNumber(exec) + p2->toNumber(exec));
2554 static double addSlowCaseToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
2556 // exception for the Date exception in defaultValue()
2557 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
2558 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
2560 if (p1->isString() || p2->isString()) {
2561 UString value = p1->toString(exec) + p2->toString(exec);
2563 return throwOutOfMemoryErrorToNumber(exec);
2564 return value.toDouble();
2567 return p1->toNumber(exec) + p2->toNumber(exec);
2570 // Fast-path choices here are based on frequency data from SunSpider:
2571 // <times> Add case: <t1> <t2>
2572 // ---------------------------
2573 // 5627160 Add case: 1 1
2574 // 247427 Add case: 5 5
2575 // 20901 Add case: 5 6
2576 // 13978 Add case: 5 1
2577 // 4000 Add case: 1 5
2580 static inline JSValue* add(ExecState* exec, JSValue* v1, JSValue* v2)
2582 JSType t1 = v1->type();
2583 JSType t2 = v2->type();
2584 const unsigned bothTypes = (t1 << 3) | t2;
2586 if (bothTypes == ((NumberType << 3) | NumberType))
2587 return jsNumber(exec, v1->toNumber(exec) + v2->toNumber(exec));
2588 if (bothTypes == ((StringType << 3) | StringType)) {
2589 UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
2591 return throwOutOfMemoryError(exec);
2592 return jsString(exec, value);
2595 // All other cases are pretty uncommon
2596 return addSlowCase(exec, v1, v2);
2599 static inline double addToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
2601 JSType t1 = v1->type();
2602 JSType t2 = v2->type();
2603 const unsigned bothTypes = (t1 << 3) | t2;
2605 if (bothTypes == ((NumberType << 3) | NumberType))
2606 return v1->toNumber(exec) + v2->toNumber(exec);
2607 if (bothTypes == ((StringType << 3) | StringType)) {
2608 UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
2610 return throwOutOfMemoryErrorToNumber(exec);
2611 return value.toDouble();
2614 // All other cases are pretty uncommon
2615 return addSlowCaseToNumber(exec, v1, v2);
2618 void AddNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2620 nodeStack.append(m_term1.get());
2621 nodeStack.append(m_term2.get());
2625 JSValue* AddNode::evaluate(ExecState* exec)
2627 JSValue* v1 = m_term1->evaluate(exec);
2628 KJS_CHECKEXCEPTIONVALUE
2630 JSValue* v2 = m_term2->evaluate(exec);
2631 KJS_CHECKEXCEPTIONVALUE
2633 return add(exec, v1, v2);
2636 double AddNode::inlineEvaluateToNumber(ExecState* exec)
2638 JSValue* v1 = m_term1->evaluate(exec);
2639 KJS_CHECKEXCEPTIONNUMBER
2641 JSValue* v2 = m_term2->evaluate(exec);
2642 KJS_CHECKEXCEPTIONNUMBER
2644 return addToNumber(exec, v1, v2);
2647 double AddNode::evaluateToNumber(ExecState* exec)
2649 return inlineEvaluateToNumber(exec);
2652 int32_t AddNode::evaluateToInt32(ExecState* exec)
2654 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2657 uint32_t AddNode::evaluateToUInt32(ExecState* exec)
2659 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2662 double AddNumbersNode::inlineEvaluateToNumber(ExecState* exec)
2664 double n1 = m_term1->evaluateToNumber(exec);
2665 KJS_CHECKEXCEPTIONNUMBER
2666 double n2 = m_term2->evaluateToNumber(exec);
2670 JSValue* AddNumbersNode::evaluate(ExecState* exec)
2672 return jsNumber(exec, inlineEvaluateToNumber(exec));
2675 double AddNumbersNode::evaluateToNumber(ExecState* exec)
2677 return inlineEvaluateToNumber(exec);
2680 int32_t AddNumbersNode::evaluateToInt32(ExecState* exec)
2682 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2685 uint32_t AddNumbersNode::evaluateToUInt32(ExecState* exec)
2687 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2690 JSValue* AddStringsNode::evaluate(ExecState* exec)
2692 JSValue* v1 = m_term1->evaluate(exec);
2693 KJS_CHECKEXCEPTIONVALUE
2695 JSValue* v2 = m_term2->evaluate(exec);
2696 KJS_CHECKEXCEPTIONVALUE
2698 return jsString(exec, static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value());
2701 JSValue* AddStringLeftNode::evaluate(ExecState* exec)
2703 JSValue* v1 = m_term1->evaluate(exec);
2704 KJS_CHECKEXCEPTIONVALUE
2706 JSValue* v2 = m_term2->evaluate(exec);
2707 KJS_CHECKEXCEPTIONVALUE
2709 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
2710 return jsString(exec, static_cast<StringImp*>(v1)->value() + p2->toString(exec));
2713 JSValue* AddStringRightNode::evaluate(ExecState* exec)
2715 JSValue* v1 = m_term1->evaluate(exec);
2716 KJS_CHECKEXCEPTIONVALUE
2718 JSValue* v2 = m_term2->evaluate(exec);
2719 KJS_CHECKEXCEPTIONVALUE
2721 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
2722 return jsString(exec, p1->toString(exec) + static_cast<StringImp*>(v2)->value());
2725 void SubNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2727 nodeStack.append(m_term1.get());
2728 nodeStack.append(m_term2.get());
2732 double SubNode::inlineEvaluateToNumber(ExecState* exec)
2734 double n1 = m_term1->evaluateToNumber(exec);
2735 KJS_CHECKEXCEPTIONNUMBER
2736 double n2 = m_term2->evaluateToNumber(exec);
2740 JSValue* SubNode::evaluate(ExecState* exec)
2742 return jsNumber(exec, inlineEvaluateToNumber(exec));
2745 double SubNode::evaluateToNumber(ExecState* exec)
2747 return inlineEvaluateToNumber(exec);
2750 int32_t SubNode::evaluateToInt32(ExecState* exec)
2752 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2755 uint32_t SubNode::evaluateToUInt32(ExecState* exec)
2757 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2760 // ------------------------------ Shift Nodes ------------------------------------
2762 void LeftShiftNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2764 nodeStack.append(m_term1.get());
2765 nodeStack.append(m_term2.get());
2769 int32_t LeftShiftNode::inlineEvaluateToInt32(ExecState* exec)
2771 int i1 = m_term1->evaluateToInt32(exec);
2772 KJS_CHECKEXCEPTIONNUMBER
2773 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
2777 JSValue* LeftShiftNode::evaluate(ExecState* exec)
2779 return jsNumber(exec, inlineEvaluateToInt32(exec));
2782 double LeftShiftNode::evaluateToNumber(ExecState* exec)
2784 return inlineEvaluateToInt32(exec);
2787 int32_t LeftShiftNode::evaluateToInt32(ExecState* exec)
2789 return inlineEvaluateToInt32(exec);
2792 uint32_t LeftShiftNode::evaluateToUInt32(ExecState* exec)
2794 return inlineEvaluateToInt32(exec);
2797 void RightShiftNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2799 nodeStack.append(m_term1.get());
2800 nodeStack.append(m_term2.get());
2804 int32_t RightShiftNode::inlineEvaluateToInt32(ExecState* exec)
2806 int i1 = m_term1->evaluateToInt32(exec);
2807 KJS_CHECKEXCEPTIONNUMBER
2808 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
2812 JSValue* RightShiftNode::evaluate(ExecState* exec)
2814 return jsNumber(exec, inlineEvaluateToInt32(exec));
2817 double RightShiftNode::evaluateToNumber(ExecState* exec)
2819 return inlineEvaluateToInt32(exec);
2822 int32_t RightShiftNode::evaluateToInt32(ExecState* exec)
2824 return inlineEvaluateToInt32(exec);
2827 uint32_t RightShiftNode::evaluateToUInt32(ExecState* exec)
2829 return inlineEvaluateToInt32(exec);
2832 void UnsignedRightShiftNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2834 nodeStack.append(m_term1.get());
2835 nodeStack.append(m_term2.get());
2839 uint32_t UnsignedRightShiftNode::inlineEvaluateToUInt32(ExecState* exec)
2841 unsigned int i1 = m_term1->evaluateToUInt32(exec);
2842 KJS_CHECKEXCEPTIONNUMBER
2843 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
2847 JSValue* UnsignedRightShiftNode::evaluate(ExecState* exec)
2849 return jsNumber(exec, inlineEvaluateToUInt32(exec));
2852 double UnsignedRightShiftNode::evaluateToNumber(ExecState* exec)
2854 return inlineEvaluateToUInt32(exec);
2857 int32_t UnsignedRightShiftNode::evaluateToInt32(ExecState* exec)
2859 return inlineEvaluateToUInt32(exec);
2862 uint32_t UnsignedRightShiftNode::evaluateToUInt32(ExecState* exec)
2864 return inlineEvaluateToUInt32(exec);
2867 // ------------------------------ Relational Nodes -------------------------------
2869 static inline bool lessThan(ExecState* exec, JSValue* v1, JSValue* v2)
2875 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
2876 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
2878 if (wasNotString1 | wasNotString2)
2881 return static_cast<const StringImp*>(p1)->value() < static_cast<const StringImp*>(p2)->value();
2884 static inline bool lessThanEq(ExecState* exec, JSValue* v1, JSValue* v2)
2890 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
2891 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
2893 if (wasNotString1 | wasNotString2)
2896 return !(static_cast<const StringImp*>(p2)->value() < static_cast<const StringImp*>(p1)->value());
2899 void LessNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2901 nodeStack.append(m_expr2.get());
2902 nodeStack.append(m_expr1.get());
2906 bool LessNode::inlineEvaluateToBoolean(ExecState* exec)
2908 JSValue* v1 = m_expr1->evaluate(exec);
2909 KJS_CHECKEXCEPTIONBOOLEAN
2910 JSValue* v2 = m_expr2->evaluate(exec);
2911 KJS_CHECKEXCEPTIONBOOLEAN
2912 return lessThan(exec, v1, v2);
2915 JSValue* LessNode::evaluate(ExecState* exec)
2917 return jsBoolean(inlineEvaluateToBoolean(exec));
2920 bool LessNode::evaluateToBoolean(ExecState* exec)
2922 return inlineEvaluateToBoolean(exec);
2925 bool LessNumbersNode::inlineEvaluateToBoolean(ExecState* exec)
2927 double n1 = m_expr1->evaluateToNumber(exec);
2928 KJS_CHECKEXCEPTIONVALUE
2929 double n2 = m_expr2->evaluateToNumber(exec);
2933 JSValue* LessNumbersNode::evaluate(ExecState* exec)
2935 return jsBoolean(inlineEvaluateToBoolean(exec));
2938 bool LessNumbersNode::evaluateToBoolean(ExecState* exec)
2940 return inlineEvaluateToBoolean(exec);
2943 bool LessStringsNode::inlineEvaluateToBoolean(ExecState* exec)
2945 JSValue* v1 = m_expr1->evaluate(exec);
2946 KJS_CHECKEXCEPTIONVALUE
2947 JSValue* v2 = m_expr2->evaluate(exec);
2948 return static_cast<StringImp*>(v1)->value() < static_cast<StringImp*>(v2)->value();
2951 JSValue* LessStringsNode::evaluate(ExecState* exec)
2953 return jsBoolean(inlineEvaluateToBoolean(exec));
2956 bool LessStringsNode::evaluateToBoolean(ExecState* exec)
2958 return inlineEvaluateToBoolean(exec);
2961 void GreaterNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2963 nodeStack.append(m_expr2.get());
2964 nodeStack.append(m_expr1.get());
2968 bool GreaterNode::inlineEvaluateToBoolean(ExecState* exec)
2970 JSValue* v1 = m_expr1->evaluate(exec);
2971 KJS_CHECKEXCEPTIONBOOLEAN
2972 JSValue* v2 = m_expr2->evaluate(exec);
2973 KJS_CHECKEXCEPTIONBOOLEAN
2974 return lessThan(exec, v2, v1);
2977 JSValue* GreaterNode::evaluate(ExecState* exec)
2979 return jsBoolean(inlineEvaluateToBoolean(exec));
2982 bool GreaterNode::evaluateToBoolean(ExecState* exec)
2984 return inlineEvaluateToBoolean(exec);
2987 void LessEqNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2989 nodeStack.append(m_expr2.get());
2990 nodeStack.append(m_expr1.get());
2994 bool LessEqNode::inlineEvaluateToBoolean(ExecState* exec)
2996 JSValue* v1 = m_expr1->evaluate(exec);
2997 KJS_CHECKEXCEPTIONBOOLEAN
2998 JSValue* v2 = m_expr2->evaluate(exec);
2999 KJS_CHECKEXCEPTIONBOOLEAN
3000 return lessThanEq(exec, v1, v2);
3003 JSValue* LessEqNode::evaluate(ExecState* exec)
3005 return jsBoolean(inlineEvaluateToBoolean(exec));
3008 bool LessEqNode::evaluateToBoolean(ExecState* exec)
3010 return inlineEvaluateToBoolean(exec);
3013 void GreaterEqNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3015 nodeStack.append(m_expr2.get());
3016 nodeStack.append(m_expr1.get());
3020 bool GreaterEqNode::inlineEvaluateToBoolean(ExecState* exec)
3022 JSValue* v1 = m_expr1->evaluate(exec);
3023 KJS_CHECKEXCEPTIONBOOLEAN
3024 JSValue* v2 = m_expr2->evaluate(exec);
3025 KJS_CHECKEXCEPTIONBOOLEAN
3026 return lessThanEq(exec, v2, v1);
3029 JSValue* GreaterEqNode::evaluate(ExecState* exec)
3031 return jsBoolean(inlineEvaluateToBoolean(exec));
3034 bool GreaterEqNode::evaluateToBoolean(ExecState* exec)
3036 return inlineEvaluateToBoolean(exec);
3039 void InstanceOfNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3041 nodeStack.append(m_expr2.get());
3042 nodeStack.append(m_expr1.get());
3046 JSValue* InstanceOfNode::evaluate(ExecState* exec)
3048 JSValue* v1 = m_expr1->evaluate(exec);
3049 KJS_CHECKEXCEPTIONVALUE
3050 JSValue* v2 = m_expr2->evaluate(exec);
3051 KJS_CHECKEXCEPTIONVALUE
3053 if (!v2->isObject())
3054 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, m_expr2.get());
3056 JSObject* o2 = static_cast<JSObject*>(v2);
3058 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
3059 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
3060 // property. It seems that all objects have the property, but not all implement it, so in this
3061 // case we return false (consistent with Mozilla).
3062 if (!o2->implementsHasInstance())
3063 return jsBoolean(false);
3065 return jsBoolean(o2->hasInstance(exec, v1));
3068 bool InstanceOfNode::evaluateToBoolean(ExecState* exec)
3070 JSValue* v1 = m_expr1->evaluate(exec);
3071 KJS_CHECKEXCEPTIONBOOLEAN
3072 JSValue* v2 = m_expr2->evaluate(exec);
3073 KJS_CHECKEXCEPTIONBOOLEAN
3075 if (!v2->isObject()) {
3076 throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'instanceof' operator.", v2, m_expr2.get());
3080 JSObject* o2 = static_cast<JSObject*>(v2);
3082 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
3083 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
3084 // property. It seems that all objects have the property, but not all implement it, so in this
3085 // case we return false (consistent with Mozilla).
3086 if (!o2->implementsHasInstance())
3089 return o2->hasInstance(exec, v1);
3092 void InNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3094 nodeStack.append(m_expr2.get());
3095 nodeStack.append(m_expr1.get());
3099 JSValue* InNode::evaluate(ExecState* exec)
3101 JSValue* v1 = m_expr1->evaluate(exec);
3102 KJS_CHECKEXCEPTIONVALUE
3103 JSValue* v2 = m_expr2->evaluate(exec);
3104 KJS_CHECKEXCEPTIONVALUE
3106 if (!v2->isObject())
3107 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
3109 return jsBoolean(static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec))));
3112 bool InNode::evaluateToBoolean(ExecState* exec)
3114 JSValue* v1 = m_expr1->evaluate(exec);
3115 KJS_CHECKEXCEPTIONBOOLEAN
3116 JSValue* v2 = m_expr2->evaluate(exec);
3117 KJS_CHECKEXCEPTIONBOOLEAN
3119 if (!v2->isObject()) {
3120 throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
3124 return static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec)));
3127 // ------------------------------ Equality Nodes ------------------------------------
3129 void EqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3131 nodeStack.append(m_expr2.get());
3132 nodeStack.append(m_expr1.get());
3136 bool EqualNode::inlineEvaluateToBoolean(ExecState* exec)
3138 JSValue* v1 = m_expr1->evaluate(exec);
3139 KJS_CHECKEXCEPTIONBOOLEAN
3140 JSValue* v2 = m_expr2->evaluate(exec);
3141 KJS_CHECKEXCEPTIONBOOLEAN
3143 return equal(exec, v1, v2);
3146 JSValue* EqualNode::evaluate(ExecState* exec)
3148 return jsBoolean(inlineEvaluateToBoolean(exec));
3151 bool EqualNode::evaluateToBoolean(ExecState* exec)
3153 return inlineEvaluateToBoolean(exec);
3156 void NotEqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3158 nodeStack.append(m_expr2.get());
3159 nodeStack.append(m_expr1.get());
3163 bool NotEqualNode::inlineEvaluateToBoolean(ExecState* exec)
3165 JSValue* v1 = m_expr1->evaluate(exec);
3166 KJS_CHECKEXCEPTIONBOOLEAN
3167 JSValue* v2 = m_expr2->evaluate(exec);
3168 KJS_CHECKEXCEPTIONBOOLEAN
3170 return !equal(exec,v1, v2);
3173 JSValue* NotEqualNode::evaluate(ExecState* exec)
3175 return jsBoolean(inlineEvaluateToBoolean(exec));
3178 bool NotEqualNode::evaluateToBoolean(ExecState* exec)
3180 return inlineEvaluateToBoolean(exec);
3183 void StrictEqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3185 nodeStack.append(m_expr2.get());
3186 nodeStack.append(m_expr1.get());
3190 bool StrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
3192 JSValue* v1 = m_expr1->evaluate(exec);
3193 KJS_CHECKEXCEPTIONBOOLEAN
3194 JSValue* v2 = m_expr2->evaluate(exec);
3195 KJS_CHECKEXCEPTIONBOOLEAN
3197 return strictEqual(exec,v1, v2);
3200 JSValue* StrictEqualNode::evaluate(ExecState* exec)
3202 return jsBoolean(inlineEvaluateToBoolean(exec));
3205 bool StrictEqualNode::evaluateToBoolean(ExecState* exec)
3207 return inlineEvaluateToBoolean(exec);
3210 void NotStrictEqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3212 nodeStack.append(m_expr2.get());
3213 nodeStack.append(m_expr1.get());
3217 bool NotStrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
3219 JSValue* v1 = m_expr1->evaluate(exec);
3220 KJS_CHECKEXCEPTIONBOOLEAN
3221 JSValue* v2 = m_expr2->evaluate(exec);
3222 KJS_CHECKEXCEPTIONBOOLEAN
3224 return !strictEqual(exec,v1, v2);
3227 JSValue* NotStrictEqualNode::evaluate(ExecState* exec)
3229 return jsBoolean(inlineEvaluateToBoolean(exec));
3232 bool NotStrictEqualNode::evaluateToBoolean(ExecState* exec)
3234 return inlineEvaluateToBoolean(exec);
3237 // ------------------------------ Bit Operation Nodes ----------------------------------
3239 void BitAndNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3241 nodeStack.append(m_expr2.get());
3242 nodeStack.append(m_expr1.get());
3246 JSValue* BitAndNode::evaluate(ExecState* exec)
3248 JSValue* v1 = m_expr1->evaluate(exec);
3249 KJS_CHECKEXCEPTIONVALUE
3250 JSValue* v2 = m_expr2->evaluate(exec);
3251 KJS_CHECKEXCEPTIONVALUE
3253 return jsNumberFromAnd(exec, v1, v2);
3256 int32_t BitAndNode::inlineEvaluateToInt32(ExecState* exec)
3258 int32_t i1 = m_expr1->evaluateToInt32(exec);
3259 KJS_CHECKEXCEPTIONNUMBER
3260 int32_t i2 = m_expr2->evaluateToInt32(exec);
3264 double BitAndNode::evaluateToNumber(ExecState* exec)
3266 return inlineEvaluateToInt32(exec);
3269 bool BitAndNode::evaluateToBoolean(ExecState* exec)
3271 return inlineEvaluateToInt32(exec);
3274 int32_t BitAndNode::evaluateToInt32(ExecState* exec)
3276 return inlineEvaluateToInt32(exec);
3279 uint32_t BitAndNode::evaluateToUInt32(ExecState* exec)
3281 return inlineEvaluateToInt32(exec);
3284 void BitXOrNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3286 nodeStack.append(m_expr2.get());
3287 nodeStack.append(m_expr1.get());
3290 int32_t BitXOrNode::inlineEvaluateToInt32(ExecState* exec)
3292 int i1 = m_expr1->evaluateToInt32(exec);
3293 KJS_CHECKEXCEPTIONNUMBER
3294 int i2 = m_expr2->evaluateToInt32(exec);
3298 JSValue* BitXOrNode::evaluate(ExecState* exec)
3300 return jsNumber(exec, inlineEvaluateToInt32(exec));
3303 double BitXOrNode::evaluateToNumber(ExecState* exec)
3305 return inlineEvaluateToInt32(exec);
3308 bool BitXOrNode::evaluateToBoolean(ExecState* exec)
3310 return inlineEvaluateToInt32(exec);
3313 int32_t BitXOrNode::evaluateToInt32(ExecState* exec)
3315 return inlineEvaluateToInt32(exec);
3318 uint32_t BitXOrNode::evaluateToUInt32(ExecState* exec)
3320 return inlineEvaluateToInt32(exec);
3323 void BitOrNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3325 nodeStack.append(m_expr2.get());
3326 nodeStack.append(m_expr1.get());
3329 int32_t BitOrNode::inlineEvaluateToInt32(ExecState* exec)
3331 int i1 = m_expr1->evaluateToInt32(exec);
3332 KJS_CHECKEXCEPTIONNUMBER
3333 int i2 = m_expr2->evaluateToInt32(exec);
3337 JSValue* BitOrNode::evaluate(ExecState* exec)
3339 return jsNumber(exec, inlineEvaluateToInt32(exec));
3342 double BitOrNode::evaluateToNumber(ExecState* exec)
3344 return inlineEvaluateToInt32(exec);
3347 bool BitOrNode::evaluateToBoolean(ExecState* exec)
3349 return inlineEvaluateToInt32(exec);
3352 int32_t BitOrNode::evaluateToInt32(ExecState* exec)
3354 return inlineEvaluateToInt32(exec);
3357 uint32_t BitOrNode::evaluateToUInt32(ExecState* exec)
3359 return inlineEvaluateToInt32(exec);
3362 // ------------------------------ Binary Logical Nodes ----------------------------
3364 void LogicalAndNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3366 nodeStack.append(m_expr2.get());
3367 nodeStack.append(m_expr1.get());
3371 JSValue* LogicalAndNode::evaluate(ExecState* exec)
3373 JSValue* v1 = m_expr1->evaluate(exec);
3374 KJS_CHECKEXCEPTIONVALUE
3375 bool b1 = v1->toBoolean(exec);
3376 KJS_CHECKEXCEPTIONVALUE
3379 JSValue* v2 = m_expr2->evaluate(exec);
3380 KJS_CHECKEXCEPTIONVALUE
3384 bool LogicalAndNode::evaluateToBoolean(ExecState* exec)
3386 bool b = m_expr1->evaluateToBoolean(exec);
3387 KJS_CHECKEXCEPTIONBOOLEAN
3388 return b && m_expr2->evaluateToBoolean(exec);
3391 void LogicalOrNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3393 nodeStack.append(m_expr2.get());
3394 nodeStack.append(m_expr1.get());
3397 JSValue* LogicalOrNode::evaluate(ExecState* exec)
3399 JSValue* v1 = m_expr1->evaluate(exec);
3400 KJS_CHECKEXCEPTIONVALUE
3401 if (v1->toBoolean(exec))
3403 return m_expr2->evaluate(exec);
3406 bool LogicalOrNode::evaluateToBoolean(ExecState* exec)
3408 bool b = m_expr1->evaluateToBoolean(exec);
3409 KJS_CHECKEXCEPTIONBOOLEAN
3410 return b || m_expr2->evaluateToBoolean(exec);
3413 // ------------------------------ ConditionalNode ------------------------------
3415 void ConditionalNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3417 nodeStack.append(m_expr2.get());
3418 nodeStack.append(m_expr1.get());
3419 nodeStack.append(m_logical.get());
3423 JSValue* ConditionalNode::evaluate(ExecState* exec)
3425 bool b = m_logical->evaluateToBoolean(exec);
3426 KJS_CHECKEXCEPTIONVALUE
3427 return b ? m_expr1->evaluate(exec) : m_expr2->evaluate(exec);
3430 bool ConditionalNode::evaluateToBoolean(ExecState* exec)
3432 bool b = m_logical->evaluateToBoolean(exec);
3433 KJS_CHECKEXCEPTIONBOOLEAN
3434 return b ? m_expr1->evaluateToBoolean(exec) : m_expr2->evaluateToBoolean(exec);
3437 double ConditionalNode::evaluateToNumber(ExecState* exec)
3439 bool b = m_logical->evaluateToBoolean(exec);
3440 KJS_CHECKEXCEPTIONNUMBER
3441 return b ? m_expr1->evaluateToNumber(exec) : m_expr2->evaluateToNumber(exec);
3444 int32_t ConditionalNode::evaluateToInt32(ExecState* exec)
3446 bool b = m_logical->evaluateToBoolean(exec);
3447 KJS_CHECKEXCEPTIONNUMBER
3448 return b ? m_expr1->evaluateToInt32(exec) : m_expr2->evaluateToInt32(exec);
3451 uint32_t ConditionalNode::evaluateToUInt32(ExecState* exec)
3453 bool b = m_logical->evaluateToBoolean(exec);
3454 KJS_CHECKEXCEPTIONNUMBER
3455 return b ? m_expr1->evaluateToUInt32(exec) : m_expr2->evaluateToUInt32(exec);
3460 static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper) KJS_FAST_CALL;
3461 static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper)
3469 v = jsNumber(exec, current->toNumber(exec) * right->evaluateToNumber(exec));
3472 v = jsNumber(exec, current->toNumber(exec) / right->evaluateToNumber(exec));
3475 v = add(exec, current, right->evaluate(exec));
3478 v = jsNumber(exec, current->toNumber(exec) - right->evaluateToNumber(exec));
3481 i1 = current->toInt32(exec);
3482 i2 = right->evaluateToInt32(exec);
3483 v = jsNumber(exec, i1 << i2);
3486 i1 = current->toInt32(exec);
3487 i2 = right->evaluateToInt32(exec);
3488 v = jsNumber(exec, i1 >> i2);
3491 ui = current->toUInt32(exec);
3492 i2 = right->evaluateToInt32(exec);
3493 v = jsNumber(exec, ui >> i2);
3496 i1 = current->toInt32(exec);
3497 i2 = right->evaluateToInt32(exec);
3498 v = jsNumber(exec, i1 & i2);
3501 i1 = current->toInt32(exec);
3502 i2 = right->evaluateToInt32(exec);
3503 v = jsNumber(exec, i1 ^ i2);
3506 i1 = current->toInt32(exec);
3507 i2 = right->evaluateToInt32(exec);
3508 v = jsNumber(exec, i1 | i2);
3511 double d1 = current->toNumber(exec);
3512 double d2 = right->evaluateToNumber(exec);
3513 v = jsNumber(exec, fmod(d1, d2));
3517 ASSERT_NOT_REACHED();
3524 // ------------------------------ ReadModifyResolveNode -----------------------------------
3526 void ReadModifyResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
3528 nodeStack.append(m_right.get());
3529 size_t index = symbolTable.get(m_ident.ustring().rep());
3530 if (index != missingSymbolMarker()) {
3531 if (isConstant(localStorage, index))
3532 new (this) ReadModifyConstNode(index);
3534 new (this) ReadModifyLocalVarNode(index);
3538 // ------------------------------ AssignResolveNode -----------------------------------
3540 void AssignResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
3542 nodeStack.append(m_right.get());
3543 size_t index = symbolTable.get(m_ident.ustring().rep());
3544 if (index != missingSymbolMarker()) {
3545 if (isConstant(localStorage, index))
3546 new (this) AssignConstNode;
3548 new (this) AssignLocalVarNode(index);
3552 // ------------------------------ ReadModifyLocalVarNode -----------------------------------
3554 JSValue* ReadModifyLocalVarNode::evaluate(ExecState* exec)
3556 ASSERT(exec->variableObject() == exec->scopeChain().top());
3558 ASSERT(m_operator != OpEqual);
3559 JSValue* v = valueForReadModifyAssignment(exec, exec->localStorage()[m_index].value, m_right.get(), m_operator);
3561 KJS_CHECKEXCEPTIONVALUE
3563 // We can't store a pointer into localStorage() and use it throughout the function
3564 // body, because valueForReadModifyAssignment() might cause an ActivationImp tear-off,
3565 // changing the value of localStorage().
3567 exec->localStorage()[m_index].value = v;
3571 // ------------------------------ AssignLocalVarNode -----------------------------------
3573 JSValue* AssignLocalVarNode::evaluate(ExecState* exec)
3575 ASSERT(exec->variableObject() == exec->scopeChain().top());
3576 JSValue* v = m_right->evaluate(exec);
3578 KJS_CHECKEXCEPTIONVALUE
3580 exec->localStorage()[m_index].value = v;
3585 // ------------------------------ ReadModifyConstNode -----------------------------------
3587 JSValue* ReadModifyConstNode::evaluate(ExecState* exec)
3589 ASSERT(exec->variableObject() == exec->scopeChain().top());
3590 JSValue* left = exec->localStorage()[m_index].value;
3591 ASSERT(m_operator != OpEqual);
3592 JSValue* result = valueForReadModifyAssignment(exec, left, m_right.get(), m_operator);
3593 KJS_CHECKEXCEPTIONVALUE
3597 // ------------------------------ AssignConstNode -----------------------------------
3599 JSValue* AssignConstNode::evaluate(ExecState* exec)
3601 return m_right->evaluate(exec);
3604 JSValue* ReadModifyResolveNode::evaluate(ExecState* exec)
3606 const ScopeChain& chain = exec->scopeChain();
3607 ScopeChainIterator iter = chain.begin();
3608 ScopeChainIterator end = chain.end();
3610 // We must always have something in the scope chain
3611 ASSERT(iter != end);
3617 if (base->getPropertySlot(exec, m_ident, slot)) {
3618 // See the comment in PostIncResolveNode::evaluate().
3625 } while (iter != end);
3627 ASSERT(m_operator != OpEqual);
3628 return throwUndefinedVariableError(exec, m_ident);
3633 ASSERT(m_operator != OpEqual);
3634 JSValue* v1 = slot.getValue(exec, base, m_ident);
3635 KJS_CHECKEXCEPTIONVALUE
3636 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
3638 KJS_CHECKEXCEPTIONVALUE
3640 // Since valueForReadModifyAssignment() might cause an ActivationImp tear-off,
3641 // we need to get the base from the ScopeChainIterator again.
3643 (*iter)->put(exec, m_ident, v);
3647 JSValue* AssignResolveNode::evaluate(ExecState* exec)
3649 const ScopeChain& chain = exec->scopeChain();
3650 ScopeChainIterator iter = chain.begin();
3651 ScopeChainIterator end = chain.end();
3653 // we must always have something in the scope chain
3654 ASSERT(iter != end);
3660 if (base->getPropertySlot(exec, m_ident, slot)) {
3661 // See the comment in PostIncResolveNode::evaluate().
3668 } while (iter != end);
3671 JSValue* v = m_right->evaluate(exec);
3673 KJS_CHECKEXCEPTIONVALUE
3675 base->put(exec, m_ident, v);
3679 // ------------------------------ ReadModifyDotNode -----------------------------------
3681 void AssignDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3683 nodeStack.append(m_right.get());
3684 nodeStack.append(m_base.get());
3687 JSValue* AssignDotNode::evaluate(ExecState* exec)
3689 JSValue* baseValue = m_base->evaluate(exec);
3690 KJS_CHECKEXCEPTIONVALUE
3691 JSObject* base = baseValue->toObject(exec);
3693 JSValue* v = m_right->evaluate(exec);
3695 KJS_CHECKEXCEPTIONVALUE
3697 base->put(exec, m_ident, v);
3701 void ReadModifyDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3703 nodeStack.append(m_right.get());
3704 nodeStack.append(m_base.get());
3707 JSValue* ReadModifyDotNode::evaluate(ExecState* exec)
3709 JSValue* baseValue = m_base->evaluate(exec);
3710 KJS_CHECKEXCEPTIONVALUE
3711 JSObject* base = baseValue->toObject(exec);
3715 ASSERT(m_operator != OpEqual);
3717 JSValue* v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
3718 KJS_CHECKEXCEPTIONVALUE
3719 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
3721 KJS_CHECKEXCEPTIONVALUE
3723 base->put(exec, m_ident, v);
3727 // ------------------------------ AssignErrorNode -----------------------------------
3729 JSValue* AssignErrorNode::evaluate(ExecState* exec)
3731 throwError(exec, ReferenceError, "Left side of assignment is not a reference.");
3732 handleException(exec);
3733 return jsUndefined();
3736 // ------------------------------ AssignBracketNode -----------------------------------
3738 void AssignBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3740 nodeStack.append(m_right.get());
3741 nodeStack.append(m_subscript.get());
3742 nodeStack.append(m_base.get());
3745 JSValue* AssignBracketNode::evaluate(ExecState* exec)
3747 JSValue* baseValue = m_base->evaluate(exec);
3748 KJS_CHECKEXCEPTIONVALUE
3749 JSValue* subscript = m_subscript->evaluate(exec);
3750 KJS_CHECKEXCEPTIONVALUE
3752 JSObject* base = baseValue->toObject(exec);
3754 uint32_t propertyIndex;
3755 if (subscript->getUInt32(propertyIndex)) {
3756 JSValue* v = m_right->evaluate(exec);
3757 KJS_CHECKEXCEPTIONVALUE
3759 base->put(exec, propertyIndex, v);
3763 Identifier propertyName(subscript->toString(exec));
3764 JSValue* v = m_right->evaluate(exec);
3765 KJS_CHECKEXCEPTIONVALUE
3767 base->put(exec, propertyName, v);
3770 void ReadModifyBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3772 nodeStack.append(m_right.get());
3773 nodeStack.append(m_subscript.get());
3774 nodeStack.append(m_base.get());
3777 JSValue* ReadModifyBracketNode::evaluate(ExecState* exec)
3779 JSValue* baseValue = m_base->evaluate(exec);
3780 KJS_CHECKEXCEPTIONVALUE
3781 JSValue* subscript = m_subscript->evaluate(exec);
3782 KJS_CHECKEXCEPTIONVALUE
3784 JSObject* base = baseValue->toObject(exec);
3786 uint32_t propertyIndex;
3787 if (subscript->getUInt32(propertyIndex)) {
3789 ASSERT(m_operator != OpEqual);
3791 JSValue* v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
3792 KJS_CHECKEXCEPTIONVALUE
3793 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
3795 KJS_CHECKEXCEPTIONVALUE
3797 base->put(exec, propertyIndex, v);
3801 Identifier propertyName(subscript->toString(exec));
3804 ASSERT(m_operator != OpEqual);
3806 JSValue* v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
3807 KJS_CHECKEXCEPTIONVALUE
3808 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
3810 KJS_CHECKEXCEPTIONVALUE
3812 base->put(exec, propertyName, v);
3816 // ------------------------------ CommaNode ------------------------------------
3818 void CommaNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3820 nodeStack.append(m_expr2.get());
3821 nodeStack.append(m_expr1.get());
3825 JSValue* CommaNode::evaluate(ExecState* exec)
3827 m_expr1->evaluate(exec);
3828 KJS_CHECKEXCEPTIONVALUE
3829 return m_expr2->evaluate(exec);
3832 // ------------------------------ ConstDeclNode ----------------------------------
3834 ConstDeclNode::ConstDeclNode(const Identifier& ident, ExpressionNode* init)
3840 void ConstDeclNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3843 nodeStack.append(m_next.get());
3845 nodeStack.append(m_init.get());
3848 void ConstDeclNode::handleSlowCase(ExecState* exec, const ScopeChain& chain, JSValue* val)
3850 ScopeChainIterator iter = chain.begin();
3851 ScopeChainIterator end = chain.end();
3853 // We must always have something in the scope chain
3854 ASSERT(iter != end);
3860 if (base->isVariableObject())
3863 } while (iter != end);
3865 ASSERT(base && base->isVariableObject());
3867 static_cast<JSVariableObject*>(base)->putWithAttributes(exec, m_ident, val, ReadOnly);
3871 inline void ConstDeclNode::evaluateSingle(ExecState* exec)
3873 ASSERT(exec->variableObject()->hasOwnProperty(exec, m_ident) || exec->codeType() == EvalCode); // Guaranteed by processDeclarations.
3874 const ScopeChain& chain = exec->scopeChain();
3875 JSVariableObject* variableObject = exec->variableObject();
3877 ASSERT(!chain.isEmpty());
3879 bool inGlobalScope = ++chain.begin() == chain.end();
3882 if (inGlobalScope) {
3883 JSValue* val = m_init->evaluate(exec);
3884 unsigned attributes = ReadOnly;
3885 if (exec->codeType() != EvalCode)
3886 attributes |= DontDelete;
3887 variableObject->putWithAttributes(exec, m_ident, val, attributes);
3889 JSValue* val = m_init->evaluate(exec);
3890 KJS_CHECKEXCEPTIONVOID
3892 // if the variable object is the top of the scope chain, then that must
3893 // be where this variable is declared, processVarDecls would have put
3894 // it there. Don't search the scope chain, to optimize this very common case.
3895 if (chain.top() != variableObject)
3896 return handleSlowCase(exec, chain, val);
3898 variableObject->putWithAttributes(exec, m_ident, val, ReadOnly);
3903 JSValue* ConstDeclNode::evaluate(ExecState* exec)
3905 evaluateSingle(exec);
3907 if (ConstDeclNode* n = m_next.get()) {
3909 n->evaluateSingle(exec);
3910 KJS_CHECKEXCEPTIONVALUE
3911 n = n->m_next.get();
3914 return jsUndefined();
3917 // ------------------------------ ConstStatementNode -----------------------------
3919 void ConstStatementNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3922 nodeStack.append(m_next.get());
3926 JSValue* ConstStatementNode::execute(ExecState* exec)
3928 m_next->evaluate(exec);
3931 return exec->setNormalCompletion();
3934 // ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
3936 static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
3938 StatementVector::iterator it = statements.end();
3939 StatementVector::iterator begin = statements.begin();
3940 while (it != begin) {
3942 stack.append((*it).get());
3946 static inline Node* statementListInitializeVariableAccessStack(StatementVector& statements, DeclarationStacks::NodeStack& stack)
3948 if (statements.isEmpty())
3951 StatementVector::iterator it = statements.end();
3952 StatementVector::iterator begin = statements.begin();
3953 StatementVector::iterator beginPlusOne = begin + 1;
3955 while (it != beginPlusOne) {
3957 stack.append((*it).get());
3960 return (*begin).get();
3963 static inline JSValue* statementListExecute(StatementVector& statements, ExecState* exec)
3966 size_t size = statements.size();
3967 for (size_t i = 0; i != size; ++i) {
3968 JSValue* statementValue = statements[i]->execute(exec);
3970 value = statementValue;
3971 if (exec->completionType() != Normal)
3974 return exec->setNormalCompletion(value);
3977 // ------------------------------ BlockNode ------------------------------------
3979 BlockNode::BlockNode(SourceElements* children)
3982 children->releaseContentsIntoVector(m_children);
3985 void BlockNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3987 statementListPushFIFO(m_children, nodeStack);
3991 JSValue* BlockNode::execute(ExecState* exec)
3993 return statementListExecute(m_children, exec);
3996 // ------------------------------ EmptyStatementNode ---------------------------
3999 JSValue* EmptyStatementNode::execute(ExecState* exec)
4001 return exec->setNormalCompletion();
4004 // ------------------------------ ExprStatementNode ----------------------------
4006 void ExprStatementNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4009 nodeStack.append(m_expr.get());
4013 JSValue* ExprStatementNode::execute(ExecState* exec)
4015 JSValue* value = m_expr->evaluate(exec);
4018 return exec->setNormalCompletion(value);
4021 // ------------------------------ VarStatementNode ----------------------------
4023 void VarStatementNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4026 nodeStack.append(m_expr.get());
4029 JSValue* VarStatementNode::execute(ExecState* exec)
4031 m_expr->evaluate(exec);
4034 return exec->setNormalCompletion();
4037 // ------------------------------ IfNode ---------------------------------------
4039 void IfNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4041 nodeStack.append(m_ifBlock.get());
4042 nodeStack.append(m_condition.get());
4046 JSValue* IfNode::execute(ExecState* exec)
4048 bool b = m_condition->evaluateToBoolean(exec);
4052 return m_ifBlock->execute(exec);
4053 return exec->setNormalCompletion();
4056 void IfElseNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
4058 nodeStack.append(m_elseBlock.get());
4059 IfNode::optimizeVariableAccess(exec, symbolTable, localStorage, nodeStack);
4063 JSValue* IfElseNode::execute(ExecState* exec)
4065 bool b = m_condition->evaluateToBoolean(exec);
4069 return m_ifBlock->execute(exec);
4070 return m_elseBlock->execute(exec);
4073 // ------------------------------ DoWhileNode ----------------------------------
4075 void DoWhileNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4077 nodeStack.append(m_statement.get());
4078 nodeStack.append(m_expr.get());
4082 JSValue* DoWhileNode::execute(ExecState* exec)
4087 exec->pushIteration();
4088 JSValue* statementValue = m_statement->execute(exec);
4089 exec->popIteration();
4091 if (exec->dynamicGlobalObject()->timedOut())
4092 return exec->setInterruptedCompletion();
4095 value = statementValue;
4097 if (exec->completionType() != Normal) {
4098 if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
4099 goto continueDoWhileLoop;
4100 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
4102 return statementValue;
4105 continueDoWhileLoop:
4106 bool b = m_expr->evaluateToBoolean(exec);
4112 return exec->setNormalCompletion(value);
4115 // ------------------------------ WhileNode ------------------------------------
4117 void WhileNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4119 nodeStack.append(m_statement.get());
4120 nodeStack.append(m_expr.get());
4124 JSValue* WhileNode::execute(ExecState* exec)
4129 bool b = m_expr->evaluateToBoolean(exec);
4134 exec->pushIteration();
4135 JSValue* statementValue = m_statement->execute(exec);
4136 exec->popIteration();
4138 if (exec->dynamicGlobalObject()->timedOut())
4139 return exec->setInterruptedCompletion();
4142 value = statementValue;
4144 if (exec->completionType() != Normal) {
4145 if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
4147 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
4149 return statementValue;
4153 return exec->setNormalCompletion(value);
4156 // ------------------------------ ForNode --------------------------------------
4158 void ForNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4160 nodeStack.append(m_statement.get());
4161 nodeStack.append(m_expr3.get());
4162 nodeStack.append(m_expr2.get());
4163 nodeStack.append(m_expr1.get());
4167 JSValue* ForNode::execute(ExecState* exec)
4171 m_expr1->evaluate(exec);
4175 bool b = m_expr2->evaluateToBoolean(exec);
4180 exec->pushIteration();
4181 JSValue* statementValue = m_statement->execute(exec);
4182 exec->popIteration();
4184 value = statementValue;
4186 if (exec->dynamicGlobalObject()->timedOut())
4187 return exec->setInterruptedCompletion();
4189 if (exec->completionType() != Normal) {
4190 if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
4191 goto continueForLoop;
4192 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
4194 return statementValue;
4198 m_expr3->evaluate(exec);
4202 return exec->setNormalCompletion(value);
4205 // ------------------------------ ForInNode ------------------------------------
4207 ForInNode::ForInNode(ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
4211 , m_statement(statement)
4212 , m_identIsVarDecl(false)
4216 ForInNode::ForInNode(const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement)
4218 , m_lexpr(new ResolveNode(ident))
4220 , m_statement(statement)
4221 , m_identIsVarDecl(true)
4224 m_init = new AssignResolveNode(ident, in);
4225 // for( var foo = bar in baz )
4228 void ForInNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4230 nodeStack.append(m_statement.get());
4231 nodeStack.append(m_expr.get());
4232 nodeStack.append(m_lexpr.get());
4234 nodeStack.append(m_init.get());
4238 JSValue* ForInNode::execute(ExecState* exec)
4243 m_init->evaluate(exec);
4247 JSValue* e = m_expr->evaluate(exec);
4250 // For Null and Undefined, we want to make sure not to go through
4251 // the loop at all, because toObject will throw an exception.
4252 if (e->isUndefinedOrNull())
4253 return exec->setNormalCompletion();
4255 JSObject* v = e->toObject(exec);
4256 PropertyNameArray propertyNames;
4257 v->getPropertyNames(exec, propertyNames);
4259 PropertyNameArray::const_iterator end = propertyNames.end();
4260 for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != end; ++it) {
4261 const Identifier& name = *it;
4262 if (!v->hasProperty(exec, name))
4265 JSValue* str = jsOwnedString(exec, name.ustring());
4267 if (m_lexpr->isResolveNode()) {
4268 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
4270 const ScopeChain& chain = exec->scopeChain();
4271 ScopeChainIterator iter = chain.begin();
4272 ScopeChainIterator end = chain.end();
4274 // we must always have something in the scope chain
4275 ASSERT(iter != end);
4281 if (o->getPropertySlot(exec, ident, slot)) {
4282 o->put(exec, ident, str);
4286 } while (iter != end);
4289 o->put(exec, ident, str);
4290 } else if (m_lexpr->isDotAccessorNode()) {
4291 const Identifier& ident = static_cast<DotAccessorNode*>(m_lexpr.get())->identifier();
4292 JSValue* v = static_cast<DotAccessorNode*>(m_lexpr.get())->base()->evaluate(exec);
4294 JSObject* o = v->toObject(exec);
4296 o->put(exec, ident, str);
4298 ASSERT(m_lexpr->isBracketAccessorNode());
4299 JSValue* v = static_cast<BracketAccessorNode*>(m_lexpr.get())->base()->evaluate(exec);
4301 JSValue* v2 = static_cast<BracketAccessorNode*>(m_lexpr.get())->subscript()->evaluate(exec);
4303 JSObject* o = v->toObject(exec);
4306 if (v2->getUInt32(i))
4307 o->put(exec, i, str);
4308 o->put(exec, Identifier(v2->toString(exec)), str);
4313 exec->pushIteration();
4314 JSValue* statementValue = m_statement->execute(exec);
4315 exec->popIteration();
4317 value = statementValue;
4319 if (exec->dynamicGlobalObject()->timedOut())
4320 return exec->setInterruptedCompletion();
4322 if (exec->completionType() != Normal) {
4323 if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
4325 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
4327 return statementValue;
4331 return exec->setNormalCompletion(value);
4334 // ------------------------------ ContinueNode ---------------------------------
4337 JSValue* ContinueNode::execute(ExecState* exec)
4339 if (m_ident.isEmpty() && !exec->inIteration())
4340 return setErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
4341 if (!m_ident.isEmpty() && !exec->seenLabels().contains(m_ident))
4342 return setErrorCompletion(exec, SyntaxError, "Label %s not found.", m_ident);
4343 return exec->setContinueCompletion(&m_ident);
4346 // ------------------------------ BreakNode ------------------------------------
4349 JSValue* BreakNode::execute(ExecState* exec)
4351 if (m_ident.isEmpty() && !exec->inIteration() && !exec->inSwitch())
4352 return setErrorCompletion(exec, SyntaxError, "Invalid break statement.");
4353 if (!m_ident.isEmpty() && !exec->seenLabels().contains(m_ident))
4354 return setErrorCompletion(exec, SyntaxError, "Label %s not found.");
4355 return exec->setBreakCompletion(&m_ident);
4358 // ------------------------------ ReturnNode -----------------------------------
4360 void ReturnNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4363 nodeStack.append(m_value.get());
4367 JSValue* ReturnNode::execute(ExecState* exec)
4369 CodeType codeType = exec->codeType();
4370 if (codeType != FunctionCode)
4371 return setErrorCompletion(exec, SyntaxError, "Invalid return statement.");
4374 return exec->setReturnValueCompletion(jsUndefined());
4376 JSValue* v = m_value->evaluate(exec);
4379 return exec->setReturnValueCompletion(v);
4382 // ------------------------------ WithNode -------------------------------------
4384 void WithNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4386 // Can't optimize within statement because "with" introduces a dynamic scope.
4387 nodeStack.append(m_expr.get());
4391 JSValue* WithNode::execute(ExecState* exec)
4393 JSValue* v = m_expr->evaluate(exec);
4395 JSObject* o = v->toObject(exec);
4397 exec->dynamicGlobalObject()->tearOffActivation(exec);
4399 JSValue* value = m_statement->execute(exec);
4405 // ------------------------------ CaseClauseNode -------------------------------
4407 void CaseClauseNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4410 nodeStack.append(m_expr.get());
4411 statementListPushFIFO(m_children, nodeStack);
4415 JSValue* CaseClauseNode::evaluate(ExecState* exec)
4417 JSValue* v = m_expr->evaluate(exec);
4418 KJS_CHECKEXCEPTIONVALUE
4424 JSValue* CaseClauseNode::executeStatements(ExecState* exec)
4426 return statementListExecute(m_children, exec);
4429 // ------------------------------ ClauseListNode -------------------------------
4431 void ClauseListNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4434 nodeStack.append(m_next.get());
4435 nodeStack.append(m_clause.get());
4438 // ------------------------------ CaseBlockNode --------------------------------
4440 CaseBlockNode::CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2)
4442 , m_defaultClause(defaultClause)
4447 void CaseBlockNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4450 nodeStack.append(m_list2.get());
4451 if (m_defaultClause)
4452 nodeStack.append(m_defaultClause.get());
4454 nodeStack.append(m_list1.get());
4458 JSValue* CaseBlockNode::executeBlock(ExecState* exec, JSValue* input)
4460 ClauseListNode* a = m_list1.get();
4462 CaseClauseNode* clause = a->getClause();
4464 JSValue* v = clause->evaluate(exec);
4466 if (strictEqual(exec, input, v)) {
4467 JSValue* res = clause->executeStatements(exec);
4468 if (exec->completionType() != Normal)
4470 for (; a; a = a->getNext()) {
4471 JSValue* res = a->getClause()->executeStatements(exec);
4472 if (exec->completionType() != Normal)
4479 ClauseListNode* b = m_list2.get();
4481 CaseClauseNode* clause = b->getClause();
4483 JSValue* v = clause->evaluate(exec);
4485 if (strictEqual(exec, input, v)) {
4486 JSValue* res = clause->executeStatements(exec);
4487 if (exec->completionType() != Normal)
4494 if (m_defaultClause) {
4495 JSValue* res = m_defaultClause->executeStatements(exec);
4496 if (exec->completionType() != Normal)
4502 CaseClauseNode* clause = b->getClause();
4503 JSValue* res = clause->executeStatements(exec);
4504 if (exec->completionType() != Normal)
4509 // bail out on error
4512 return exec->setNormalCompletion();
4515 // ------------------------------ SwitchNode -----------------------------------
4517 void SwitchNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4519 nodeStack.append(m_block.get());
4520 nodeStack.append(m_expr.get());
4524 JSValue* SwitchNode::execute(ExecState* exec)
4526 JSValue* v = m_expr->evaluate(exec);
4530 JSValue* result = m_block->executeBlock(exec, v);
4533 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
4534 exec->setCompletionType(Normal);
4538 // ------------------------------ LabelNode ------------------------------------
4540 void LabelNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4542 nodeStack.append(m_statement.get());
4546 JSValue* LabelNode::execute(ExecState* exec)
4548 if (!exec->seenLabels().push(m_label))
4549 return setErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", m_label);
4550 JSValue* result = m_statement->execute(exec);
4551 exec->seenLabels().pop();
4553 if (exec->completionType() == Break && exec->breakOrContinueTarget() == m_label)
4554 exec->setCompletionType(Normal);
4558 // ------------------------------ ThrowNode ------------------------------------
4560 void ThrowNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4562 nodeStack.append(m_expr.get());
4566 JSValue* ThrowNode::execute(ExecState* exec)
4568 JSValue* v = m_expr->evaluate(exec);
4571 handleException(exec, v);
4572 return exec->setThrowCompletion(v);
4575 // ------------------------------ TryNode --------------------------------------
4577 void TryNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4579 // Can't optimize within catchBlock because "catch" introduces a dynamic scope.
4581 nodeStack.append(m_finallyBlock.get());
4582 nodeStack.append(m_tryBlock.get());
4586 JSValue* TryNode::execute(ExecState* exec)
4588 JSValue* result = m_tryBlock->execute(exec);
4590 if (m_catchBlock && exec->completionType() == Throw) {
4591 JSObject* obj = new (exec) JSObject;
4592 obj->putDirect(m_exceptionIdent, result, DontDelete);
4593 exec->dynamicGlobalObject()->tearOffActivation(exec);
4594 exec->pushScope(obj);
4595 result = m_catchBlock->execute(exec);
4599 if (m_finallyBlock) {
4600 ComplType savedCompletionType = exec->completionType();
4601 JSValue* finallyResult = m_finallyBlock->execute(exec);
4602 if (exec->completionType() != Normal)
4603 result = finallyResult;
4605 exec->setCompletionType(savedCompletionType);
4611 // ------------------------------ FunctionBodyNode -----------------------------
4613 ScopeNode::ScopeNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
4614 : BlockNode(children)
4615 , m_sourceURL(parser().sourceURL())
4616 , m_sourceId(parser().sourceId())
4617 , m_usesEval(usesEval)