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