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>
47 class FunctionBodyNodeWithDebuggerHooks : public FunctionBodyNode {
49 FunctionBodyNodeWithDebuggerHooks(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
50 virtual JSValue* execute(ExecState*) KJS_FAST_CALL;
55 __builtin_expect ((x), 0)
60 #define KJS_CHECKEXCEPTION \
61 if (UNLIKELY(exec->hadException())) \
62 return rethrowException(exec);
64 #define KJS_CHECKEXCEPTIONVALUE \
65 if (UNLIKELY(exec->hadException())) { \
66 handleException(exec); \
67 return jsUndefined(); \
70 #define KJS_CHECKEXCEPTIONNUMBER \
71 if (UNLIKELY(exec->hadException())) { \
72 handleException(exec); \
76 #define KJS_CHECKEXCEPTIONBOOLEAN \
77 if (UNLIKELY(exec->hadException())) { \
78 handleException(exec); \
82 #define KJS_CHECKEXCEPTIONVOID \
83 if (UNLIKELY(exec->hadException())) { \
84 handleException(exec); \
89 static inline bool canSkipLookup(ExecState* exec, const Identifier& ident)
91 // Static lookup in EvalCode is impossible because variables aren't DontDelete.
92 // Static lookup in GlobalCode may be possible, but we haven't implemented support for it yet.
93 if (exec->codeType() != FunctionCode)
96 // Static lookup is impossible when something dynamic has been added to the front of the scope chain.
97 if (exec->variableObject() != exec->scopeChain().top())
100 // Static lookup is impossible if the symbol isn't statically declared.
101 if (!exec->variableObject()->symbolTable().contains(ident.ustring().rep()))
108 static inline bool isConstant(const LocalStorage& localStorage, size_t index)
110 ASSERT(index < localStorage.size());
111 return localStorage[index].attributes & ReadOnly;
114 // ------------------------------ Node -----------------------------------------
117 #ifndef LOG_CHANNEL_PREFIX
118 #define LOG_CHANNEL_PREFIX Log
120 static WTFLogChannel LogKJSNodeLeaks = { 0x00000000, "", WTFLogChannelOn };
122 struct ParserRefCountedCounter {
123 static unsigned count;
124 ParserRefCountedCounter()
127 LOG(KJSNodeLeaks, "LEAK: %u KJS::Node\n", count);
130 unsigned ParserRefCountedCounter::count = 0;
131 static ParserRefCountedCounter parserRefCountedCounter;
134 static HashSet<ParserRefCounted*>* newTrackedObjects;
135 static HashCountedSet<ParserRefCounted*>* trackedObjectExtraRefCounts;
137 ParserRefCounted::ParserRefCounted()
140 ++ParserRefCountedCounter::count;
142 if (!newTrackedObjects)
143 newTrackedObjects = new HashSet<ParserRefCounted*>;
144 newTrackedObjects->add(this);
145 ASSERT(newTrackedObjects->contains(this));
148 ParserRefCounted::~ParserRefCounted()
151 --ParserRefCountedCounter::count;
155 void ParserRefCounted::ref()
157 // bumping from 0 to 1 is just removing from the new nodes set
158 if (newTrackedObjects) {
159 HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->find(this);
160 if (it != newTrackedObjects->end()) {
161 newTrackedObjects->remove(it);
162 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
167 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
169 if (!trackedObjectExtraRefCounts)
170 trackedObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
171 trackedObjectExtraRefCounts->add(this);
174 void ParserRefCounted::deref()
176 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
178 if (!trackedObjectExtraRefCounts) {
183 HashCountedSet<ParserRefCounted*>::iterator it = trackedObjectExtraRefCounts->find(this);
184 if (it == trackedObjectExtraRefCounts->end())
187 trackedObjectExtraRefCounts->remove(it);
190 unsigned ParserRefCounted::refcount()
192 if (newTrackedObjects && newTrackedObjects->contains(this)) {
193 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
197 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
199 if (!trackedObjectExtraRefCounts)
202 return 1 + trackedObjectExtraRefCounts->count(this);
205 void ParserRefCounted::deleteNewObjects()
207 if (!newTrackedObjects)
211 HashSet<ParserRefCounted*>::iterator end = newTrackedObjects->end();
212 for (HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->begin(); it != end; ++it)
213 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(*it));
215 deleteAllValues(*newTrackedObjects);
216 delete newTrackedObjects;
217 newTrackedObjects = 0;
221 : m_expectedReturnType(ObjectType)
223 m_line = lexer().lineNo();
226 Node::Node(JSType expectedReturn)
227 : m_expectedReturnType(expectedReturn)
229 m_line = lexer().lineNo();
232 double ExpressionNode::evaluateToNumber(ExecState* exec)
234 JSValue* value = evaluate(exec);
235 KJS_CHECKEXCEPTIONNUMBER
236 return value->toNumber(exec);
239 bool ExpressionNode::evaluateToBoolean(ExecState* exec)
241 JSValue* value = evaluate(exec);
242 KJS_CHECKEXCEPTIONBOOLEAN
243 return value->toBoolean(exec);
246 int32_t ExpressionNode::evaluateToInt32(ExecState* exec)
248 JSValue* value = evaluate(exec);
249 KJS_CHECKEXCEPTIONNUMBER
250 return value->toInt32(exec);
253 uint32_t ExpressionNode::evaluateToUInt32(ExecState* exec)
255 JSValue* value = evaluate(exec);
256 KJS_CHECKEXCEPTIONNUMBER
257 return value->toUInt32(exec);
260 static void substitute(UString& string, const UString& substring) KJS_FAST_CALL;
261 static void substitute(UString& string, const UString& substring)
263 int position = string.find("%s");
264 ASSERT(position != -1);
265 UString newString = string.substr(0, position);
266 newString.append(substring);
267 newString.append(string.substr(position + 2));
271 static inline int currentSourceId(ExecState* exec) KJS_FAST_CALL;
272 static inline int currentSourceId(ExecState* exec)
274 return exec->scopeNode()->sourceId();
277 static inline const UString& currentSourceURL(ExecState* exec) KJS_FAST_CALL;
278 static inline const UString& currentSourceURL(ExecState* exec)
280 return exec->scopeNode()->sourceURL();
283 JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg)
285 return exec->setThrowCompletion(Error::create(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
288 JSValue* Node::setErrorCompletion(ExecState* exec, ErrorType e, const char* msg, const Identifier& ident)
290 UString message = msg;
291 substitute(message, ident.ustring());
292 return exec->setThrowCompletion(Error::create(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
295 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg)
297 return KJS::throwError(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec));
300 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const char* string)
302 UString message = msg;
303 substitute(message, string);
304 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
307 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr)
309 UString message = msg;
310 substitute(message, v->toString(exec));
311 substitute(message, expr->toString());
312 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
315 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, const Identifier& label)
317 UString message = msg;
318 substitute(message, label.ustring());
319 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
322 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* e1, Node* e2)
324 UString message = msg;
325 substitute(message, v->toString(exec));
326 substitute(message, e1->toString());
327 substitute(message, e2->toString());
328 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
331 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr, const Identifier& label)
333 UString message = msg;
334 substitute(message, v->toString(exec));
335 substitute(message, expr->toString());
336 substitute(message, label.ustring());
337 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
340 JSValue* Node::throwError(ExecState* exec, ErrorType e, const char* msg, JSValue* v, const Identifier& label)
342 UString message = msg;
343 substitute(message, v->toString(exec));
344 substitute(message, label.ustring());
345 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
348 JSValue* Node::throwUndefinedVariableError(ExecState* exec, const Identifier& ident)
350 return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
353 void Node::handleException(ExecState* exec)
355 handleException(exec, exec->exception());
358 void Node::handleException(ExecState* exec, JSValue* exceptionValue)
360 if (exceptionValue->isObject()) {
361 JSObject* exception = static_cast<JSObject*>(exceptionValue);
362 if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
363 exception->put(exec, "line", jsNumber(m_line));
364 exception->put(exec, "sourceURL", jsString(currentSourceURL(exec)));
367 Debugger* dbg = exec->dynamicGlobalObject()->debugger();
368 if (dbg && !dbg->hasHandledException(exec, exceptionValue))
369 dbg->exception(exec, currentSourceId(exec), m_line, exceptionValue);
372 NEVER_INLINE JSValue* Node::rethrowException(ExecState* exec)
374 JSValue* exception = exec->exception();
375 exec->clearException();
376 handleException(exec, exception);
377 return exec->setThrowCompletion(exception);
380 // ------------------------------ StatementNode --------------------------------
382 StatementNode::StatementNode()
388 void StatementNode::setLoc(int firstLine, int lastLine)
391 m_lastLine = lastLine;
394 // ------------------------------ SourceElements --------------------------------
396 void SourceElements::append(PassRefPtr<StatementNode> statement)
398 if (statement->isEmptyStatement())
401 if (Debugger::debuggersPresent)
402 m_statements.append(new BreakpointCheckStatement(statement));
404 m_statements.append(statement);
407 // ------------------------------ BreakpointCheckStatement --------------------------------
409 BreakpointCheckStatement::BreakpointCheckStatement(PassRefPtr<StatementNode> statement)
410 : m_statement(statement)
415 JSValue* BreakpointCheckStatement::execute(ExecState* exec)
417 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger())
418 if (!debugger->atStatement(exec, currentSourceId(exec), m_statement->firstLine(), m_statement->lastLine()))
419 return exec->setNormalCompletion();
420 return m_statement->execute(exec);
423 void BreakpointCheckStatement::streamTo(SourceStream& stream) const
425 m_statement->streamTo(stream);
428 void BreakpointCheckStatement::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
430 nodeStack.append(m_statement.get());
433 // ------------------------------ NullNode -------------------------------------
435 JSValue* NullNode::evaluate(ExecState* )
440 // ------------------------------ FalseNode ----------------------------------
442 JSValue* FalseNode::evaluate(ExecState*)
444 return jsBoolean(false);
447 // ------------------------------ TrueNode ----------------------------------
449 JSValue* TrueNode::evaluate(ExecState*)
451 return jsBoolean(true);
454 // ------------------------------ NumberNode -----------------------------------
456 JSValue* NumberNode::evaluate(ExecState*)
458 // Number nodes are only created when the number can't fit in a JSImmediate, so no need to check again.
459 return jsNumberCell(m_double);
462 double NumberNode::evaluateToNumber(ExecState*)
467 bool NumberNode::evaluateToBoolean(ExecState*)
469 return m_double < 0.0 || m_double > 0.0; // false for NaN as well as 0
472 int32_t NumberNode::evaluateToInt32(ExecState*)
474 return JSValue::toInt32(m_double);
477 uint32_t NumberNode::evaluateToUInt32(ExecState*)
479 return JSValue::toUInt32(m_double);
482 // ------------------------------ ImmediateNumberNode -----------------------------------
484 JSValue* ImmediateNumberNode::evaluate(ExecState*)
489 int32_t ImmediateNumberNode::evaluateToInt32(ExecState*)
491 return JSImmediate::getTruncatedInt32(m_value);
494 uint32_t ImmediateNumberNode::evaluateToUInt32(ExecState*)
497 if (JSImmediate::getTruncatedUInt32(m_value, i))
500 return JSValue::toUInt32SlowCase(m_double, ok);
503 // ------------------------------ StringNode -----------------------------------
505 JSValue* StringNode::evaluate(ExecState*)
507 return jsOwnedString(m_value);
510 double StringNode::evaluateToNumber(ExecState*)
512 return m_value.toDouble();
515 bool StringNode::evaluateToBoolean(ExecState*)
517 return !m_value.isEmpty();
520 // ------------------------------ RegExpNode -----------------------------------
522 JSValue* RegExpNode::evaluate(ExecState* exec)
524 return exec->lexicalGlobalObject()->regExpConstructor()->createRegExpImp(exec, m_regExp);
527 // ------------------------------ ThisNode -------------------------------------
530 JSValue* ThisNode::evaluate(ExecState* exec)
532 return exec->thisValue();
535 // ------------------------------ ResolveNode ----------------------------------
537 // ECMA 11.1.2 & 10.1.4
538 JSValue* ResolveNode::inlineEvaluate(ExecState* exec)
540 // Check for missed optimization opportunity.
541 ASSERT(!canSkipLookup(exec, m_ident));
543 const ScopeChain& chain = exec->scopeChain();
544 ScopeChainIterator iter = chain.begin();
545 ScopeChainIterator end = chain.end();
547 // we must always have something in the scope chain
554 if (o->getPropertySlot(exec, m_ident, slot))
555 return slot.getValue(exec, o, m_ident);
558 } while (iter != end);
560 return throwUndefinedVariableError(exec, m_ident);
563 JSValue* ResolveNode::evaluate(ExecState* exec)
565 return inlineEvaluate(exec);
568 double ResolveNode::evaluateToNumber(ExecState* exec)
570 JSValue* v = inlineEvaluate(exec);
571 KJS_CHECKEXCEPTIONNUMBER
572 return v->toNumber(exec);
575 bool ResolveNode::evaluateToBoolean(ExecState* exec)
577 JSValue* v = inlineEvaluate(exec);
578 KJS_CHECKEXCEPTIONBOOLEAN
579 return v->toBoolean(exec);
582 int32_t ResolveNode::evaluateToInt32(ExecState* exec)
584 JSValue* v = inlineEvaluate(exec);
585 KJS_CHECKEXCEPTIONNUMBER
586 return v->toInt32(exec);
589 uint32_t ResolveNode::evaluateToUInt32(ExecState* exec)
591 JSValue* v = inlineEvaluate(exec);
592 KJS_CHECKEXCEPTIONNUMBER
593 return v->toUInt32(exec);
596 static size_t getSymbolTableEntry(ExecState* exec, const Identifier& ident, const SymbolTable& symbolTable, size_t& stackDepth)
598 size_t index = symbolTable.get(ident.ustring().rep());
599 if (index != missingSymbolMarker()) {
604 if (ident == exec->propertyNames().arguments) {
606 return missingSymbolMarker();
609 const ScopeChain& chain = exec->scopeChain();
610 ScopeChainIterator iter = chain.begin();
611 ScopeChainIterator end = chain.end();
613 for (; iter != end; ++iter, ++depth) {
614 JSObject* currentScope = *iter;
615 if (!currentScope->isVariableObject())
617 JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
618 index = currentVariableObject->symbolTable().get(ident.ustring().rep());
619 if (index != missingSymbolMarker()) {
623 if (currentVariableObject->isDynamicScope())
627 return missingSymbolMarker();
630 void ResolveNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
633 size_t index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
634 if (index != missingSymbolMarker()) {
636 new (this) LocalVarAccessNode(index);
638 new (this) ScopedVarAccessNode(index, depth);
645 new (this) NonLocalVarAccessNode(depth);
648 JSValue* LocalVarAccessNode::inlineEvaluate(ExecState* exec)
650 ASSERT(exec->variableObject() == exec->scopeChain().top());
651 return exec->localStorage()[m_index].value;
654 JSValue* LocalVarAccessNode::evaluate(ExecState* exec)
656 return inlineEvaluate(exec);
659 double LocalVarAccessNode::evaluateToNumber(ExecState* exec)
661 return inlineEvaluate(exec)->toNumber(exec);
664 bool LocalVarAccessNode::evaluateToBoolean(ExecState* exec)
666 return inlineEvaluate(exec)->toBoolean(exec);
669 int32_t LocalVarAccessNode::evaluateToInt32(ExecState* exec)
671 return inlineEvaluate(exec)->toInt32(exec);
674 uint32_t LocalVarAccessNode::evaluateToUInt32(ExecState* exec)
676 return inlineEvaluate(exec)->toUInt32(exec);
679 static inline JSValue* getNonLocalSymbol(ExecState* exec, size_t index, size_t scopeDepth)
681 const ScopeChain& chain = exec->scopeChain();
682 ScopeChainIterator iter = chain.begin();
683 for (size_t i = 0; i < scopeDepth; ++iter, ++i)
684 ASSERT(iter != chain.end());
685 JSObject* scope = *iter;
686 ASSERT(scope->isVariableObject());
687 JSVariableObject* variableObject = static_cast<JSVariableObject*>(scope);
688 return variableObject->localStorage()[index].value;
691 JSValue* ScopedVarAccessNode::inlineEvaluate(ExecState* exec)
693 return getNonLocalSymbol(exec, m_index, m_scopeDepth);
696 JSValue* ScopedVarAccessNode::evaluate(ExecState* exec)
698 return inlineEvaluate(exec);
701 double ScopedVarAccessNode::evaluateToNumber(ExecState* exec)
703 return inlineEvaluate(exec)->toNumber(exec);
706 bool ScopedVarAccessNode::evaluateToBoolean(ExecState* exec)
708 return inlineEvaluate(exec)->toBoolean(exec);
711 int32_t ScopedVarAccessNode::evaluateToInt32(ExecState* exec)
713 return inlineEvaluate(exec)->toInt32(exec);
716 uint32_t ScopedVarAccessNode::evaluateToUInt32(ExecState* exec)
718 return inlineEvaluate(exec)->toUInt32(exec);
721 JSValue* NonLocalVarAccessNode::inlineEvaluate(ExecState* exec)
723 // Check for missed optimization opportunity.
724 ASSERT(!canSkipLookup(exec, m_ident));
726 const ScopeChain& chain = exec->scopeChain();
727 ScopeChainIterator iter = chain.begin();
728 ScopeChainIterator end = chain.end();
729 for (size_t i = 0; i < m_scopeDepth; ++i, ++iter)
732 // we must always have something in the scope chain
739 if (o->getPropertySlot(exec, m_ident, slot))
740 return slot.getValue(exec, o, m_ident);
743 } while (iter != end);
745 return throwUndefinedVariableError(exec, m_ident);
748 JSValue* NonLocalVarAccessNode::evaluate(ExecState* exec)
750 return inlineEvaluate(exec);
753 double NonLocalVarAccessNode::evaluateToNumber(ExecState* exec)
755 return inlineEvaluate(exec)->toNumber(exec);
758 bool NonLocalVarAccessNode::evaluateToBoolean(ExecState* exec)
760 return inlineEvaluate(exec)->toBoolean(exec);
763 int32_t NonLocalVarAccessNode::evaluateToInt32(ExecState* exec)
765 return inlineEvaluate(exec)->toInt32(exec);
768 uint32_t NonLocalVarAccessNode::evaluateToUInt32(ExecState* exec)
770 return inlineEvaluate(exec)->toUInt32(exec);
773 // ------------------------------ ElementNode ----------------------------------
775 void ElementNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
778 nodeStack.append(m_next.get());
780 nodeStack.append(m_node.get());
784 JSValue* ElementNode::evaluate(ExecState* exec)
786 JSObject* array = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
788 for (ElementNode* n = this; n; n = n->m_next.get()) {
789 JSValue* val = n->m_node->evaluate(exec);
790 KJS_CHECKEXCEPTIONVALUE
791 length += n->m_elision;
792 array->put(exec, length++, val);
797 // ------------------------------ ArrayNode ------------------------------------
799 void ArrayNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
802 nodeStack.append(m_element.get());
806 JSValue* ArrayNode::evaluate(ExecState* exec)
812 array = static_cast<JSObject*>(m_element->evaluate(exec));
813 KJS_CHECKEXCEPTIONVALUE
814 length = m_optional ? array->get(exec, exec->propertyNames().length)->toInt32(exec) : 0;
816 JSValue* newArr = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
817 array = static_cast<JSObject*>(newArr);
822 array->put(exec, exec->propertyNames().length, jsNumber(m_elision + length));
827 // ------------------------------ ObjectLiteralNode ----------------------------
829 void ObjectLiteralNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
832 nodeStack.append(m_list.get());
836 JSValue* ObjectLiteralNode::evaluate(ExecState* exec)
839 return m_list->evaluate(exec);
841 return exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
844 // ------------------------------ PropertyListNode -----------------------------
846 void PropertyListNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
849 nodeStack.append(m_next.get());
850 nodeStack.append(m_node.get());
854 JSValue* PropertyListNode::evaluate(ExecState* exec)
856 JSObject* obj = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
858 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
859 JSValue* v = p->m_node->m_assign->evaluate(exec);
860 KJS_CHECKEXCEPTIONVALUE
862 switch (p->m_node->m_type) {
863 case PropertyNode::Getter:
864 ASSERT(v->isObject());
865 obj->defineGetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
867 case PropertyNode::Setter:
868 ASSERT(v->isObject());
869 obj->defineSetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
871 case PropertyNode::Constant:
872 obj->put(exec, p->m_node->name(), v);
880 // ------------------------------ PropertyNode -----------------------------
882 void PropertyNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
884 nodeStack.append(m_assign.get());
888 JSValue* PropertyNode::evaluate(ExecState*)
894 // ------------------------------ BracketAccessorNode --------------------------------
896 void BracketAccessorNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
898 nodeStack.append(m_subscript.get());
899 nodeStack.append(m_base.get());
903 JSValue* BracketAccessorNode::inlineEvaluate(ExecState* exec)
905 JSValue* v1 = m_base->evaluate(exec);
906 KJS_CHECKEXCEPTIONVALUE
907 JSValue* v2 = m_subscript->evaluate(exec);
908 KJS_CHECKEXCEPTIONVALUE
909 JSObject* o = v1->toObject(exec);
911 if (v2->getUInt32(i))
912 return o->get(exec, i);
913 return o->get(exec, Identifier(v2->toString(exec)));
916 JSValue* BracketAccessorNode::evaluate(ExecState* exec)
918 return inlineEvaluate(exec);
921 double BracketAccessorNode::evaluateToNumber(ExecState* exec)
923 JSValue* v = inlineEvaluate(exec);
924 KJS_CHECKEXCEPTIONNUMBER
925 return v->toNumber(exec);
928 bool BracketAccessorNode::evaluateToBoolean(ExecState* exec)
930 JSValue* v = inlineEvaluate(exec);
931 KJS_CHECKEXCEPTIONBOOLEAN
932 return v->toBoolean(exec);
935 int32_t BracketAccessorNode::evaluateToInt32(ExecState* exec)
937 JSValue* v = inlineEvaluate(exec);
938 KJS_CHECKEXCEPTIONNUMBER
939 return v->toInt32(exec);
942 uint32_t BracketAccessorNode::evaluateToUInt32(ExecState* exec)
944 JSValue* v = inlineEvaluate(exec);
945 KJS_CHECKEXCEPTIONNUMBER
946 return v->toUInt32(exec);
949 // ------------------------------ DotAccessorNode --------------------------------
951 void DotAccessorNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
953 nodeStack.append(m_base.get());
957 JSValue* DotAccessorNode::inlineEvaluate(ExecState* exec)
959 JSValue* v = m_base->evaluate(exec);
960 KJS_CHECKEXCEPTIONVALUE
961 return v->toObject(exec)->get(exec, m_ident);
964 JSValue* DotAccessorNode::evaluate(ExecState* exec)
966 return inlineEvaluate(exec);
969 double DotAccessorNode::evaluateToNumber(ExecState* exec)
971 JSValue* v = inlineEvaluate(exec);
972 KJS_CHECKEXCEPTIONNUMBER
973 return v->toNumber(exec);
976 bool DotAccessorNode::evaluateToBoolean(ExecState* exec)
978 JSValue* v = inlineEvaluate(exec);
979 KJS_CHECKEXCEPTIONBOOLEAN
980 return v->toBoolean(exec);
983 int32_t DotAccessorNode::evaluateToInt32(ExecState* exec)
985 JSValue* v = inlineEvaluate(exec);
986 KJS_CHECKEXCEPTIONNUMBER
987 return v->toInt32(exec);
990 uint32_t DotAccessorNode::evaluateToUInt32(ExecState* exec)
992 JSValue* v = inlineEvaluate(exec);
993 KJS_CHECKEXCEPTIONNUMBER
994 return v->toUInt32(exec);
997 // ------------------------------ ArgumentListNode -----------------------------
999 void ArgumentListNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1002 nodeStack.append(m_next.get());
1004 nodeStack.append(m_expr.get());
1008 void ArgumentListNode::evaluateList(ExecState* exec, List& list)
1010 for (ArgumentListNode* n = this; n; n = n->m_next.get()) {
1011 JSValue* v = n->m_expr->evaluate(exec);
1012 KJS_CHECKEXCEPTIONVOID
1017 // ------------------------------ ArgumentsNode --------------------------------
1019 void ArgumentsNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1022 nodeStack.append(m_listNode.get());
1025 // ------------------------------ NewExprNode ----------------------------------
1027 void NewExprNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1030 nodeStack.append(m_args.get());
1031 nodeStack.append(m_expr.get());
1036 JSValue* NewExprNode::inlineEvaluate(ExecState* exec)
1038 JSValue* v = m_expr->evaluate(exec);
1039 KJS_CHECKEXCEPTIONVALUE
1043 m_args->evaluateList(exec, argList);
1044 KJS_CHECKEXCEPTIONVALUE
1048 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, m_expr.get());
1050 JSObject* constr = static_cast<JSObject*>(v);
1051 if (!constr->implementsConstruct())
1052 return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, m_expr.get());
1054 return constr->construct(exec, argList);
1057 JSValue* NewExprNode::evaluate(ExecState* exec)
1059 return inlineEvaluate(exec);
1062 double NewExprNode::evaluateToNumber(ExecState* exec)
1064 JSValue* v = inlineEvaluate(exec);
1065 KJS_CHECKEXCEPTIONNUMBER
1066 return v->toNumber(exec);
1069 bool NewExprNode::evaluateToBoolean(ExecState* exec)
1071 JSValue* v = inlineEvaluate(exec);
1072 KJS_CHECKEXCEPTIONBOOLEAN
1073 return v->toBoolean(exec);
1076 int32_t NewExprNode::evaluateToInt32(ExecState* exec)
1078 JSValue* v = inlineEvaluate(exec);
1079 KJS_CHECKEXCEPTIONNUMBER
1080 return v->toInt32(exec);
1083 uint32_t NewExprNode::evaluateToUInt32(ExecState* exec)
1085 JSValue* v = inlineEvaluate(exec);
1086 KJS_CHECKEXCEPTIONNUMBER
1087 return v->toUInt32(exec);
1090 template <ExpressionNode::CallerType callerType, bool scopeDepthIsZero>
1091 inline JSValue* ExpressionNode::resolveAndCall(ExecState* exec, const Identifier& ident, ArgumentsNode* args, size_t scopeDepth)
1093 const ScopeChain& chain = exec->scopeChain();
1094 ScopeChainIterator iter = chain.begin();
1095 ScopeChainIterator end = chain.end();
1097 if (!scopeDepthIsZero) {
1098 for (size_t i = 0; i < scopeDepth; ++iter, ++i)
1099 ASSERT(iter != chain.end());
1102 // we must always have something in the scope chain
1103 ASSERT(iter != end);
1109 if (base->getPropertySlot(exec, ident, slot)) {
1110 JSValue* v = slot.getValue(exec, base, ident);
1111 KJS_CHECKEXCEPTIONVALUE
1114 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
1116 JSObject* func = static_cast<JSObject*>(v);
1118 if (!func->implementsCall())
1119 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
1122 args->evaluateList(exec, argList);
1123 KJS_CHECKEXCEPTIONVALUE
1125 if (callerType == EvalOperator) {
1126 if (base == exec->lexicalGlobalObject() && func == exec->lexicalGlobalObject()->evalFunction()) {
1127 exec->dynamicGlobalObject()->tearOffActivation(exec);
1128 return eval(exec, exec->scopeChain(), exec->variableObject(), exec->dynamicGlobalObject(), exec->thisValue(), argList);
1132 JSObject* thisObj = base->toThisObject(exec);
1133 return func->call(exec, thisObj, argList);
1136 } while (iter != end);
1138 return throwUndefinedVariableError(exec, ident);
1141 void EvalFunctionCallNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1143 nodeStack.append(m_args.get());
1146 JSValue* EvalFunctionCallNode::evaluate(ExecState* exec)
1148 return resolveAndCall<EvalOperator, true>(exec, exec->propertyNames().eval, m_args.get());
1151 void FunctionCallValueNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1153 nodeStack.append(m_args.get());
1154 nodeStack.append(m_expr.get());
1158 JSValue* FunctionCallValueNode::evaluate(ExecState* exec)
1160 JSValue* v = m_expr->evaluate(exec);
1161 KJS_CHECKEXCEPTIONVALUE
1163 if (!v->isObject()) {
1164 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_expr.get());
1167 JSObject* func = static_cast<JSObject*>(v);
1169 if (!func->implementsCall()) {
1170 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_expr.get());
1174 m_args->evaluateList(exec, argList);
1175 KJS_CHECKEXCEPTIONVALUE
1177 JSObject* thisObj = exec->globalThisValue();
1178 return func->call(exec, thisObj, argList);
1181 void FunctionCallResolveNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
1183 nodeStack.append(m_args.get());
1186 size_t index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
1187 if (index != missingSymbolMarker()) {
1189 new (this) LocalVarFunctionCallNode(index);
1191 new (this) ScopedVarFunctionCallNode(index, depth);
1198 new (this) NonLocalVarFunctionCallNode(depth);
1202 JSValue* FunctionCallResolveNode::inlineEvaluate(ExecState* exec)
1204 // Check for missed optimization opportunity.
1205 ASSERT(!canSkipLookup(exec, m_ident));
1207 return resolveAndCall<FunctionCall, true>(exec, m_ident, m_args.get());
1210 JSValue* FunctionCallResolveNode::evaluate(ExecState* exec)
1212 return inlineEvaluate(exec);
1215 double FunctionCallResolveNode::evaluateToNumber(ExecState* exec)
1217 JSValue* v = inlineEvaluate(exec);
1218 KJS_CHECKEXCEPTIONNUMBER
1219 return v->toNumber(exec);
1222 bool FunctionCallResolveNode::evaluateToBoolean(ExecState* exec)
1224 JSValue* v = inlineEvaluate(exec);
1225 KJS_CHECKEXCEPTIONBOOLEAN
1226 return v->toBoolean(exec);
1229 int32_t FunctionCallResolveNode::evaluateToInt32(ExecState* exec)
1231 JSValue* v = inlineEvaluate(exec);
1232 KJS_CHECKEXCEPTIONNUMBER
1233 return v->toInt32(exec);
1236 uint32_t FunctionCallResolveNode::evaluateToUInt32(ExecState* exec)
1238 JSValue* v = inlineEvaluate(exec);
1239 KJS_CHECKEXCEPTIONNUMBER
1240 return v->toUInt32(exec);
1243 JSValue* LocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
1245 ASSERT(exec->variableObject() == exec->scopeChain().top());
1247 JSValue* v = exec->localStorage()[m_index].value;
1250 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
1252 JSObject* func = static_cast<JSObject*>(v);
1253 if (!func->implementsCall())
1254 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
1257 m_args->evaluateList(exec, argList);
1258 KJS_CHECKEXCEPTIONVALUE
1260 JSObject* thisObj = exec->globalThisValue();
1261 return func->call(exec, thisObj, argList);
1264 JSValue* LocalVarFunctionCallNode::evaluate(ExecState* exec)
1266 return inlineEvaluate(exec);
1269 double LocalVarFunctionCallNode::evaluateToNumber(ExecState* exec)
1271 JSValue* v = inlineEvaluate(exec);
1272 KJS_CHECKEXCEPTIONNUMBER
1273 return v->toNumber(exec);
1276 bool LocalVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
1278 JSValue* v = inlineEvaluate(exec);
1279 KJS_CHECKEXCEPTIONBOOLEAN
1280 return v->toBoolean(exec);
1283 int32_t LocalVarFunctionCallNode::evaluateToInt32(ExecState* exec)
1285 JSValue* v = inlineEvaluate(exec);
1286 KJS_CHECKEXCEPTIONNUMBER
1287 return v->toInt32(exec);
1290 uint32_t LocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
1292 JSValue* v = inlineEvaluate(exec);
1293 KJS_CHECKEXCEPTIONNUMBER
1294 return v->toUInt32(exec);
1297 JSValue* ScopedVarFunctionCallNode::inlineEvaluate(ExecState* exec)
1299 ASSERT(exec->variableObject() == exec->scopeChain().top());
1301 JSValue* v = getNonLocalSymbol(exec, m_index, m_scopeDepth);
1304 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
1306 JSObject* func = static_cast<JSObject*>(v);
1307 if (!func->implementsCall())
1308 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
1311 m_args->evaluateList(exec, argList);
1312 KJS_CHECKEXCEPTIONVALUE
1314 JSObject* thisObj = exec->globalThisValue();
1315 return func->call(exec, thisObj, argList);
1318 JSValue* ScopedVarFunctionCallNode::evaluate(ExecState* exec)
1320 return inlineEvaluate(exec);
1323 double ScopedVarFunctionCallNode::evaluateToNumber(ExecState* exec)
1325 JSValue* v = inlineEvaluate(exec);
1326 KJS_CHECKEXCEPTIONNUMBER
1327 return v->toNumber(exec);
1330 bool ScopedVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
1332 JSValue* v = inlineEvaluate(exec);
1333 KJS_CHECKEXCEPTIONBOOLEAN
1334 return v->toBoolean(exec);
1337 int32_t ScopedVarFunctionCallNode::evaluateToInt32(ExecState* exec)
1339 JSValue* v = inlineEvaluate(exec);
1340 KJS_CHECKEXCEPTIONNUMBER
1341 return v->toInt32(exec);
1344 uint32_t ScopedVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
1346 JSValue* v = inlineEvaluate(exec);
1347 KJS_CHECKEXCEPTIONNUMBER
1348 return v->toUInt32(exec);
1351 JSValue* NonLocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
1353 // Check for missed optimization opportunity.
1354 ASSERT(!canSkipLookup(exec, m_ident));
1356 return resolveAndCall<FunctionCall, false>(exec, m_ident, m_args.get(), m_scopeDepth);
1359 JSValue* NonLocalVarFunctionCallNode::evaluate(ExecState* exec)
1361 return inlineEvaluate(exec);
1364 double NonLocalVarFunctionCallNode::evaluateToNumber(ExecState* exec)
1366 JSValue* v = inlineEvaluate(exec);
1367 KJS_CHECKEXCEPTIONNUMBER
1368 return v->toNumber(exec);
1371 bool NonLocalVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
1373 JSValue* v = inlineEvaluate(exec);
1374 KJS_CHECKEXCEPTIONBOOLEAN
1375 return v->toBoolean(exec);
1378 int32_t NonLocalVarFunctionCallNode::evaluateToInt32(ExecState* exec)
1380 JSValue* v = inlineEvaluate(exec);
1381 KJS_CHECKEXCEPTIONNUMBER
1382 return v->toInt32(exec);
1385 uint32_t NonLocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
1387 JSValue* v = inlineEvaluate(exec);
1388 KJS_CHECKEXCEPTIONNUMBER
1389 return v->toUInt32(exec);
1392 void FunctionCallBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1394 nodeStack.append(m_args.get());
1395 nodeStack.append(m_subscript.get());
1396 nodeStack.append(m_base.get());
1400 JSValue* FunctionCallBracketNode::evaluate(ExecState* exec)
1402 JSValue* baseVal = m_base->evaluate(exec);
1403 KJS_CHECKEXCEPTIONVALUE
1405 JSValue* subscriptVal = m_subscript->evaluate(exec);
1407 JSObject* baseObj = baseVal->toObject(exec);
1412 if (subscriptVal->getUInt32(i)) {
1413 if (baseObj->getPropertySlot(exec, i, slot))
1414 funcVal = slot.getValue(exec, baseObj, i);
1416 funcVal = jsUndefined();
1418 Identifier ident(subscriptVal->toString(exec));
1419 if (baseObj->getPropertySlot(exec, ident, slot))
1420 funcVal = baseObj->get(exec, ident);
1422 funcVal = jsUndefined();
1425 KJS_CHECKEXCEPTIONVALUE
1427 if (!funcVal->isObject())
1428 return throwError(exec, TypeError, "Value %s (result of expression %s[%s]) is not object.", funcVal, m_base.get(), m_subscript.get());
1430 JSObject* func = static_cast<JSObject*>(funcVal);
1432 if (!func->implementsCall())
1433 return throwError(exec, TypeError, "Object %s (result of expression %s[%s]) does not allow calls.", funcVal, m_base.get(), m_subscript.get());
1436 m_args->evaluateList(exec, argList);
1437 KJS_CHECKEXCEPTIONVALUE
1439 JSObject* thisObj = baseObj;
1441 ASSERT(thisObj->isObject());
1442 ASSERT(!thisObj->isActivationObject());
1444 // No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
1445 return func->call(exec, thisObj, argList);
1448 static const char* dotExprNotAnObjectString() KJS_FAST_CALL;
1449 static const char* dotExprNotAnObjectString()
1451 return "Value %s (result of expression %s.%s) is not object.";
1454 static const char* dotExprDoesNotAllowCallsString() KJS_FAST_CALL;
1455 static const char* dotExprDoesNotAllowCallsString()
1457 return "Object %s (result of expression %s.%s) does not allow calls.";
1460 void FunctionCallDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1462 nodeStack.append(m_args.get());
1463 nodeStack.append(m_base.get());
1467 JSValue* FunctionCallDotNode::inlineEvaluate(ExecState* exec)
1469 JSValue* baseVal = m_base->evaluate(exec);
1470 KJS_CHECKEXCEPTIONVALUE
1472 JSObject* baseObj = baseVal->toObject(exec);
1474 JSValue* funcVal = baseObj->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, baseObj, m_ident) : jsUndefined();
1475 KJS_CHECKEXCEPTIONVALUE
1477 if (!funcVal->isObject())
1478 return throwError(exec, TypeError, dotExprNotAnObjectString(), funcVal, m_base.get(), m_ident);
1480 JSObject* func = static_cast<JSObject*>(funcVal);
1482 if (!func->implementsCall())
1483 return throwError(exec, TypeError, dotExprDoesNotAllowCallsString(), funcVal, m_base.get(), m_ident);
1486 m_args->evaluateList(exec, argList);
1487 KJS_CHECKEXCEPTIONVALUE
1489 JSObject* thisObj = baseObj;
1491 ASSERT(thisObj->isObject());
1492 ASSERT(!thisObj->isActivationObject());
1494 // No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
1495 return func->call(exec, thisObj, argList);
1498 JSValue* FunctionCallDotNode::evaluate(ExecState* exec)
1500 return inlineEvaluate(exec);
1503 double FunctionCallDotNode::evaluateToNumber(ExecState* exec)
1505 JSValue* v = inlineEvaluate(exec);
1506 KJS_CHECKEXCEPTIONNUMBER
1507 return v->toNumber(exec);
1510 bool FunctionCallDotNode::evaluateToBoolean(ExecState* exec)
1512 JSValue* v = inlineEvaluate(exec);
1513 KJS_CHECKEXCEPTIONBOOLEAN
1514 return v->toBoolean(exec);
1517 int32_t FunctionCallDotNode::evaluateToInt32(ExecState* exec)
1519 JSValue* v = inlineEvaluate(exec);
1520 KJS_CHECKEXCEPTIONNUMBER
1521 return v->toInt32(exec);
1524 uint32_t FunctionCallDotNode::evaluateToUInt32(ExecState* exec)
1526 JSValue* v = inlineEvaluate(exec);
1527 KJS_CHECKEXCEPTIONNUMBER
1528 return v->toUInt32(exec);
1533 // ------------------------------ PostfixResolveNode ----------------------------------
1536 void PostIncResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
1538 size_t index = symbolTable.get(m_ident.ustring().rep());
1539 if (index != missingSymbolMarker()) {
1540 if (isConstant(localStorage, index))
1541 new (this) PostIncConstNode(index);
1543 new (this) PostIncLocalVarNode(index);
1547 JSValue* PostIncResolveNode::evaluate(ExecState* exec)
1549 // Check for missed optimization opportunity.
1550 ASSERT(!canSkipLookup(exec, m_ident));
1552 const ScopeChain& chain = exec->scopeChain();
1553 ScopeChainIterator iter = chain.begin();
1554 ScopeChainIterator end = chain.end();
1556 // we must always have something in the scope chain
1557 ASSERT(iter != end);
1561 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
1562 // If m_ident is 'arguments', the base->getPropertySlot() may cause
1563 // base (which must be an ActivationImp in such this case) to be torn
1564 // off from the activation stack, in which case we need to get it again
1565 // from the ScopeChainIterator.
1567 JSObject* base = *iter;
1568 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
1569 base->put(exec, m_ident, jsNumber(v->toNumber(exec) + 1));
1574 } while (iter != end);
1576 return throwUndefinedVariableError(exec, m_ident);
1579 void PostIncResolveNode::optimizeForUnnecessaryResult()
1581 new (this) PreIncResolveNode(PlacementNewAdopt);
1584 JSValue* PostIncLocalVarNode::evaluate(ExecState* exec)
1586 ASSERT(exec->variableObject() == exec->scopeChain().top());
1588 JSValue** slot = &exec->localStorage()[m_index].value;
1589 JSValue* v = (*slot)->toJSNumber(exec);
1590 *slot = jsNumber(v->toNumber(exec) + 1);
1594 void PostIncLocalVarNode::optimizeForUnnecessaryResult()
1596 new (this) PreIncLocalVarNode(m_index);
1600 void PostDecResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
1602 size_t index = symbolTable.get(m_ident.ustring().rep());
1603 if (index != missingSymbolMarker()) {
1604 if (isConstant(localStorage, index))
1605 new (this) PostDecConstNode(index);
1607 new (this) PostDecLocalVarNode(index);
1611 JSValue* PostDecResolveNode::evaluate(ExecState* exec)
1613 // Check for missed optimization opportunity.
1614 ASSERT(!canSkipLookup(exec, m_ident));
1616 const ScopeChain& chain = exec->scopeChain();
1617 ScopeChainIterator iter = chain.begin();
1618 ScopeChainIterator end = chain.end();
1620 // we must always have something in the scope chain
1621 ASSERT(iter != end);
1625 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
1626 // See the comment in PostIncResolveNode::evaluate().
1628 JSObject* base = *iter;
1629 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
1630 base->put(exec, m_ident, jsNumber(v->toNumber(exec) - 1));
1635 } while (iter != end);
1637 return throwUndefinedVariableError(exec, m_ident);
1640 void PostDecResolveNode::optimizeForUnnecessaryResult()
1642 new (this) PreDecResolveNode(PlacementNewAdopt);
1645 JSValue* PostDecLocalVarNode::evaluate(ExecState* exec)
1647 ASSERT(exec->variableObject() == exec->scopeChain().top());
1649 JSValue** slot = &exec->localStorage()[m_index].value;
1650 JSValue* v = (*slot)->toJSNumber(exec);
1651 *slot = jsNumber(v->toNumber(exec) - 1);
1655 double PostDecLocalVarNode::inlineEvaluateToNumber(ExecState* exec)
1657 ASSERT(exec->variableObject() == exec->scopeChain().top());
1659 JSValue** slot = &exec->localStorage()[m_index].value;
1660 double n = (*slot)->toNumber(exec);
1661 *slot = jsNumber(n - 1);
1665 double PostDecLocalVarNode::evaluateToNumber(ExecState* exec)
1667 return inlineEvaluateToNumber(exec);
1670 bool PostDecLocalVarNode::evaluateToBoolean(ExecState* exec)
1672 double result = inlineEvaluateToNumber(exec);
1673 return result > 0.0 || 0.0 > result; // NaN produces false as well
1676 int32_t PostDecLocalVarNode::evaluateToInt32(ExecState* exec)
1678 return JSValue::toInt32(inlineEvaluateToNumber(exec));
1681 uint32_t PostDecLocalVarNode::evaluateToUInt32(ExecState* exec)
1683 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
1686 void PostDecLocalVarNode::optimizeForUnnecessaryResult()
1688 new (this) PreDecLocalVarNode(m_index);
1691 // ------------------------------ PostfixBracketNode ----------------------------------
1693 void PostfixBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1695 nodeStack.append(m_subscript.get());
1696 nodeStack.append(m_base.get());
1699 JSValue* PostIncBracketNode::evaluate(ExecState* exec)
1701 JSValue* baseValue = m_base->evaluate(exec);
1702 KJS_CHECKEXCEPTIONVALUE
1703 JSValue* subscript = m_subscript->evaluate(exec);
1704 KJS_CHECKEXCEPTIONVALUE
1706 JSObject* base = baseValue->toObject(exec);
1708 uint32_t propertyIndex;
1709 if (subscript->getUInt32(propertyIndex)) {
1711 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1712 KJS_CHECKEXCEPTIONVALUE
1714 JSValue* v2 = v->toJSNumber(exec);
1715 base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) + 1));
1720 Identifier propertyName(subscript->toString(exec));
1722 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1723 KJS_CHECKEXCEPTIONVALUE
1725 JSValue* v2 = v->toJSNumber(exec);
1726 base->put(exec, propertyName, jsNumber(v2->toNumber(exec) + 1));
1730 JSValue* PostDecBracketNode::evaluate(ExecState* exec)
1732 JSValue* baseValue = m_base->evaluate(exec);
1733 KJS_CHECKEXCEPTIONVALUE
1734 JSValue* subscript = m_subscript->evaluate(exec);
1735 KJS_CHECKEXCEPTIONVALUE
1737 JSObject* base = baseValue->toObject(exec);
1739 uint32_t propertyIndex;
1740 if (subscript->getUInt32(propertyIndex)) {
1742 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1743 KJS_CHECKEXCEPTIONVALUE
1745 JSValue* v2 = v->toJSNumber(exec);
1746 base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) - 1));
1750 Identifier propertyName(subscript->toString(exec));
1752 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1753 KJS_CHECKEXCEPTIONVALUE
1755 JSValue* v2 = v->toJSNumber(exec);
1756 base->put(exec, propertyName, jsNumber(v2->toNumber(exec) - 1));
1760 // ------------------------------ PostfixDotNode ----------------------------------
1762 void PostfixDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1764 nodeStack.append(m_base.get());
1767 JSValue* PostIncDotNode::evaluate(ExecState* exec)
1769 JSValue* baseValue = m_base->evaluate(exec);
1770 KJS_CHECKEXCEPTIONVALUE
1771 JSObject* base = baseValue->toObject(exec);
1774 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1775 KJS_CHECKEXCEPTIONVALUE
1777 JSValue* v2 = v->toJSNumber(exec);
1778 base->put(exec, m_ident, jsNumber(v2->toNumber(exec) + 1));
1782 JSValue* PostDecDotNode::evaluate(ExecState* exec)
1784 JSValue* baseValue = m_base->evaluate(exec);
1785 KJS_CHECKEXCEPTIONVALUE
1786 JSObject* base = baseValue->toObject(exec);
1789 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1790 KJS_CHECKEXCEPTIONVALUE
1792 JSValue* v2 = v->toJSNumber(exec);
1793 base->put(exec, m_ident, jsNumber(v2->toNumber(exec) - 1));
1797 // ------------------------------ PostfixErrorNode -----------------------------------
1799 JSValue* PostfixErrorNode::evaluate(ExecState* exec)
1801 throwError(exec, ReferenceError, "Postfix %s operator applied to value that is not a reference.",
1802 m_operator == OpPlusPlus ? "++" : "--");
1803 handleException(exec);
1804 return jsUndefined();
1807 // ------------------------------ DeleteResolveNode -----------------------------------
1809 void DeleteResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
1811 size_t index = symbolTable.get(m_ident.ustring().rep());
1812 if (index != missingSymbolMarker())
1813 new (this) LocalVarDeleteNode();
1818 JSValue* DeleteResolveNode::evaluate(ExecState* exec)
1820 // Check for missed optimization opportunity.
1821 ASSERT(!canSkipLookup(exec, m_ident));
1823 const ScopeChain& chain = exec->scopeChain();
1824 ScopeChainIterator iter = chain.begin();
1825 ScopeChainIterator end = chain.end();
1827 // We must always have something in the scope chain
1828 ASSERT(iter != end);
1834 if (base->getPropertySlot(exec, m_ident, slot))
1835 return jsBoolean(base->deleteProperty(exec, m_ident));
1838 } while (iter != end);
1840 return jsBoolean(true);
1843 JSValue* LocalVarDeleteNode::evaluate(ExecState*)
1845 return jsBoolean(false);
1848 // ------------------------------ DeleteBracketNode -----------------------------------
1850 void DeleteBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1852 nodeStack.append(m_subscript.get());
1853 nodeStack.append(m_base.get());
1856 JSValue* DeleteBracketNode::evaluate(ExecState* exec)
1858 JSValue* baseValue = m_base->evaluate(exec);
1859 KJS_CHECKEXCEPTIONVALUE
1860 JSValue* subscript = m_subscript->evaluate(exec);
1861 KJS_CHECKEXCEPTIONVALUE
1863 JSObject* base = baseValue->toObject(exec);
1865 uint32_t propertyIndex;
1866 if (subscript->getUInt32(propertyIndex))
1867 return jsBoolean(base->deleteProperty(exec, propertyIndex));
1869 Identifier propertyName(subscript->toString(exec));
1870 return jsBoolean(base->deleteProperty(exec, propertyName));
1873 // ------------------------------ DeleteDotNode -----------------------------------
1875 void DeleteDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1877 nodeStack.append(m_base.get());
1880 JSValue* DeleteDotNode::evaluate(ExecState* exec)
1882 JSValue* baseValue = m_base->evaluate(exec);
1883 JSObject* base = baseValue->toObject(exec);
1884 KJS_CHECKEXCEPTIONVALUE
1886 return jsBoolean(base->deleteProperty(exec, m_ident));
1889 // ------------------------------ DeleteValueNode -----------------------------------
1891 void DeleteValueNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1893 nodeStack.append(m_expr.get());
1896 JSValue* DeleteValueNode::evaluate(ExecState* exec)
1898 m_expr->evaluate(exec);
1899 KJS_CHECKEXCEPTIONVALUE
1901 // delete on a non-location expression ignores the value and returns true
1902 return jsBoolean(true);
1905 // ------------------------------ VoidNode -------------------------------------
1907 void VoidNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1909 nodeStack.append(m_expr.get());
1913 JSValue* VoidNode::evaluate(ExecState* exec)
1915 m_expr->evaluate(exec);
1916 KJS_CHECKEXCEPTIONVALUE
1918 return jsUndefined();
1923 // ------------------------------ TypeOfValueNode -----------------------------------
1925 void TypeOfValueNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1927 nodeStack.append(m_expr.get());
1930 static JSValue* typeStringForValue(JSValue* v) KJS_FAST_CALL;
1931 static JSValue* typeStringForValue(JSValue* v)
1933 switch (v->type()) {
1935 return jsString("undefined");
1937 return jsString("object");
1939 return jsString("boolean");
1941 return jsString("number");
1943 return jsString("string");
1945 if (v->isObject()) {
1946 // Return "undefined" for objects that should be treated
1947 // as null when doing comparisons.
1948 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
1949 return jsString("undefined");
1950 else if (static_cast<JSObject*>(v)->implementsCall())
1951 return jsString("function");
1954 return jsString("object");
1958 void TypeOfResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
1960 size_t index = symbolTable.get(m_ident.ustring().rep());
1961 if (index != missingSymbolMarker())
1962 new (this) LocalVarTypeOfNode(index);
1965 JSValue* LocalVarTypeOfNode::evaluate(ExecState* exec)
1967 ASSERT(exec->variableObject() == exec->scopeChain().top());
1969 return typeStringForValue(exec->localStorage()[m_index].value);
1972 JSValue* TypeOfResolveNode::evaluate(ExecState* exec)
1974 const ScopeChain& chain = exec->scopeChain();
1975 ScopeChainIterator iter = chain.begin();
1976 ScopeChainIterator end = chain.end();
1978 // We must always have something in the scope chain
1979 ASSERT(iter != end);
1985 if (base->getPropertySlot(exec, m_ident, slot)) {
1986 JSValue* v = slot.getValue(exec, base, m_ident);
1987 return typeStringForValue(v);
1991 } while (iter != end);
1993 return jsString("undefined");
1996 // ------------------------------ TypeOfValueNode -----------------------------------
1998 JSValue* TypeOfValueNode::evaluate(ExecState* exec)
2000 JSValue* v = m_expr->evaluate(exec);
2001 KJS_CHECKEXCEPTIONVALUE
2003 return typeStringForValue(v);
2006 // ECMA 11.4.4 and 11.4.5
2008 // ------------------------------ PrefixResolveNode ----------------------------------
2010 void PreIncResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
2012 size_t index = symbolTable.get(m_ident.ustring().rep());
2013 if (index != missingSymbolMarker()) {
2014 if (isConstant(localStorage, index))
2015 new (this) PreIncConstNode(index);
2017 new (this) PreIncLocalVarNode(index);
2021 JSValue* PreIncLocalVarNode::evaluate(ExecState* exec)
2023 ASSERT(exec->variableObject() == exec->scopeChain().top());
2024 JSValue** slot = &exec->localStorage()[m_index].value;
2026 double n = (*slot)->toNumber(exec);
2027 JSValue* n2 = jsNumber(n + 1);
2032 JSValue* PreIncResolveNode::evaluate(ExecState* exec)
2034 const ScopeChain& chain = exec->scopeChain();
2035 ScopeChainIterator iter = chain.begin();
2036 ScopeChainIterator end = chain.end();
2038 // we must always have something in the scope chain
2039 ASSERT(iter != end);
2043 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
2044 // See the comment in PostIncResolveNode::evaluate().
2046 JSObject* base = *iter;
2047 JSValue* v = slot.getValue(exec, base, m_ident);
2049 double n = v->toNumber(exec);
2050 JSValue* n2 = jsNumber(n + 1);
2051 base->put(exec, m_ident, n2);
2057 } while (iter != end);
2059 return throwUndefinedVariableError(exec, m_ident);
2062 void PreDecResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
2064 size_t index = symbolTable.get(m_ident.ustring().rep());
2065 if (index != missingSymbolMarker()) {
2066 if (isConstant(localStorage, index))
2067 new (this) PreDecConstNode(index);
2069 new (this) PreDecLocalVarNode(index);
2073 JSValue* PreDecLocalVarNode::evaluate(ExecState* exec)
2075 ASSERT(exec->variableObject() == exec->scopeChain().top());
2076 JSValue** slot = &exec->localStorage()[m_index].value;
2078 double n = (*slot)->toNumber(exec);
2079 JSValue* n2 = jsNumber(n - 1);
2084 JSValue* PreDecResolveNode::evaluate(ExecState* exec)
2086 const ScopeChain& chain = exec->scopeChain();
2087 ScopeChainIterator iter = chain.begin();
2088 ScopeChainIterator end = chain.end();
2090 // we must always have something in the scope chain
2091 ASSERT(iter != end);
2095 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
2096 // See the comment in PostIncResolveNode::evaluate().
2098 JSObject* base = *iter;
2099 JSValue* v = slot.getValue(exec, base, m_ident);
2101 double n = v->toNumber(exec);
2102 JSValue* n2 = jsNumber(n - 1);
2103 base->put(exec, m_ident, n2);
2109 } while (iter != end);
2111 return throwUndefinedVariableError(exec, m_ident);
2114 // ------------------------------ PreIncConstNode ----------------------------------
2116 JSValue* PreIncConstNode::evaluate(ExecState* exec)
2118 ASSERT(exec->variableObject() == exec->scopeChain().top());
2119 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) + 1);
2122 // ------------------------------ PreDecConstNode ----------------------------------
2124 JSValue* PreDecConstNode::evaluate(ExecState* exec)
2126 ASSERT(exec->variableObject() == exec->scopeChain().top());
2127 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) - 1);
2130 // ------------------------------ PostIncConstNode ----------------------------------
2132 JSValue* PostIncConstNode::evaluate(ExecState* exec)
2134 ASSERT(exec->variableObject() == exec->scopeChain().top());
2135 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
2138 // ------------------------------ PostDecConstNode ----------------------------------
2140 JSValue* PostDecConstNode::evaluate(ExecState* exec)
2142 ASSERT(exec->variableObject() == exec->scopeChain().top());
2143 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
2146 // ------------------------------ PrefixBracketNode ----------------------------------
2148 void PrefixBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2150 nodeStack.append(m_subscript.get());
2151 nodeStack.append(m_base.get());
2154 JSValue* PreIncBracketNode::evaluate(ExecState* exec)
2156 JSValue* baseValue = m_base->evaluate(exec);
2157 KJS_CHECKEXCEPTIONVALUE
2158 JSValue* subscript = m_subscript->evaluate(exec);
2159 KJS_CHECKEXCEPTIONVALUE
2161 JSObject* base = baseValue->toObject(exec);
2163 uint32_t propertyIndex;
2164 if (subscript->getUInt32(propertyIndex)) {
2166 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2167 KJS_CHECKEXCEPTIONVALUE
2169 JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
2170 base->put(exec, propertyIndex, n2);
2175 Identifier propertyName(subscript->toString(exec));
2177 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2178 KJS_CHECKEXCEPTIONVALUE
2180 JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
2181 base->put(exec, propertyName, n2);
2186 JSValue* PreDecBracketNode::evaluate(ExecState* exec)
2188 JSValue* baseValue = m_base->evaluate(exec);
2189 KJS_CHECKEXCEPTIONVALUE
2190 JSValue* subscript = m_subscript->evaluate(exec);
2191 KJS_CHECKEXCEPTIONVALUE
2193 JSObject* base = baseValue->toObject(exec);
2195 uint32_t propertyIndex;
2196 if (subscript->getUInt32(propertyIndex)) {
2198 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2199 KJS_CHECKEXCEPTIONVALUE
2201 JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
2202 base->put(exec, propertyIndex, n2);
2207 Identifier propertyName(subscript->toString(exec));
2209 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2210 KJS_CHECKEXCEPTIONVALUE
2212 JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
2213 base->put(exec, propertyName, n2);
2218 // ------------------------------ PrefixDotNode ----------------------------------
2220 void PrefixDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2222 nodeStack.append(m_base.get());
2225 JSValue* PreIncDotNode::evaluate(ExecState* exec)
2227 JSValue* baseValue = m_base->evaluate(exec);
2228 KJS_CHECKEXCEPTIONVALUE
2229 JSObject* base = baseValue->toObject(exec);
2232 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2233 KJS_CHECKEXCEPTIONVALUE
2235 double n = v->toNumber(exec);
2236 JSValue* n2 = jsNumber(n + 1);
2237 base->put(exec, m_ident, n2);
2242 JSValue* PreDecDotNode::evaluate(ExecState* exec)
2244 JSValue* baseValue = m_base->evaluate(exec);
2245 KJS_CHECKEXCEPTIONVALUE
2246 JSObject* base = baseValue->toObject(exec);
2249 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2250 KJS_CHECKEXCEPTIONVALUE
2252 double n = v->toNumber(exec);
2253 JSValue* n2 = jsNumber(n - 1);
2254 base->put(exec, m_ident, n2);
2259 // ------------------------------ PrefixErrorNode -----------------------------------
2261 JSValue* PrefixErrorNode::evaluate(ExecState* exec)
2263 throwError(exec, ReferenceError, "Prefix %s operator applied to value that is not a reference.",
2264 m_operator == OpPlusPlus ? "++" : "--");
2265 handleException(exec);
2266 return jsUndefined();
2269 // ------------------------------ UnaryPlusNode --------------------------------
2271 void UnaryPlusNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2273 nodeStack.append(m_expr.get());
2277 JSValue* UnaryPlusNode::evaluate(ExecState* exec)
2279 JSValue* v = m_expr->evaluate(exec);
2280 KJS_CHECKEXCEPTIONVALUE
2281 return v->toJSNumber(exec);
2284 bool UnaryPlusNode::evaluateToBoolean(ExecState* exec)
2286 return m_expr->evaluateToBoolean(exec);
2289 double UnaryPlusNode::evaluateToNumber(ExecState* exec)
2291 return m_expr->evaluateToNumber(exec);
2294 int32_t UnaryPlusNode::evaluateToInt32(ExecState* exec)
2296 return m_expr->evaluateToInt32(exec);
2299 uint32_t UnaryPlusNode::evaluateToUInt32(ExecState* exec)
2301 return m_expr->evaluateToInt32(exec);
2304 // ------------------------------ NegateNode -----------------------------------
2306 void NegateNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2308 nodeStack.append(m_expr.get());
2312 JSValue* NegateNode::evaluate(ExecState* exec)
2314 // No need to check exception, caller will do so right after evaluate()
2315 return jsNumber(-m_expr->evaluateToNumber(exec));
2318 double NegateNode::evaluateToNumber(ExecState* exec)
2320 // No need to check exception, caller will do so right after evaluateToNumber()
2321 return -m_expr->evaluateToNumber(exec);
2324 // ------------------------------ BitwiseNotNode -------------------------------
2326 void BitwiseNotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2328 nodeStack.append(m_expr.get());
2332 int32_t BitwiseNotNode::inlineEvaluateToInt32(ExecState* exec)
2334 return ~m_expr->evaluateToInt32(exec);
2337 JSValue* BitwiseNotNode::evaluate(ExecState* exec)
2339 return jsNumber(inlineEvaluateToInt32(exec));
2342 double BitwiseNotNode::evaluateToNumber(ExecState* exec)
2344 return inlineEvaluateToInt32(exec);
2347 bool BitwiseNotNode::evaluateToBoolean(ExecState* exec)
2349 return inlineEvaluateToInt32(exec);
2352 int32_t BitwiseNotNode::evaluateToInt32(ExecState* exec)
2354 return inlineEvaluateToInt32(exec);
2357 uint32_t BitwiseNotNode::evaluateToUInt32(ExecState* exec)
2359 return inlineEvaluateToInt32(exec);
2362 // ------------------------------ LogicalNotNode -------------------------------
2364 void LogicalNotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2366 nodeStack.append(m_expr.get());
2370 JSValue* LogicalNotNode::evaluate(ExecState* exec)
2372 return jsBoolean(!m_expr->evaluateToBoolean(exec));
2375 bool LogicalNotNode::evaluateToBoolean(ExecState* exec)
2377 return !m_expr->evaluateToBoolean(exec);
2380 // ------------------------------ Multiplicative Nodes -----------------------------------
2382 void MultNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2384 nodeStack.append(m_term1.get());
2385 nodeStack.append(m_term2.get());
2389 double MultNode::inlineEvaluateToNumber(ExecState* exec)
2391 double n1 = m_term1->evaluateToNumber(exec);
2392 KJS_CHECKEXCEPTIONNUMBER
2393 double n2 = m_term2->evaluateToNumber(exec);
2397 JSValue* MultNode::evaluate(ExecState* exec)
2399 return jsNumber(inlineEvaluateToNumber(exec));
2402 double MultNode::evaluateToNumber(ExecState* exec)
2404 return inlineEvaluateToNumber(exec);
2407 bool MultNode::evaluateToBoolean(ExecState* exec)
2409 double result = inlineEvaluateToNumber(exec);
2410 return result > 0.0 || 0.0 > result; // NaN produces false as well
2413 int32_t MultNode::evaluateToInt32(ExecState* exec)
2415 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2418 uint32_t MultNode::evaluateToUInt32(ExecState* exec)
2420 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2423 void DivNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2425 nodeStack.append(m_term1.get());
2426 nodeStack.append(m_term2.get());
2430 double DivNode::inlineEvaluateToNumber(ExecState* exec)
2432 double n1 = m_term1->evaluateToNumber(exec);
2433 KJS_CHECKEXCEPTIONNUMBER
2434 double n2 = m_term2->evaluateToNumber(exec);
2438 JSValue* DivNode::evaluate(ExecState* exec)
2440 return jsNumber(inlineEvaluateToNumber(exec));
2443 double DivNode::evaluateToNumber(ExecState* exec)
2445 return inlineEvaluateToNumber(exec);
2448 int32_t DivNode::evaluateToInt32(ExecState* exec)
2450 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2453 uint32_t DivNode::evaluateToUInt32(ExecState* exec)
2455 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2458 void ModNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2460 nodeStack.append(m_term1.get());
2461 nodeStack.append(m_term2.get());
2465 double ModNode::inlineEvaluateToNumber(ExecState* exec)
2467 double n1 = m_term1->evaluateToNumber(exec);
2468 KJS_CHECKEXCEPTIONNUMBER
2469 double n2 = m_term2->evaluateToNumber(exec);
2470 return fmod(n1, n2);
2473 JSValue* ModNode::evaluate(ExecState* exec)
2475 return jsNumber(inlineEvaluateToNumber(exec));
2478 double ModNode::evaluateToNumber(ExecState* exec)
2480 return inlineEvaluateToNumber(exec);
2483 bool ModNode::evaluateToBoolean(ExecState* exec)
2485 double result = inlineEvaluateToNumber(exec);
2486 return result > 0.0 || 0.0 > result; // NaN produces false as well
2489 int32_t ModNode::evaluateToInt32(ExecState* exec)
2491 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2494 uint32_t ModNode::evaluateToUInt32(ExecState* exec)
2496 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2499 // ------------------------------ Additive Nodes --------------------------------------
2501 static JSValue* throwOutOfMemoryError(ExecState* exec)
2503 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
2504 exec->setException(error);
2508 static double throwOutOfMemoryErrorToNumber(ExecState* exec)
2510 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
2511 exec->setException(error);
2516 static JSValue* addSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
2518 // exception for the Date exception in defaultValue()
2519 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
2520 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
2522 if (p1->isString() || p2->isString()) {
2523 UString value = p1->toString(exec) + p2->toString(exec);
2525 return throwOutOfMemoryError(exec);
2526 return jsString(value);
2529 return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
2532 static double addSlowCaseToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
2534 // exception for the Date exception in defaultValue()
2535 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
2536 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
2538 if (p1->isString() || p2->isString()) {
2539 UString value = p1->toString(exec) + p2->toString(exec);
2541 return throwOutOfMemoryErrorToNumber(exec);
2542 return value.toDouble();
2545 return p1->toNumber(exec) + p2->toNumber(exec);
2548 // Fast-path choices here are based on frequency data from SunSpider:
2549 // <times> Add case: <t1> <t2>
2550 // ---------------------------
2551 // 5627160 Add case: 1 1
2552 // 247427 Add case: 5 5
2553 // 20901 Add case: 5 6
2554 // 13978 Add case: 5 1
2555 // 4000 Add case: 1 5
2558 static inline JSValue* add(ExecState* exec, JSValue* v1, JSValue* v2)
2560 JSType t1 = v1->type();
2561 JSType t2 = v2->type();
2562 const unsigned bothTypes = (t1 << 3) | t2;
2564 if (bothTypes == ((NumberType << 3) | NumberType))
2565 return jsNumber(v1->toNumber(exec) + v2->toNumber(exec));
2566 if (bothTypes == ((StringType << 3) | StringType)) {
2567 UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
2569 return throwOutOfMemoryError(exec);
2570 return jsString(value);
2573 // All other cases are pretty uncommon
2574 return addSlowCase(exec, v1, v2);
2577 static inline double addToNumber(ExecState* exec, JSValue* v1, JSValue* v2)
2579 JSType t1 = v1->type();
2580 JSType t2 = v2->type();
2581 const unsigned bothTypes = (t1 << 3) | t2;
2583 if (bothTypes == ((NumberType << 3) | NumberType))
2584 return v1->toNumber(exec) + v2->toNumber(exec);
2585 if (bothTypes == ((StringType << 3) | StringType)) {
2586 UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
2588 return throwOutOfMemoryErrorToNumber(exec);
2589 return value.toDouble();
2592 // All other cases are pretty uncommon
2593 return addSlowCaseToNumber(exec, v1, v2);
2596 void AddNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2598 nodeStack.append(m_term1.get());
2599 nodeStack.append(m_term2.get());
2603 JSValue* AddNode::evaluate(ExecState* exec)
2605 JSValue* v1 = m_term1->evaluate(exec);
2606 KJS_CHECKEXCEPTIONVALUE
2608 JSValue* v2 = m_term2->evaluate(exec);
2609 KJS_CHECKEXCEPTIONVALUE
2611 return add(exec, v1, v2);
2614 double AddNode::inlineEvaluateToNumber(ExecState* exec)
2616 JSValue* v1 = m_term1->evaluate(exec);
2617 KJS_CHECKEXCEPTIONNUMBER
2619 JSValue* v2 = m_term2->evaluate(exec);
2620 KJS_CHECKEXCEPTIONNUMBER
2622 return addToNumber(exec, v1, v2);
2625 double AddNode::evaluateToNumber(ExecState* exec)
2627 return inlineEvaluateToNumber(exec);
2630 int32_t AddNode::evaluateToInt32(ExecState* exec)
2632 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2635 uint32_t AddNode::evaluateToUInt32(ExecState* exec)
2637 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2640 double AddNumbersNode::inlineEvaluateToNumber(ExecState* exec)
2642 double n1 = m_term1->evaluateToNumber(exec);
2643 KJS_CHECKEXCEPTIONNUMBER
2644 double n2 = m_term2->evaluateToNumber(exec);
2648 JSValue* AddNumbersNode::evaluate(ExecState* exec)
2650 return jsNumber(inlineEvaluateToNumber(exec));
2653 double AddNumbersNode::evaluateToNumber(ExecState* exec)
2655 return inlineEvaluateToNumber(exec);
2658 int32_t AddNumbersNode::evaluateToInt32(ExecState* exec)
2660 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2663 uint32_t AddNumbersNode::evaluateToUInt32(ExecState* exec)
2665 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2668 JSValue* AddStringsNode::evaluate(ExecState* exec)
2670 JSValue* v1 = m_term1->evaluate(exec);
2671 KJS_CHECKEXCEPTIONVALUE
2673 JSValue* v2 = m_term2->evaluate(exec);
2674 KJS_CHECKEXCEPTIONVALUE
2676 return jsString(static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value());
2679 JSValue* AddStringLeftNode::evaluate(ExecState* exec)
2681 JSValue* v1 = m_term1->evaluate(exec);
2682 KJS_CHECKEXCEPTIONVALUE
2684 JSValue* v2 = m_term2->evaluate(exec);
2685 KJS_CHECKEXCEPTIONVALUE
2687 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
2688 return jsString(static_cast<StringImp*>(v1)->value() + p2->toString(exec));
2691 JSValue* AddStringRightNode::evaluate(ExecState* exec)
2693 JSValue* v1 = m_term1->evaluate(exec);
2694 KJS_CHECKEXCEPTIONVALUE
2696 JSValue* v2 = m_term2->evaluate(exec);
2697 KJS_CHECKEXCEPTIONVALUE
2699 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
2700 return jsString(p1->toString(exec) + static_cast<StringImp*>(v2)->value());
2703 void SubNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2705 nodeStack.append(m_term1.get());
2706 nodeStack.append(m_term2.get());
2710 double SubNode::inlineEvaluateToNumber(ExecState* exec)
2712 double n1 = m_term1->evaluateToNumber(exec);
2713 KJS_CHECKEXCEPTIONNUMBER
2714 double n2 = m_term2->evaluateToNumber(exec);
2718 JSValue* SubNode::evaluate(ExecState* exec)
2720 return jsNumber(inlineEvaluateToNumber(exec));
2723 double SubNode::evaluateToNumber(ExecState* exec)
2725 return inlineEvaluateToNumber(exec);
2728 int32_t SubNode::evaluateToInt32(ExecState* exec)
2730 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2733 uint32_t SubNode::evaluateToUInt32(ExecState* exec)
2735 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2738 // ------------------------------ Shift Nodes ------------------------------------
2740 void LeftShiftNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2742 nodeStack.append(m_term1.get());
2743 nodeStack.append(m_term2.get());
2747 int32_t LeftShiftNode::inlineEvaluateToInt32(ExecState* exec)
2749 int i1 = m_term1->evaluateToInt32(exec);
2750 KJS_CHECKEXCEPTIONNUMBER
2751 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
2755 JSValue* LeftShiftNode::evaluate(ExecState* exec)
2757 return jsNumber(inlineEvaluateToInt32(exec));
2760 double LeftShiftNode::evaluateToNumber(ExecState* exec)
2762 return inlineEvaluateToInt32(exec);
2765 int32_t LeftShiftNode::evaluateToInt32(ExecState* exec)
2767 return inlineEvaluateToInt32(exec);
2770 uint32_t LeftShiftNode::evaluateToUInt32(ExecState* exec)
2772 return inlineEvaluateToInt32(exec);
2775 void RightShiftNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2777 nodeStack.append(m_term1.get());
2778 nodeStack.append(m_term2.get());
2782 int32_t RightShiftNode::inlineEvaluateToInt32(ExecState* exec)
2784 int i1 = m_term1->evaluateToInt32(exec);
2785 KJS_CHECKEXCEPTIONNUMBER
2786 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
2790 JSValue* RightShiftNode::evaluate(ExecState* exec)
2792 return jsNumber(inlineEvaluateToInt32(exec));
2795 double RightShiftNode::evaluateToNumber(ExecState* exec)
2797 return inlineEvaluateToInt32(exec);
2800 int32_t RightShiftNode::evaluateToInt32(ExecState* exec)
2802 return inlineEvaluateToInt32(exec);
2805 uint32_t RightShiftNode::evaluateToUInt32(ExecState* exec)
2807 return inlineEvaluateToInt32(exec);
2810 void UnsignedRightShiftNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2812 nodeStack.append(m_term1.get());
2813 nodeStack.append(m_term2.get());
2817 uint32_t UnsignedRightShiftNode::inlineEvaluateToUInt32(ExecState* exec)
2819 unsigned int i1 = m_term1->evaluateToUInt32(exec);
2820 KJS_CHECKEXCEPTIONNUMBER
2821 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
2825 JSValue* UnsignedRightShiftNode::evaluate(ExecState* exec)
2827 return jsNumber(inlineEvaluateToUInt32(exec));
2830 double UnsignedRightShiftNode::evaluateToNumber(ExecState* exec)
2832 return inlineEvaluateToUInt32(exec);
2835 int32_t UnsignedRightShiftNode::evaluateToInt32(ExecState* exec)
2837 return inlineEvaluateToUInt32(exec);
2840 uint32_t UnsignedRightShiftNode::evaluateToUInt32(ExecState* exec)
2842 return inlineEvaluateToUInt32(exec);
2845 // ------------------------------ Relational Nodes -------------------------------
2847 static inline bool lessThan(ExecState* exec, JSValue* v1, JSValue* v2)
2853 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
2854 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
2856 if (wasNotString1 | wasNotString2)
2859 return static_cast<const StringImp*>(p1)->value() < static_cast<const StringImp*>(p2)->value();
2862 static inline bool lessThanEq(ExecState* exec, JSValue* v1, JSValue* v2)
2868 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
2869 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
2871 if (wasNotString1 | wasNotString2)
2874 return !(static_cast<const StringImp*>(p2)->value() < static_cast<const StringImp*>(p1)->value());
2877 void LessNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2879 nodeStack.append(m_expr2.get());
2880 nodeStack.append(m_expr1.get());
2884 bool LessNode::inlineEvaluateToBoolean(ExecState* exec)
2886 JSValue* v1 = m_expr1->evaluate(exec);
2887 KJS_CHECKEXCEPTIONBOOLEAN
2888 JSValue* v2 = m_expr2->evaluate(exec);
2889 KJS_CHECKEXCEPTIONBOOLEAN
2890 return lessThan(exec, v1, v2);
2893 JSValue* LessNode::evaluate(ExecState* exec)
2895 return jsBoolean(inlineEvaluateToBoolean(exec));
2898 bool LessNode::evaluateToBoolean(ExecState* exec)
2900 return inlineEvaluateToBoolean(exec);
2903 bool LessNumbersNode::inlineEvaluateToBoolean(ExecState* exec)
2905 double n1 = m_expr1->evaluateToNumber(exec);
2906 KJS_CHECKEXCEPTIONVALUE
2907 double n2 = m_expr2->evaluateToNumber(exec);
2911 JSValue* LessNumbersNode::evaluate(ExecState* exec)
2913 return jsBoolean(inlineEvaluateToBoolean(exec));
2916 bool LessNumbersNode::evaluateToBoolean(ExecState* exec)
2918 return inlineEvaluateToBoolean(exec);
2921 bool LessStringsNode::inlineEvaluateToBoolean(ExecState* exec)
2923 JSValue* v1 = m_expr1->evaluate(exec);
2924 KJS_CHECKEXCEPTIONVALUE
2925 JSValue* v2 = m_expr2->evaluate(exec);
2926 return static_cast<StringImp*>(v1)->value() < static_cast<StringImp*>(v2)->value();
2929 JSValue* LessStringsNode::evaluate(ExecState* exec)
2931 return jsBoolean(inlineEvaluateToBoolean(exec));
2934 bool LessStringsNode::evaluateToBoolean(ExecState* exec)
2936 return inlineEvaluateToBoolean(exec);
2939 void GreaterNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2941 nodeStack.append(m_expr2.get());
2942 nodeStack.append(m_expr1.get());
2946 bool GreaterNode::inlineEvaluateToBoolean(ExecState* exec)
2948 JSValue* v1 = m_expr1->evaluate(exec);
2949 KJS_CHECKEXCEPTIONBOOLEAN
2950 JSValue* v2 = m_expr2->evaluate(exec);
2951 KJS_CHECKEXCEPTIONBOOLEAN
2952 return lessThan(exec, v2, v1);
2955 JSValue* GreaterNode::evaluate(ExecState* exec)
2957 return jsBoolean(inlineEvaluateToBoolean(exec));
2960 bool GreaterNode::evaluateToBoolean(ExecState* exec)
2962 return inlineEvaluateToBoolean(exec);
2965 void LessEqNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2967 nodeStack.append(m_expr2.get());
2968 nodeStack.append(m_expr1.get());
2972 bool LessEqNode::inlineEvaluateToBoolean(ExecState* exec)
2974 JSValue* v1 = m_expr1->evaluate(exec);
2975 KJS_CHECKEXCEPTIONBOOLEAN
2976 JSValue* v2 = m_expr2->evaluate(exec);
2977 KJS_CHECKEXCEPTIONBOOLEAN
2978 return lessThanEq(exec, v1, v2);
2981 JSValue* LessEqNode::evaluate(ExecState* exec)
2983 return jsBoolean(inlineEvaluateToBoolean(exec));
2986 bool LessEqNode::evaluateToBoolean(ExecState* exec)
2988 return inlineEvaluateToBoolean(exec);
2991 void GreaterEqNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2993 nodeStack.append(m_expr2.get());
2994 nodeStack.append(m_expr1.get());
2998 bool GreaterEqNode::inlineEvaluateToBoolean(ExecState* exec)
3000 JSValue* v1 = m_expr1->evaluate(exec);
3001 KJS_CHECKEXCEPTIONBOOLEAN
3002 JSValue* v2 = m_expr2->evaluate(exec);
3003 KJS_CHECKEXCEPTIONBOOLEAN
3004 return lessThanEq(exec, v2, v1);
3007 JSValue* GreaterEqNode::evaluate(ExecState* exec)
3009 return jsBoolean(inlineEvaluateToBoolean(exec));
3012 bool GreaterEqNode::evaluateToBoolean(ExecState* exec)
3014 return inlineEvaluateToBoolean(exec);
3017 void InstanceOfNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3019 nodeStack.append(m_expr2.get());
3020 nodeStack.append(m_expr1.get());
3024 JSValue* InstanceOfNode::evaluate(ExecState* exec)
3026 JSValue* v1 = m_expr1->evaluate(exec);
3027 KJS_CHECKEXCEPTIONVALUE
3028 JSValue* v2 = m_expr2->evaluate(exec);
3029 KJS_CHECKEXCEPTIONVALUE
3031 if (!v2->isObject())
3032 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, m_expr2.get());
3034 JSObject* o2 = static_cast<JSObject*>(v2);
3036 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
3037 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
3038 // property. It seems that all objects have the property, but not all implement it, so in this
3039 // case we return false (consistent with Mozilla).
3040 if (!o2->implementsHasInstance())
3041 return jsBoolean(false);
3043 return jsBoolean(o2->hasInstance(exec, v1));
3046 bool InstanceOfNode::evaluateToBoolean(ExecState* exec)
3048 JSValue* v1 = m_expr1->evaluate(exec);
3049 KJS_CHECKEXCEPTIONBOOLEAN
3050 JSValue* v2 = m_expr2->evaluate(exec);
3051 KJS_CHECKEXCEPTIONBOOLEAN
3053 if (!v2->isObject()) {
3054 throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'instanceof' operator.", v2, m_expr2.get());
3058 JSObject* o2 = static_cast<JSObject*>(v2);
3060 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
3061 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
3062 // property. It seems that all objects have the property, but not all implement it, so in this
3063 // case we return false (consistent with Mozilla).
3064 if (!o2->implementsHasInstance())
3067 return o2->hasInstance(exec, v1);
3070 void InNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3072 nodeStack.append(m_expr2.get());
3073 nodeStack.append(m_expr1.get());
3077 JSValue* InNode::evaluate(ExecState* exec)
3079 JSValue* v1 = m_expr1->evaluate(exec);
3080 KJS_CHECKEXCEPTIONVALUE
3081 JSValue* v2 = m_expr2->evaluate(exec);
3082 KJS_CHECKEXCEPTIONVALUE
3084 if (!v2->isObject())
3085 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
3087 return jsBoolean(static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec))));
3090 bool InNode::evaluateToBoolean(ExecState* exec)
3092 JSValue* v1 = m_expr1->evaluate(exec);
3093 KJS_CHECKEXCEPTIONBOOLEAN
3094 JSValue* v2 = m_expr2->evaluate(exec);
3095 KJS_CHECKEXCEPTIONBOOLEAN
3097 if (!v2->isObject()) {
3098 throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
3102 return static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec)));
3105 // ------------------------------ Equality Nodes ------------------------------------
3107 void EqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3109 nodeStack.append(m_expr2.get());
3110 nodeStack.append(m_expr1.get());
3114 bool EqualNode::inlineEvaluateToBoolean(ExecState* exec)
3116 JSValue* v1 = m_expr1->evaluate(exec);
3117 KJS_CHECKEXCEPTIONBOOLEAN
3118 JSValue* v2 = m_expr2->evaluate(exec);
3119 KJS_CHECKEXCEPTIONBOOLEAN
3121 return equal(exec, v1, v2);
3124 JSValue* EqualNode::evaluate(ExecState* exec)
3126 return jsBoolean(inlineEvaluateToBoolean(exec));
3129 bool EqualNode::evaluateToBoolean(ExecState* exec)
3131 return inlineEvaluateToBoolean(exec);
3134 void NotEqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3136 nodeStack.append(m_expr2.get());
3137 nodeStack.append(m_expr1.get());
3141 bool NotEqualNode::inlineEvaluateToBoolean(ExecState* exec)
3143 JSValue* v1 = m_expr1->evaluate(exec);
3144 KJS_CHECKEXCEPTIONBOOLEAN
3145 JSValue* v2 = m_expr2->evaluate(exec);
3146 KJS_CHECKEXCEPTIONBOOLEAN
3148 return !equal(exec,v1, v2);
3151 JSValue* NotEqualNode::evaluate(ExecState* exec)
3153 return jsBoolean(inlineEvaluateToBoolean(exec));
3156 bool NotEqualNode::evaluateToBoolean(ExecState* exec)
3158 return inlineEvaluateToBoolean(exec);
3161 void StrictEqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3163 nodeStack.append(m_expr2.get());
3164 nodeStack.append(m_expr1.get());
3168 bool StrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
3170 JSValue* v1 = m_expr1->evaluate(exec);
3171 KJS_CHECKEXCEPTIONBOOLEAN
3172 JSValue* v2 = m_expr2->evaluate(exec);
3173 KJS_CHECKEXCEPTIONBOOLEAN
3175 return strictEqual(exec,v1, v2);
3178 JSValue* StrictEqualNode::evaluate(ExecState* exec)
3180 return jsBoolean(inlineEvaluateToBoolean(exec));
3183 bool StrictEqualNode::evaluateToBoolean(ExecState* exec)
3185 return inlineEvaluateToBoolean(exec);
3188 void NotStrictEqualNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3190 nodeStack.append(m_expr2.get());
3191 nodeStack.append(m_expr1.get());
3195 bool NotStrictEqualNode::inlineEvaluateToBoolean(ExecState* exec)
3197 JSValue* v1 = m_expr1->evaluate(exec);
3198 KJS_CHECKEXCEPTIONBOOLEAN
3199 JSValue* v2 = m_expr2->evaluate(exec);
3200 KJS_CHECKEXCEPTIONBOOLEAN
3202 return !strictEqual(exec,v1, v2);
3205 JSValue* NotStrictEqualNode::evaluate(ExecState* exec)
3207 return jsBoolean(inlineEvaluateToBoolean(exec));
3210 bool NotStrictEqualNode::evaluateToBoolean(ExecState* exec)
3212 return inlineEvaluateToBoolean(exec);
3215 // ------------------------------ Bit Operation Nodes ----------------------------------
3217 void BitAndNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3219 nodeStack.append(m_expr2.get());
3220 nodeStack.append(m_expr1.get());
3224 JSValue* BitAndNode::evaluate(ExecState* exec)
3226 JSValue* v1 = m_expr1->evaluate(exec);
3227 KJS_CHECKEXCEPTIONVALUE
3228 JSValue* v2 = m_expr2->evaluate(exec);
3229 KJS_CHECKEXCEPTIONVALUE
3231 return jsNumberFromAnd(exec, v1, v2);
3234 int32_t BitAndNode::inlineEvaluateToInt32(ExecState* exec)
3236 int32_t i1 = m_expr1->evaluateToInt32(exec);
3237 KJS_CHECKEXCEPTIONNUMBER
3238 int32_t i2 = m_expr2->evaluateToInt32(exec);
3242 double BitAndNode::evaluateToNumber(ExecState* exec)
3244 return inlineEvaluateToInt32(exec);
3247 bool BitAndNode::evaluateToBoolean(ExecState* exec)
3249 return inlineEvaluateToInt32(exec);
3252 int32_t BitAndNode::evaluateToInt32(ExecState* exec)
3254 return inlineEvaluateToInt32(exec);
3257 uint32_t BitAndNode::evaluateToUInt32(ExecState* exec)
3259 return inlineEvaluateToInt32(exec);
3262 void BitXOrNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3264 nodeStack.append(m_expr2.get());
3265 nodeStack.append(m_expr1.get());
3268 int32_t BitXOrNode::inlineEvaluateToInt32(ExecState* exec)
3270 int i1 = m_expr1->evaluateToInt32(exec);
3271 KJS_CHECKEXCEPTIONNUMBER
3272 int i2 = m_expr2->evaluateToInt32(exec);
3276 JSValue* BitXOrNode::evaluate(ExecState* exec)
3278 return jsNumber(inlineEvaluateToInt32(exec));
3281 double BitXOrNode::evaluateToNumber(ExecState* exec)
3283 return inlineEvaluateToInt32(exec);
3286 bool BitXOrNode::evaluateToBoolean(ExecState* exec)
3288 return inlineEvaluateToInt32(exec);
3291 int32_t BitXOrNode::evaluateToInt32(ExecState* exec)
3293 return inlineEvaluateToInt32(exec);
3296 uint32_t BitXOrNode::evaluateToUInt32(ExecState* exec)
3298 return inlineEvaluateToInt32(exec);
3301 void BitOrNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3303 nodeStack.append(m_expr2.get());
3304 nodeStack.append(m_expr1.get());
3307 int32_t BitOrNode::inlineEvaluateToInt32(ExecState* exec)
3309 int i1 = m_expr1->evaluateToInt32(exec);
3310 KJS_CHECKEXCEPTIONNUMBER
3311 int i2 = m_expr2->evaluateToInt32(exec);
3315 JSValue* BitOrNode::evaluate(ExecState* exec)
3317 return jsNumber(inlineEvaluateToInt32(exec));
3320 double BitOrNode::evaluateToNumber(ExecState* exec)
3322 return inlineEvaluateToInt32(exec);
3325 bool BitOrNode::evaluateToBoolean(ExecState* exec)
3327 return inlineEvaluateToInt32(exec);
3330 int32_t BitOrNode::evaluateToInt32(ExecState* exec)
3332 return inlineEvaluateToInt32(exec);
3335 uint32_t BitOrNode::evaluateToUInt32(ExecState* exec)
3337 return inlineEvaluateToInt32(exec);
3340 // ------------------------------ Binary Logical Nodes ----------------------------
3342 void LogicalAndNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3344 nodeStack.append(m_expr2.get());
3345 nodeStack.append(m_expr1.get());
3349 JSValue* LogicalAndNode::evaluate(ExecState* exec)
3351 JSValue* v1 = m_expr1->evaluate(exec);
3352 KJS_CHECKEXCEPTIONVALUE
3353 bool b1 = v1->toBoolean(exec);
3354 KJS_CHECKEXCEPTIONVALUE
3357 JSValue* v2 = m_expr2->evaluate(exec);
3358 KJS_CHECKEXCEPTIONVALUE
3362 bool LogicalAndNode::evaluateToBoolean(ExecState* exec)
3364 bool b = m_expr1->evaluateToBoolean(exec);
3365 KJS_CHECKEXCEPTIONBOOLEAN
3366 return b && m_expr2->evaluateToBoolean(exec);
3369 void LogicalOrNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3371 nodeStack.append(m_expr2.get());
3372 nodeStack.append(m_expr1.get());
3375 JSValue* LogicalOrNode::evaluate(ExecState* exec)
3377 JSValue* v1 = m_expr1->evaluate(exec);
3378 KJS_CHECKEXCEPTIONVALUE
3379 if (v1->toBoolean(exec))
3381 return m_expr2->evaluate(exec);
3384 bool LogicalOrNode::evaluateToBoolean(ExecState* exec)
3386 bool b = m_expr1->evaluateToBoolean(exec);
3387 KJS_CHECKEXCEPTIONBOOLEAN
3388 return b || m_expr2->evaluateToBoolean(exec);
3391 // ------------------------------ ConditionalNode ------------------------------
3393 void ConditionalNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3395 nodeStack.append(m_expr2.get());
3396 nodeStack.append(m_expr1.get());
3397 nodeStack.append(m_logical.get());
3401 JSValue* ConditionalNode::evaluate(ExecState* exec)
3403 bool b = m_logical->evaluateToBoolean(exec);
3404 KJS_CHECKEXCEPTIONVALUE
3405 return b ? m_expr1->evaluate(exec) : m_expr2->evaluate(exec);
3408 bool ConditionalNode::evaluateToBoolean(ExecState* exec)
3410 bool b = m_logical->evaluateToBoolean(exec);
3411 KJS_CHECKEXCEPTIONBOOLEAN
3412 return b ? m_expr1->evaluateToBoolean(exec) : m_expr2->evaluateToBoolean(exec);
3415 double ConditionalNode::evaluateToNumber(ExecState* exec)
3417 bool b = m_logical->evaluateToBoolean(exec);
3418 KJS_CHECKEXCEPTIONNUMBER
3419 return b ? m_expr1->evaluateToNumber(exec) : m_expr2->evaluateToNumber(exec);
3422 int32_t ConditionalNode::evaluateToInt32(ExecState* exec)
3424 bool b = m_logical->evaluateToBoolean(exec);
3425 KJS_CHECKEXCEPTIONNUMBER
3426 return b ? m_expr1->evaluateToInt32(exec) : m_expr2->evaluateToInt32(exec);
3429 uint32_t ConditionalNode::evaluateToUInt32(ExecState* exec)
3431 bool b = m_logical->evaluateToBoolean(exec);
3432 KJS_CHECKEXCEPTIONNUMBER
3433 return b ? m_expr1->evaluateToUInt32(exec) : m_expr2->evaluateToUInt32(exec);
3438 static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper) KJS_FAST_CALL;
3439 static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(ExecState* exec, JSValue* current, ExpressionNode* right, Operator oper)
3447 v = jsNumber(current->toNumber(exec) * right->evaluateToNumber(exec));
3450 v = jsNumber(current->toNumber(exec) / right->evaluateToNumber(exec));
3453 v = add(exec, current, right->evaluate(exec));
3456 v = jsNumber(current->toNumber(exec) - right->evaluateToNumber(exec));
3459 i1 = current->toInt32(exec);
3460 i2 = right->evaluateToInt32(exec);
3461 v = jsNumber(i1 << i2);
3464 i1 = current->toInt32(exec);
3465 i2 = right->evaluateToInt32(exec);
3466 v = jsNumber(i1 >> i2);
3469 ui = current->toUInt32(exec);
3470 i2 = right->evaluateToInt32(exec);
3471 v = jsNumber(ui >> i2);
3474 i1 = current->toInt32(exec);
3475 i2 = right->evaluateToInt32(exec);
3476 v = jsNumber(i1 & i2);
3479 i1 = current->toInt32(exec);
3480 i2 = right->evaluateToInt32(exec);
3481 v = jsNumber(i1 ^ i2);
3484 i1 = current->toInt32(exec);
3485 i2 = right->evaluateToInt32(exec);
3486 v = jsNumber(i1 | i2);
3489 double d1 = current->toNumber(exec);
3490 double d2 = right->evaluateToNumber(exec);
3491 v = jsNumber(fmod(d1, d2));
3495 ASSERT_NOT_REACHED();
3502 // ------------------------------ ReadModifyResolveNode -----------------------------------
3504 void ReadModifyResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
3506 nodeStack.append(m_right.get());
3507 size_t index = symbolTable.get(m_ident.ustring().rep());
3508 if (index != missingSymbolMarker()) {
3509 if (isConstant(localStorage, index))
3510 new (this) ReadModifyConstNode(index);
3512 new (this) ReadModifyLocalVarNode(index);
3516 // ------------------------------ AssignResolveNode -----------------------------------
3518 void AssignResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
3520 nodeStack.append(m_right.get());
3521 size_t index = symbolTable.get(m_ident.ustring().rep());
3522 if (index != missingSymbolMarker()) {
3523 if (isConstant(localStorage, index))
3524 new (this) AssignConstNode;
3526 new (this) AssignLocalVarNode(index);
3530 // ------------------------------ ReadModifyLocalVarNode -----------------------------------
3532 JSValue* ReadModifyLocalVarNode::evaluate(ExecState* exec)
3534 ASSERT(exec->variableObject() == exec->scopeChain().top());
3536 ASSERT(m_operator != OpEqual);
3537 JSValue* v = valueForReadModifyAssignment(exec, exec->localStorage()[m_index].value, m_right.get(), m_operator);
3539 KJS_CHECKEXCEPTIONVALUE
3541 // We can't store a pointer into localStorage() and use it throughout the function
3542 // body, because valueForReadModifyAssignment() might cause an ActivationImp tear-off,
3543 // changing the value of localStorage().
3545 exec->localStorage()[m_index].value = v;
3549 // ------------------------------ AssignLocalVarNode -----------------------------------
3551 JSValue* AssignLocalVarNode::evaluate(ExecState* exec)
3553 ASSERT(exec->variableObject() == exec->scopeChain().top());
3554 JSValue* v = m_right->evaluate(exec);
3556 KJS_CHECKEXCEPTIONVALUE
3558 exec->localStorage()[m_index].value = v;
3563 // ------------------------------ ReadModifyConstNode -----------------------------------
3565 JSValue* ReadModifyConstNode::evaluate(ExecState* exec)
3567 ASSERT(exec->variableObject() == exec->scopeChain().top());
3568 JSValue* left = exec->localStorage()[m_index].value;
3569 ASSERT(m_operator != OpEqual);
3570 JSValue* result = valueForReadModifyAssignment(exec, left, m_right.get(), m_operator);
3571 KJS_CHECKEXCEPTIONVALUE
3575 // ------------------------------ AssignConstNode -----------------------------------
3577 JSValue* AssignConstNode::evaluate(ExecState* exec)
3579 return m_right->evaluate(exec);
3582 JSValue* ReadModifyResolveNode::evaluate(ExecState* exec)
3584 const ScopeChain& chain = exec->scopeChain();
3585 ScopeChainIterator iter = chain.begin();
3586 ScopeChainIterator end = chain.end();
3588 // We must always have something in the scope chain
3589 ASSERT(iter != end);
3595 if (base->getPropertySlot(exec, m_ident, slot)) {
3596 // See the comment in PostIncResolveNode::evaluate().
3603 } while (iter != end);
3605 ASSERT(m_operator != OpEqual);
3606 return throwUndefinedVariableError(exec, m_ident);
3611 ASSERT(m_operator != OpEqual);
3612 JSValue* v1 = slot.getValue(exec, base, m_ident);
3613 KJS_CHECKEXCEPTIONVALUE
3614 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
3616 KJS_CHECKEXCEPTIONVALUE
3618 // Since valueForReadModifyAssignment() might cause an ActivationImp tear-off,
3619 // we need to get the base from the ScopeChainIterator again.
3621 (*iter)->put(exec, m_ident, v);
3625 JSValue* AssignResolveNode::evaluate(ExecState* exec)
3627 const ScopeChain& chain = exec->scopeChain();
3628 ScopeChainIterator iter = chain.begin();
3629 ScopeChainIterator end = chain.end();
3631 // we must always have something in the scope chain
3632 ASSERT(iter != end);
3638 if (base->getPropertySlot(exec, m_ident, slot)) {
3639 // See the comment in PostIncResolveNode::evaluate().
3646 } while (iter != end);
3649 JSValue* v = m_right->evaluate(exec);
3651 KJS_CHECKEXCEPTIONVALUE
3653 base->put(exec, m_ident, v);
3657 // ------------------------------ ReadModifyDotNode -----------------------------------
3659 void AssignDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3661 nodeStack.append(m_right.get());
3662 nodeStack.append(m_base.get());
3665 JSValue* AssignDotNode::evaluate(ExecState* exec)
3667 JSValue* baseValue = m_base->evaluate(exec);
3668 KJS_CHECKEXCEPTIONVALUE
3669 JSObject* base = baseValue->toObject(exec);
3671 JSValue* v = m_right->evaluate(exec);
3673 KJS_CHECKEXCEPTIONVALUE
3675 base->put(exec, m_ident, v);
3679 void ReadModifyDotNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3681 nodeStack.append(m_right.get());
3682 nodeStack.append(m_base.get());
3685 JSValue* ReadModifyDotNode::evaluate(ExecState* exec)
3687 JSValue* baseValue = m_base->evaluate(exec);
3688 KJS_CHECKEXCEPTIONVALUE
3689 JSObject* base = baseValue->toObject(exec);
3693 ASSERT(m_operator != OpEqual);
3695 JSValue* v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
3696 KJS_CHECKEXCEPTIONVALUE
3697 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
3699 KJS_CHECKEXCEPTIONVALUE
3701 base->put(exec, m_ident, v);
3705 // ------------------------------ AssignErrorNode -----------------------------------
3707 JSValue* AssignErrorNode::evaluate(ExecState* exec)
3709 throwError(exec, ReferenceError, "Left side of assignment is not a reference.");
3710 handleException(exec);
3711 return jsUndefined();
3714 // ------------------------------ AssignBracketNode -----------------------------------
3716 void AssignBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3718 nodeStack.append(m_right.get());
3719 nodeStack.append(m_subscript.get());
3720 nodeStack.append(m_base.get());
3723 JSValue* AssignBracketNode::evaluate(ExecState* exec)
3725 JSValue* baseValue = m_base->evaluate(exec);
3726 KJS_CHECKEXCEPTIONVALUE
3727 JSValue* subscript = m_subscript->evaluate(exec);
3728 KJS_CHECKEXCEPTIONVALUE
3730 JSObject* base = baseValue->toObject(exec);
3732 uint32_t propertyIndex;
3733 if (subscript->getUInt32(propertyIndex)) {
3734 JSValue* v = m_right->evaluate(exec);
3735 KJS_CHECKEXCEPTIONVALUE
3737 base->put(exec, propertyIndex, v);
3741 Identifier propertyName(subscript->toString(exec));
3742 JSValue* v = m_right->evaluate(exec);
3743 KJS_CHECKEXCEPTIONVALUE
3745 base->put(exec, propertyName, v);
3748 void ReadModifyBracketNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3750 nodeStack.append(m_right.get());
3751 nodeStack.append(m_subscript.get());
3752 nodeStack.append(m_base.get());
3755 JSValue* ReadModifyBracketNode::evaluate(ExecState* exec)
3757 JSValue* baseValue = m_base->evaluate(exec);
3758 KJS_CHECKEXCEPTIONVALUE
3759 JSValue* subscript = m_subscript->evaluate(exec);
3760 KJS_CHECKEXCEPTIONVALUE
3762 JSObject* base = baseValue->toObject(exec);
3764 uint32_t propertyIndex;
3765 if (subscript->getUInt32(propertyIndex)) {
3767 ASSERT(m_operator != OpEqual);
3769 JSValue* v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
3770 KJS_CHECKEXCEPTIONVALUE
3771 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
3773 KJS_CHECKEXCEPTIONVALUE
3775 base->put(exec, propertyIndex, v);
3779 Identifier propertyName(subscript->toString(exec));
3782 ASSERT(m_operator != OpEqual);
3784 JSValue* v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
3785 KJS_CHECKEXCEPTIONVALUE
3786 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
3788 KJS_CHECKEXCEPTIONVALUE
3790 base->put(exec, propertyName, v);
3794 // ------------------------------ CommaNode ------------------------------------
3796 void CommaNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3798 nodeStack.append(m_expr2.get());
3799 nodeStack.append(m_expr1.get());
3803 JSValue* CommaNode::evaluate(ExecState* exec)
3805 m_expr1->evaluate(exec);
3806 KJS_CHECKEXCEPTIONVALUE
3807 return m_expr2->evaluate(exec);
3810 // ------------------------------ ConstDeclNode ----------------------------------
3812 ConstDeclNode::ConstDeclNode(const Identifier& ident, ExpressionNode* init)
3818 void ConstDeclNode::optimizeVariableAccess(ExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3821 nodeStack.append(m_next.get());
3823 nodeStack.append(m_init.get());
3826 void ConstDeclNode::handleSlowCase(ExecState* exec, const ScopeChain& chain, JSValue* val)
3828 ScopeChainIterator iter = chain.begin();
3829 ScopeChainIterator end = chain.end();
3831 // We must always have something in the scope chain
3832 ASSERT(iter != end);
3838 if (base->isVariableObject())
3841 } while (iter != end);
3843 ASSERT(base && base->isVariableObject());
3845 static_cast<JSVariableObject*>(base)->putWithAttributes(exec, m_ident, val, ReadOnly);
3849 inline void ConstDeclNode::evaluateSingle(ExecState* exec)
3851 ASSERT(exec->variableObject()->hasOwnProperty(exec, m_ident) || exec->codeType() == EvalCode); // Guaranteed by processDeclarations.
3852 const ScopeChain& chain = exec->scopeChain();
3853 JSVariableObject* variableObject = exec->variableObject();
3855 ASSERT(!chain.isEmpty());
3857 bool inGlobalScope = ++chain.begin() == chain.end();
3860 if (inGlobalScope) {
3861 JSValue* val = m_init->evaluate(exec);
3862 unsigned attributes = ReadOnly;
3863 if (exec->codeType() != EvalCode)
3864 attributes |= DontDelete;
3865 variableObject->putWithAttributes(exec, m_ident, val, attributes);
3867 JSValue* val = m_init->evaluate(exec);
3868 KJS_CHECKEXCEPTIONVOID
3870 // if the variable object is the top of the scope chain, then that must
3871 // be where this variable is declared, processVarDecls would have put
3872 // it there. Don't search the scope chain, to optimize this very common case.
3873 if (chain.top() != variableObject)
3874 return handleSlowCase(exec, chain, val);
3876 variableObject->putWithAttributes(exec, m_ident, val, ReadOnly);
3881 JSValue* ConstDeclNode::evaluate(ExecState* exec)