source: webkit/trunk/JavaScriptCore/kjs/nodes.cpp@ 34250

Last change on this file since 34250 was 34250, checked in by [email protected], 17 years ago

JavaScriptCore:

2008-05-29 Maciej Stachowiak <[email protected]>

Reviewed by Oliver.

  • fixed <rdar://problem/5972943> REGRESSION(r33979): Flash clips do not play on cnn.com


Finally blocks could clobber registers that had to remain live
until they returned. This patch takes a conservative approach and
makes sure that finally blocks do not reuse any registers that
were previously allocated for the function. In the future this
could probably be tightened up to be less profligate with the
register allocation.


  • VM/CodeGenerator.cpp: (KJS::CodeGenerator::highestUsedRegister):
  • VM/CodeGenerator.h:
  • kjs/nodes.cpp: (KJS::TryNode::emitCode):

LayoutTests:

2008-05-29 Maciej Stachowiak <[email protected]>

Reviewed by Oliver. Test by Geoff Garen.


  • fixed <rdar://problem/5972943> REGRESSION(r33979): Flash clips do not play on cnn.com
  • fast/js/finally-codegen-failure-expected.txt: Added.
  • fast/js/finally-codegen-failure.html: Added.
  • Property svn:eol-style set to native
File size: 198.1 KB
Line 
1/*
2* Copyright (C) 1999-2002 Harri Porten ([email protected])
3* Copyright (C) 2001 Peter Kelly ([email protected])
4* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5* Copyright (C) 2007 Cameron Zwarich ([email protected])
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <[email protected]>
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 "CodeGenerator.h"
30#include "ExecState.h"
31#include "JSGlobalObject.h"
32#include "Parser.h"
33#include "PropertyNameArray.h"
34#include "array_object.h"
35#include "debugger.h"
36#include "function_object.h"
37#include "lexer.h"
38#include "operations.h"
39#include "regexp_object.h"
40#include <math.h>
41#include <wtf/Assertions.h>
42#include <wtf/HashCountedSet.h>
43#include <wtf/HashSet.h>
44#include <wtf/MathExtras.h>
45
46namespace KJS {
47
48class FunctionBodyNodeWithDebuggerHooks : public FunctionBodyNode {
49public:
50 FunctionBodyNodeWithDebuggerHooks(SourceElements*, VarStack*, FunctionStack*, bool usesEval, bool needsClosure) KJS_FAST_CALL;
51 virtual JSValue* execute(OldInterpreterExecState*) KJS_FAST_CALL;
52};
53
54#if COMPILER(GCC)
55#define UNLIKELY(x) \
56 __builtin_expect ((x), 0)
57#else
58#define UNLIKELY(x) x
59#endif
60
61#define KJS_CHECKEXCEPTION \
62if (UNLIKELY(exec->hadException())) \
63 return rethrowException(exec);
64
65#define KJS_CHECKEXCEPTIONVALUE \
66if (UNLIKELY(exec->hadException())) { \
67 handleException(exec); \
68 return jsUndefined(); \
69}
70
71#define KJS_CHECKEXCEPTIONNUMBER \
72if (UNLIKELY(exec->hadException())) { \
73 handleException(exec); \
74 return 0; \
75}
76
77#define KJS_CHECKEXCEPTIONBOOLEAN \
78if (UNLIKELY(exec->hadException())) { \
79 handleException(exec); \
80 return false; \
81}
82
83#define KJS_CHECKEXCEPTIONVOID \
84if (UNLIKELY(exec->hadException())) { \
85 handleException(exec); \
86 return; \
87}
88
89#if !ASSERT_DISABLED
90static inline bool canSkipLookup(OldInterpreterExecState* exec, const Identifier& ident)
91{
92 // Static lookup in EvalCode is impossible because variables aren't DontDelete.
93 // Static lookup in GlobalCode may be possible, but we haven't implemented support for it yet.
94 if (exec->codeType() != FunctionCode)
95 return false;
96
97 // Static lookup is impossible when something dynamic has been added to the front of the scope chain.
98 if (exec->variableObject() != exec->scopeChain().top())
99 return false;
100
101 // Static lookup is impossible if the symbol isn't statically declared.
102 if (!exec->variableObject()->symbolTable().contains(ident.ustring().rep()))
103 return false;
104
105 return true;
106}
107#endif
108
109static inline bool isConstant(const LocalStorage& localStorage, size_t index)
110{
111 ASSERT(index < localStorage.size());
112 return localStorage[index].attributes & ReadOnly;
113}
114
115static inline UString::Rep* rep(const Identifier& ident)
116{
117 return ident.ustring().rep();
118}
119
120// ------------------------------ Node -----------------------------------------
121
122#ifndef NDEBUG
123#ifndef LOG_CHANNEL_PREFIX
124#define LOG_CHANNEL_PREFIX Log
125#endif
126static WTFLogChannel LogKJSNodeLeaks = { 0x00000000, "", WTFLogChannelOn };
127
128struct ParserRefCountedCounter {
129 static unsigned count;
130 ParserRefCountedCounter()
131 {
132 if (count)
133 LOG(KJSNodeLeaks, "LEAK: %u KJS::Node\n", count);
134 }
135};
136unsigned ParserRefCountedCounter::count = 0;
137static ParserRefCountedCounter parserRefCountedCounter;
138#endif
139
140static HashSet<ParserRefCounted*>* newTrackedObjects;
141static HashCountedSet<ParserRefCounted*>* trackedObjectExtraRefCounts;
142
143ParserRefCounted::ParserRefCounted()
144{
145#ifndef NDEBUG
146 ++ParserRefCountedCounter::count;
147#endif
148 if (!newTrackedObjects)
149 newTrackedObjects = new HashSet<ParserRefCounted*>;
150 newTrackedObjects->add(this);
151 ASSERT(newTrackedObjects->contains(this));
152}
153
154ParserRefCounted::~ParserRefCounted()
155{
156#ifndef NDEBUG
157 --ParserRefCountedCounter::count;
158#endif
159}
160
161void ParserRefCounted::ref()
162{
163 // bumping from 0 to 1 is just removing from the new nodes set
164 if (newTrackedObjects) {
165 HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->find(this);
166 if (it != newTrackedObjects->end()) {
167 newTrackedObjects->remove(it);
168 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
169 return;
170 }
171 }
172
173 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
174
175 if (!trackedObjectExtraRefCounts)
176 trackedObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
177 trackedObjectExtraRefCounts->add(this);
178}
179
180void ParserRefCounted::deref()
181{
182 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
183
184 if (!trackedObjectExtraRefCounts) {
185 delete this;
186 return;
187 }
188
189 HashCountedSet<ParserRefCounted*>::iterator it = trackedObjectExtraRefCounts->find(this);
190 if (it == trackedObjectExtraRefCounts->end())
191 delete this;
192 else
193 trackedObjectExtraRefCounts->remove(it);
194}
195
196unsigned ParserRefCounted::refcount()
197{
198 if (newTrackedObjects && newTrackedObjects->contains(this)) {
199 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(this));
200 return 0;
201 }
202
203 ASSERT(!newTrackedObjects || !newTrackedObjects->contains(this));
204
205 if (!trackedObjectExtraRefCounts)
206 return 1;
207
208 return 1 + trackedObjectExtraRefCounts->count(this);
209}
210
211void ParserRefCounted::deleteNewObjects()
212{
213 if (!newTrackedObjects)
214 return;
215
216#ifndef NDEBUG
217 HashSet<ParserRefCounted*>::iterator end = newTrackedObjects->end();
218 for (HashSet<ParserRefCounted*>::iterator it = newTrackedObjects->begin(); it != end; ++it)
219 ASSERT(!trackedObjectExtraRefCounts || !trackedObjectExtraRefCounts->contains(*it));
220#endif
221 deleteAllValues(*newTrackedObjects);
222 delete newTrackedObjects;
223 newTrackedObjects = 0;
224}
225
226Node::Node()
227 : m_expectedReturnType(ObjectType)
228{
229 m_line = lexer().lineNo();
230}
231
232Node::Node(JSType expectedReturn)
233 : m_expectedReturnType(expectedReturn)
234{
235 m_line = lexer().lineNo();
236}
237
238double ExpressionNode::evaluateToNumber(OldInterpreterExecState* exec)
239{
240 JSValue* value = evaluate(exec);
241 KJS_CHECKEXCEPTIONNUMBER
242 return value->toNumber(exec);
243}
244
245bool ExpressionNode::evaluateToBoolean(OldInterpreterExecState* exec)
246{
247 JSValue* value = evaluate(exec);
248 KJS_CHECKEXCEPTIONBOOLEAN
249 return value->toBoolean(exec);
250}
251
252int32_t ExpressionNode::evaluateToInt32(OldInterpreterExecState* exec)
253{
254 JSValue* value = evaluate(exec);
255 KJS_CHECKEXCEPTIONNUMBER
256 return value->toInt32(exec);
257}
258
259uint32_t ExpressionNode::evaluateToUInt32(OldInterpreterExecState* exec)
260{
261 JSValue* value = evaluate(exec);
262 KJS_CHECKEXCEPTIONNUMBER
263 return value->toUInt32(exec);
264}
265
266static void substitute(UString& string, const UString& substring) KJS_FAST_CALL;
267static void substitute(UString& string, const UString& substring)
268{
269 int position = string.find("%s");
270 ASSERT(position != -1);
271 UString newString = string.substr(0, position);
272 newString.append(substring);
273 newString.append(string.substr(position + 2));
274 string = newString;
275}
276
277static inline int currentSourceId(ExecState* exec) KJS_FAST_CALL;
278static inline int currentSourceId(ExecState*)
279{
280 ASSERT_NOT_REACHED();
281 return 0;
282}
283
284static inline const UString currentSourceURL(ExecState* exec) KJS_FAST_CALL;
285static inline const UString currentSourceURL(ExecState*)
286{
287 ASSERT_NOT_REACHED();
288 return UString();
289}
290
291JSValue* Node::setErrorCompletion(OldInterpreterExecState* exec, ErrorType e, const char* msg)
292{
293 return exec->setThrowCompletion(Error::create(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
294}
295
296JSValue* Node::setErrorCompletion(OldInterpreterExecState* exec, ErrorType e, const char* msg, const Identifier& ident)
297{
298 UString message = msg;
299 substitute(message, ident.ustring());
300 return exec->setThrowCompletion(Error::create(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec)));
301}
302
303JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg)
304{
305 return KJS::throwError(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec));
306}
307
308JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, const char* string)
309{
310 UString message = msg;
311 substitute(message, string);
312 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
313}
314
315JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr)
316{
317 UString message = msg;
318 substitute(message, v->toString(exec));
319 substitute(message, expr->toString());
320 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
321}
322
323JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, const Identifier& label)
324{
325 UString message = msg;
326 substitute(message, label.ustring());
327 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
328}
329
330JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* e1, Node* e2)
331{
332 UString message = msg;
333 substitute(message, v->toString(exec));
334 substitute(message, e1->toString());
335 substitute(message, e2->toString());
336 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
337}
338
339JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, Node* expr, const Identifier& label)
340{
341 UString message = msg;
342 substitute(message, v->toString(exec));
343 substitute(message, expr->toString());
344 substitute(message, label.ustring());
345 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
346}
347
348JSValue* Node::throwError(OldInterpreterExecState* exec, ErrorType e, const char* msg, JSValue* v, const Identifier& label)
349{
350 UString message = msg;
351 substitute(message, v->toString(exec));
352 substitute(message, label.ustring());
353 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
354}
355
356JSValue* Node::throwUndefinedVariableError(OldInterpreterExecState* exec, const Identifier& ident)
357{
358 return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
359}
360
361void Node::handleException(OldInterpreterExecState* exec)
362{
363 handleException(exec, exec->exception());
364}
365
366void Node::handleException(OldInterpreterExecState* exec, JSValue* exceptionValue)
367{
368 if (exceptionValue->isObject()) {
369 JSObject* exception = static_cast<JSObject*>(exceptionValue);
370 if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
371 exception->put(exec, "line", jsNumber(m_line));
372 exception->put(exec, "sourceURL", jsString(currentSourceURL(exec)));
373 }
374 }
375#if 0
376 Debugger* dbg = exec->dynamicGlobalObject()->debugger();
377 if (dbg && !dbg->hasHandledException(exec, exceptionValue))
378 dbg->exception(exec, currentSourceId(exec), m_line, exceptionValue);
379#endif
380}
381
382NEVER_INLINE JSValue* Node::rethrowException(OldInterpreterExecState* exec)
383{
384 JSValue* exception = exec->exception();
385 exec->clearException();
386 handleException(exec, exception);
387 return exec->setThrowCompletion(exception);
388}
389
390RegisterID* Node::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg)
391{
392 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(msg));
393 generator.emitThrow(exception);
394 return exception;
395}
396
397RegisterID* Node::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
398{
399 UString message = msg;
400 substitute(message, label.ustring());
401 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(message));
402 generator.emitThrow(exception);
403 return exception;
404}
405
406// ------------------------------ StatementNode --------------------------------
407
408StatementNode::StatementNode()
409 : m_lastLine(-1)
410{
411 m_line = -1;
412}
413
414void StatementNode::setLoc(int firstLine, int lastLine)
415{
416 m_line = firstLine;
417 m_lastLine = lastLine;
418}
419
420// ------------------------------ SourceElements --------------------------------
421
422void SourceElements::append(PassRefPtr<StatementNode> statement)
423{
424 if (statement->isEmptyStatement())
425 return;
426
427 m_statements.append(statement);
428}
429
430// ------------------------------ BreakpointCheckStatement --------------------------------
431
432BreakpointCheckStatement::BreakpointCheckStatement(PassRefPtr<StatementNode> statement)
433 : m_statement(statement)
434{
435 ASSERT(m_statement);
436}
437
438JSValue* BreakpointCheckStatement::execute(OldInterpreterExecState* exec)
439{
440 return m_statement->execute(exec);
441}
442
443void BreakpointCheckStatement::streamTo(SourceStream& stream) const
444{
445 m_statement->streamTo(stream);
446}
447
448void BreakpointCheckStatement::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
449{
450 nodeStack.append(m_statement.get());
451}
452
453// ------------------------------ NullNode -------------------------------------
454
455RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst)
456{
457 return generator.emitLoad(generator.finalDestination(dst), jsNull());
458}
459
460JSValue* NullNode::evaluate(OldInterpreterExecState* )
461{
462 return jsNull();
463}
464
465// ------------------------------ FalseNode ----------------------------------
466
467RegisterID* FalseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
468{
469 return generator.emitLoad(generator.finalDestination(dst), false);
470}
471
472JSValue* FalseNode::evaluate(OldInterpreterExecState*)
473{
474 return jsBoolean(false);
475}
476
477// ------------------------------ TrueNode ----------------------------------
478
479RegisterID* TrueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
480{
481 return generator.emitLoad(generator.finalDestination(dst), true);
482}
483
484JSValue* TrueNode::evaluate(OldInterpreterExecState*)
485{
486 return jsBoolean(true);
487}
488
489// ------------------------------ NumberNode -----------------------------------
490
491RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst)
492{
493 return generator.emitLoad(generator.finalDestination(dst), m_double);
494}
495
496JSValue* NumberNode::evaluate(OldInterpreterExecState*)
497{
498 // Number nodes are only created when the number can't fit in a JSImmediate, so no need to check again.
499 return jsNumberCell(m_double);
500}
501
502double NumberNode::evaluateToNumber(OldInterpreterExecState*)
503{
504 return m_double;
505}
506
507bool NumberNode::evaluateToBoolean(OldInterpreterExecState*)
508{
509 return m_double < 0.0 || m_double > 0.0; // false for NaN as well as 0
510}
511
512int32_t NumberNode::evaluateToInt32(OldInterpreterExecState*)
513{
514 return JSValue::toInt32(m_double);
515}
516
517uint32_t NumberNode::evaluateToUInt32(OldInterpreterExecState*)
518{
519 return JSValue::toUInt32(m_double);
520}
521
522// ------------------------------ ImmediateNumberNode -----------------------------------
523
524JSValue* ImmediateNumberNode::evaluate(OldInterpreterExecState*)
525{
526 return m_value;
527}
528
529int32_t ImmediateNumberNode::evaluateToInt32(OldInterpreterExecState*)
530{
531 return JSImmediate::getTruncatedInt32(m_value);
532}
533
534uint32_t ImmediateNumberNode::evaluateToUInt32(OldInterpreterExecState*)
535{
536 uint32_t i;
537 if (JSImmediate::getTruncatedUInt32(m_value, i))
538 return i;
539 bool ok;
540 return JSValue::toUInt32SlowCase(m_double, ok);
541}
542
543// ------------------------------ StringNode -----------------------------------
544
545RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
546{
547 // FIXME: should we try to atomize constant strings?
548 return generator.emitLoad(generator.finalDestination(dst), jsOwnedString(m_value));
549}
550
551JSValue* StringNode::evaluate(OldInterpreterExecState*)
552{
553 return jsOwnedString(m_value);
554}
555
556double StringNode::evaluateToNumber(OldInterpreterExecState*)
557{
558 return m_value.toDouble();
559}
560
561bool StringNode::evaluateToBoolean(OldInterpreterExecState*)
562{
563 return !m_value.isEmpty();
564}
565
566// ------------------------------ RegExpNode -----------------------------------
567
568RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
569{
570 if (!m_regExp->isValid())
571 return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", m_regExp->errorMessage());
572 return generator.emitNewRegExp(generator.finalDestination(dst), m_regExp.get());
573}
574
575JSValue* RegExpNode::evaluate(OldInterpreterExecState*)
576{
577 ASSERT_NOT_REACHED();
578 return 0;
579}
580
581// ------------------------------ ThisNode -------------------------------------
582
583RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
584{
585 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
586}
587
588// ECMA 11.1.1
589JSValue* ThisNode::evaluate(OldInterpreterExecState* exec)
590{
591 return exec->thisValue();
592}
593
594// ------------------------------ ResolveNode ----------------------------------
595
596RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
597{
598 if (RegisterID* local = generator.registerForLocal(m_ident))
599 return generator.moveToDestinationIfNeeded(dst, local);
600
601 return generator.emitResolve(generator.finalDestination(dst), m_ident);
602}
603
604// ECMA 11.1.2 & 10.1.4
605JSValue* ResolveNode::inlineEvaluate(OldInterpreterExecState* exec)
606{
607 // Check for missed optimization opportunity.
608 ASSERT(!canSkipLookup(exec, m_ident));
609
610 const ScopeChain& chain = exec->scopeChain();
611 ScopeChainIterator iter = chain.begin();
612 ScopeChainIterator end = chain.end();
613
614 // we must always have something in the scope chain
615 ASSERT(iter != end);
616
617 PropertySlot slot;
618 do {
619 JSObject* o = *iter;
620
621 if (o->getPropertySlot(exec, m_ident, slot))
622 return slot.getValue(exec, o, m_ident);
623
624 ++iter;
625 } while (iter != end);
626
627 return throwUndefinedVariableError(exec, m_ident);
628}
629
630JSValue* ResolveNode::evaluate(OldInterpreterExecState* exec)
631{
632 return inlineEvaluate(exec);
633}
634
635double ResolveNode::evaluateToNumber(OldInterpreterExecState* exec)
636{
637 JSValue* v = inlineEvaluate(exec);
638 KJS_CHECKEXCEPTIONNUMBER
639 return v->toNumber(exec);
640}
641
642bool ResolveNode::evaluateToBoolean(OldInterpreterExecState* exec)
643{
644 JSValue* v = inlineEvaluate(exec);
645 KJS_CHECKEXCEPTIONBOOLEAN
646 return v->toBoolean(exec);
647}
648
649int32_t ResolveNode::evaluateToInt32(OldInterpreterExecState* exec)
650{
651 JSValue* v = inlineEvaluate(exec);
652 KJS_CHECKEXCEPTIONNUMBER
653 return v->toInt32(exec);
654}
655
656uint32_t ResolveNode::evaluateToUInt32(OldInterpreterExecState* exec)
657{
658 JSValue* v = inlineEvaluate(exec);
659 KJS_CHECKEXCEPTIONNUMBER
660 return v->toUInt32(exec);
661}
662
663static size_t getSymbolTableEntry(OldInterpreterExecState* exec, const Identifier& ident, const SymbolTable& symbolTable, size_t& stackDepth)
664{
665 int index = symbolTable.get(ident.ustring().rep()).getIndex();
666 if (index != missingSymbolMarker()) {
667 stackDepth = 0;
668 return index;
669 }
670
671 if (ident == exec->propertyNames().arguments) {
672 stackDepth = 0;
673 return missingSymbolMarker();
674 }
675
676 const ScopeChain& chain = exec->scopeChain();
677 ScopeChainIterator iter = chain.begin();
678 ScopeChainIterator end = chain.end();
679 size_t depth = 0;
680 for (; iter != end; ++iter, ++depth) {
681 JSObject* currentScope = *iter;
682 if (!currentScope->isVariableObject())
683 break;
684 JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
685 index = currentVariableObject->symbolTable().get(ident.ustring().rep()).getIndex();
686 if (index != missingSymbolMarker()) {
687 stackDepth = depth;
688 return index;
689 }
690 if (currentVariableObject->isDynamicScope())
691 break;
692 }
693 stackDepth = depth;
694 return missingSymbolMarker();
695}
696
697void ResolveNode::optimizeVariableAccess(OldInterpreterExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
698{
699 size_t depth = 0;
700 int index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
701 if (index != missingSymbolMarker()) {
702 if (!depth)
703 new (this) LocalVarAccessNode(index);
704 else
705 new (this) ScopedVarAccessNode(index, depth);
706 return;
707 }
708
709 if (!depth)
710 return;
711
712 new (this) NonLocalVarAccessNode(depth);
713}
714
715JSValue* LocalVarAccessNode::inlineEvaluate(OldInterpreterExecState* exec)
716{
717 ASSERT(exec->variableObject() == exec->scopeChain().top());
718 return exec->localStorage()[m_index].value;
719}
720
721JSValue* LocalVarAccessNode::evaluate(OldInterpreterExecState* exec)
722{
723 return inlineEvaluate(exec);
724}
725
726double LocalVarAccessNode::evaluateToNumber(OldInterpreterExecState* exec)
727{
728 return inlineEvaluate(exec)->toNumber(exec);
729}
730
731bool LocalVarAccessNode::evaluateToBoolean(OldInterpreterExecState* exec)
732{
733 return inlineEvaluate(exec)->toBoolean(exec);
734}
735
736int32_t LocalVarAccessNode::evaluateToInt32(OldInterpreterExecState* exec)
737{
738 return inlineEvaluate(exec)->toInt32(exec);
739}
740
741uint32_t LocalVarAccessNode::evaluateToUInt32(OldInterpreterExecState* exec)
742{
743 return inlineEvaluate(exec)->toUInt32(exec);
744}
745
746static inline JSValue* getNonLocalSymbol(OldInterpreterExecState* exec, size_t, size_t scopeDepth)
747{
748 const ScopeChain& chain = exec->scopeChain();
749 ScopeChainIterator iter = chain.begin();
750 for (size_t i = 0; i < scopeDepth; ++iter, ++i)
751 ASSERT(iter != chain.end());
752#ifndef NDEBUG
753 JSObject* scope = *iter;
754#endif
755 ASSERT(scope->isVariableObject());
756 ASSERT_NOT_REACHED();
757 return 0;
758}
759
760JSValue* ScopedVarAccessNode::inlineEvaluate(OldInterpreterExecState* exec)
761{
762 return getNonLocalSymbol(exec, m_index, m_scopeDepth);
763}
764
765JSValue* ScopedVarAccessNode::evaluate(OldInterpreterExecState* exec)
766{
767 return inlineEvaluate(exec);
768}
769
770double ScopedVarAccessNode::evaluateToNumber(OldInterpreterExecState* exec)
771{
772 return inlineEvaluate(exec)->toNumber(exec);
773}
774
775bool ScopedVarAccessNode::evaluateToBoolean(OldInterpreterExecState* exec)
776{
777 return inlineEvaluate(exec)->toBoolean(exec);
778}
779
780int32_t ScopedVarAccessNode::evaluateToInt32(OldInterpreterExecState* exec)
781{
782 return inlineEvaluate(exec)->toInt32(exec);
783}
784
785uint32_t ScopedVarAccessNode::evaluateToUInt32(OldInterpreterExecState* exec)
786{
787 return inlineEvaluate(exec)->toUInt32(exec);
788}
789
790JSValue* NonLocalVarAccessNode::inlineEvaluate(OldInterpreterExecState* exec)
791{
792 // Check for missed optimization opportunity.
793 ASSERT(!canSkipLookup(exec, m_ident));
794
795 const ScopeChain& chain = exec->scopeChain();
796 ScopeChainIterator iter = chain.begin();
797 ScopeChainIterator end = chain.end();
798 for (size_t i = 0; i < m_scopeDepth; ++i, ++iter)
799 ASSERT(iter != end);
800
801 // we must always have something in the scope chain
802 ASSERT(iter != end);
803
804 PropertySlot slot;
805 do {
806 JSObject* o = *iter;
807
808 if (o->getPropertySlot(exec, m_ident, slot))
809 return slot.getValue(exec, o, m_ident);
810
811 ++iter;
812 } while (iter != end);
813
814 return throwUndefinedVariableError(exec, m_ident);
815}
816
817JSValue* NonLocalVarAccessNode::evaluate(OldInterpreterExecState* exec)
818{
819 return inlineEvaluate(exec);
820}
821
822double NonLocalVarAccessNode::evaluateToNumber(OldInterpreterExecState* exec)
823{
824 return inlineEvaluate(exec)->toNumber(exec);
825}
826
827bool NonLocalVarAccessNode::evaluateToBoolean(OldInterpreterExecState* exec)
828{
829 return inlineEvaluate(exec)->toBoolean(exec);
830}
831
832int32_t NonLocalVarAccessNode::evaluateToInt32(OldInterpreterExecState* exec)
833{
834 return inlineEvaluate(exec)->toInt32(exec);
835}
836
837uint32_t NonLocalVarAccessNode::evaluateToUInt32(OldInterpreterExecState* exec)
838{
839 return inlineEvaluate(exec)->toUInt32(exec);
840}
841
842// ------------------------------ ElementNode ----------------------------------
843
844void ElementNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
845{
846 if (m_next)
847 nodeStack.append(m_next.get());
848 ASSERT(m_node);
849 nodeStack.append(m_node.get());
850}
851
852// ECMA 11.1.4
853JSValue* ElementNode::evaluate(OldInterpreterExecState* exec)
854{
855 JSObject* array = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
856 int length = 0;
857 for (ElementNode* n = this; n; n = n->m_next.get()) {
858 JSValue* val = n->m_node->evaluate(exec);
859 KJS_CHECKEXCEPTIONVALUE
860 length += n->m_elision;
861 array->put(exec, length++, val);
862 }
863 return array;
864}
865
866// ------------------------------ ArrayNode ------------------------------------
867
868
869RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst)
870{
871 RefPtr<RegisterID> newArray = generator.emitNewArray(generator.tempDestination(dst));
872 unsigned length = 0;
873
874 RegisterID* value;
875 for (ElementNode* n = m_element.get(); n; n = n->m_next.get()) {
876 value = generator.emitNode(n->m_node.get());
877 length += n->m_elision;
878 generator.emitPutByIndex(newArray.get(), length++, value);
879 }
880
881 value = generator.emitLoad(generator.newTemporary(), jsNumber(m_elision + length));
882 generator.emitPutById(newArray.get(), generator.propertyNames().length, value);
883
884 return generator.moveToDestinationIfNeeded(dst, newArray.get());
885}
886
887void ArrayNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
888{
889 if (m_element)
890 nodeStack.append(m_element.get());
891}
892
893// ECMA 11.1.4
894JSValue* ArrayNode::evaluate(OldInterpreterExecState* exec)
895{
896 JSObject* array;
897 int length;
898
899 if (m_element) {
900 array = static_cast<JSObject*>(m_element->evaluate(exec));
901 KJS_CHECKEXCEPTIONVALUE
902 length = m_optional ? array->get(exec, exec->propertyNames().length)->toInt32(exec) : 0;
903 } else {
904 JSValue* newArr = exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList());
905 array = static_cast<JSObject*>(newArr);
906 length = 0;
907 }
908
909 if (m_optional)
910 array->put(exec, exec->propertyNames().length, jsNumber(m_elision + length));
911
912 return array;
913}
914
915// ------------------------------ ObjectLiteralNode ----------------------------
916
917RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst)
918{
919 if (m_list)
920 return generator.emitNode(dst, m_list.get());
921 else
922 return generator.emitNewObject(generator.finalDestination(dst));
923}
924
925void ObjectLiteralNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
926{
927 if (m_list)
928 nodeStack.append(m_list.get());
929}
930
931// ECMA 11.1.5
932JSValue* ObjectLiteralNode::evaluate(OldInterpreterExecState* exec)
933{
934 if (m_list)
935 return m_list->evaluate(exec);
936
937 return exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
938}
939
940// ------------------------------ PropertyListNode -----------------------------
941
942RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
943{
944 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
945
946 generator.emitNewObject(newObj.get());
947
948 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
949 RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
950
951 switch (p->m_node->m_type) {
952 case PropertyNode::Constant: {
953 generator.emitPutById(newObj.get(), p->m_node->name(), value);
954 break;
955 }
956 case PropertyNode::Getter: {
957 generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
958 break;
959 }
960 case PropertyNode::Setter: {
961 generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
962 break;
963 }
964 default:
965 ASSERT_NOT_REACHED();
966 }
967 }
968
969 return generator.moveToDestinationIfNeeded(dst, newObj.get());
970}
971
972void PropertyListNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
973{
974 if (m_next)
975 nodeStack.append(m_next.get());
976 nodeStack.append(m_node.get());
977}
978
979// ECMA 11.1.5
980JSValue* PropertyListNode::evaluate(OldInterpreterExecState* exec)
981{
982 JSObject* obj = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
983
984 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
985 JSValue* v = p->m_node->m_assign->evaluate(exec);
986 KJS_CHECKEXCEPTIONVALUE
987
988 switch (p->m_node->m_type) {
989 case PropertyNode::Getter:
990 ASSERT(v->isObject());
991 obj->defineGetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
992 break;
993 case PropertyNode::Setter:
994 ASSERT(v->isObject());
995 obj->defineSetter(exec, p->m_node->name(), static_cast<JSObject* >(v));
996 break;
997 case PropertyNode::Constant:
998 obj->put(exec, p->m_node->name(), v);
999 break;
1000 }
1001 }
1002
1003 return obj;
1004}
1005
1006// ------------------------------ PropertyNode -----------------------------
1007
1008void PropertyNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1009{
1010 nodeStack.append(m_assign.get());
1011}
1012
1013// ECMA 11.1.5
1014JSValue* PropertyNode::evaluate(OldInterpreterExecState*)
1015{
1016 ASSERT(false);
1017 return jsNull();
1018}
1019
1020// ------------------------------ BracketAccessorNode --------------------------------
1021
1022RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1023{
1024 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1025 RegisterID* property = generator.emitNode(m_subscript.get());
1026
1027 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
1028}
1029
1030void BracketAccessorNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1031{
1032 nodeStack.append(m_subscript.get());
1033 nodeStack.append(m_base.get());
1034}
1035
1036// ECMA 11.2.1a
1037JSValue* BracketAccessorNode::inlineEvaluate(OldInterpreterExecState* exec)
1038{
1039 JSValue* v1 = m_base->evaluate(exec);
1040 KJS_CHECKEXCEPTIONVALUE
1041 JSValue* v2 = m_subscript->evaluate(exec);
1042 KJS_CHECKEXCEPTIONVALUE
1043 JSObject* o = v1->toObject(exec);
1044 uint32_t i;
1045 if (v2->getUInt32(i))
1046 return o->get(exec, i);
1047 return o->get(exec, Identifier(v2->toString(exec)));
1048}
1049
1050JSValue* BracketAccessorNode::evaluate(OldInterpreterExecState* exec)
1051{
1052 return inlineEvaluate(exec);
1053}
1054
1055double BracketAccessorNode::evaluateToNumber(OldInterpreterExecState* exec)
1056{
1057 JSValue* v = inlineEvaluate(exec);
1058 KJS_CHECKEXCEPTIONNUMBER
1059 return v->toNumber(exec);
1060}
1061
1062bool BracketAccessorNode::evaluateToBoolean(OldInterpreterExecState* exec)
1063{
1064 JSValue* v = inlineEvaluate(exec);
1065 KJS_CHECKEXCEPTIONBOOLEAN
1066 return v->toBoolean(exec);
1067}
1068
1069int32_t BracketAccessorNode::evaluateToInt32(OldInterpreterExecState* exec)
1070{
1071 JSValue* v = inlineEvaluate(exec);
1072 KJS_CHECKEXCEPTIONNUMBER
1073 return v->toInt32(exec);
1074}
1075
1076uint32_t BracketAccessorNode::evaluateToUInt32(OldInterpreterExecState* exec)
1077{
1078 JSValue* v = inlineEvaluate(exec);
1079 KJS_CHECKEXCEPTIONNUMBER
1080 return v->toUInt32(exec);
1081}
1082
1083// ------------------------------ DotAccessorNode --------------------------------
1084
1085RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1086{
1087 RegisterID* base = generator.emitNode(m_base.get());
1088 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
1089}
1090
1091void DotAccessorNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1092{
1093 nodeStack.append(m_base.get());
1094}
1095
1096// ECMA 11.2.1b
1097JSValue* DotAccessorNode::inlineEvaluate(OldInterpreterExecState* exec)
1098{
1099 JSValue* v = m_base->evaluate(exec);
1100 KJS_CHECKEXCEPTIONVALUE
1101 return v->toObject(exec)->get(exec, m_ident);
1102}
1103
1104JSValue* DotAccessorNode::evaluate(OldInterpreterExecState* exec)
1105{
1106 return inlineEvaluate(exec);
1107}
1108
1109double DotAccessorNode::evaluateToNumber(OldInterpreterExecState* exec)
1110{
1111 JSValue* v = inlineEvaluate(exec);
1112 KJS_CHECKEXCEPTIONNUMBER
1113 return v->toNumber(exec);
1114}
1115
1116bool DotAccessorNode::evaluateToBoolean(OldInterpreterExecState* exec)
1117{
1118 JSValue* v = inlineEvaluate(exec);
1119 KJS_CHECKEXCEPTIONBOOLEAN
1120 return v->toBoolean(exec);
1121}
1122
1123int32_t DotAccessorNode::evaluateToInt32(OldInterpreterExecState* exec)
1124{
1125 JSValue* v = inlineEvaluate(exec);
1126 KJS_CHECKEXCEPTIONNUMBER
1127 return v->toInt32(exec);
1128}
1129
1130uint32_t DotAccessorNode::evaluateToUInt32(OldInterpreterExecState* exec)
1131{
1132 JSValue* v = inlineEvaluate(exec);
1133 KJS_CHECKEXCEPTIONNUMBER
1134 return v->toUInt32(exec);
1135}
1136
1137// ------------------------------ ArgumentListNode -----------------------------
1138
1139RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1140{
1141 ASSERT(m_expr);
1142 return generator.emitNode(dst, m_expr.get());
1143}
1144
1145void ArgumentListNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1146{
1147 if (m_next)
1148 nodeStack.append(m_next.get());
1149 ASSERT(m_expr);
1150 nodeStack.append(m_expr.get());
1151}
1152
1153// ECMA 11.2.4
1154void ArgumentListNode::evaluateList(OldInterpreterExecState* exec, List& list)
1155{
1156 for (ArgumentListNode* n = this; n; n = n->m_next.get()) {
1157 JSValue* v = n->m_expr->evaluate(exec);
1158 KJS_CHECKEXCEPTIONVOID
1159 list.append(v);
1160 }
1161}
1162
1163// ------------------------------ ArgumentsNode --------------------------------
1164
1165void ArgumentsNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1166{
1167 if (m_listNode)
1168 nodeStack.append(m_listNode.get());
1169}
1170
1171// ------------------------------ NewExprNode ----------------------------------
1172
1173RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1174{
1175 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
1176 return generator.emitConstruct(generator.finalDestination(dst), r0.get(), m_args.get());
1177}
1178
1179void NewExprNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1180{
1181 if (m_args)
1182 nodeStack.append(m_args.get());
1183 nodeStack.append(m_expr.get());
1184}
1185
1186// ECMA 11.2.2
1187
1188JSValue* NewExprNode::inlineEvaluate(OldInterpreterExecState* exec)
1189{
1190 JSValue* v = m_expr->evaluate(exec);
1191 KJS_CHECKEXCEPTIONVALUE
1192
1193 List argList;
1194 if (m_args) {
1195 m_args->evaluateList(exec, argList);
1196 KJS_CHECKEXCEPTIONVALUE
1197 }
1198
1199 if (!v->isObject())
1200 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, m_expr.get());
1201
1202 ConstructData constructData;
1203 if (v->getConstructData(constructData) == ConstructTypeNone)
1204 return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, m_expr.get());
1205
1206 return static_cast<JSObject*>(v)->construct(exec, argList);
1207}
1208
1209JSValue* NewExprNode::evaluate(OldInterpreterExecState* exec)
1210{
1211 return inlineEvaluate(exec);
1212}
1213
1214double NewExprNode::evaluateToNumber(OldInterpreterExecState* exec)
1215{
1216 JSValue* v = inlineEvaluate(exec);
1217 KJS_CHECKEXCEPTIONNUMBER
1218 return v->toNumber(exec);
1219}
1220
1221bool NewExprNode::evaluateToBoolean(OldInterpreterExecState* exec)
1222{
1223 JSValue* v = inlineEvaluate(exec);
1224 KJS_CHECKEXCEPTIONBOOLEAN
1225 return v->toBoolean(exec);
1226}
1227
1228int32_t NewExprNode::evaluateToInt32(OldInterpreterExecState* exec)
1229{
1230 JSValue* v = inlineEvaluate(exec);
1231 KJS_CHECKEXCEPTIONNUMBER
1232 return v->toInt32(exec);
1233}
1234
1235uint32_t NewExprNode::evaluateToUInt32(OldInterpreterExecState* exec)
1236{
1237 JSValue* v = inlineEvaluate(exec);
1238 KJS_CHECKEXCEPTIONNUMBER
1239 return v->toUInt32(exec);
1240}
1241
1242template <ExpressionNode::CallerType callerType, bool scopeDepthIsZero>
1243inline JSValue* ExpressionNode::resolveAndCall(OldInterpreterExecState* exec, const Identifier& ident, ArgumentsNode* args, size_t scopeDepth)
1244{
1245 const ScopeChain& chain = exec->scopeChain();
1246 ScopeChainIterator iter = chain.begin();
1247 ScopeChainIterator end = chain.end();
1248
1249 if (!scopeDepthIsZero) {
1250 for (size_t i = 0; i < scopeDepth; ++iter, ++i)
1251 ASSERT(iter != chain.end());
1252 }
1253
1254 // we must always have something in the scope chain
1255 ASSERT(iter != end);
1256
1257 PropertySlot slot;
1258 JSObject* base;
1259 do {
1260 base = *iter;
1261 if (base->getPropertySlot(exec, ident, slot)) {
1262 JSValue* v = slot.getValue(exec, base, ident);
1263 KJS_CHECKEXCEPTIONVALUE
1264
1265 if (!v->isObject())
1266 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
1267
1268 JSObject* func = static_cast<JSObject*>(v);
1269
1270 if (!func->implementsCall())
1271 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
1272
1273 List argList;
1274 args->evaluateList(exec, argList);
1275 KJS_CHECKEXCEPTIONVALUE
1276
1277 if (callerType == EvalOperator) {
1278 if (base == exec->lexicalGlobalObject() && func == exec->lexicalGlobalObject()->evalFunction()) {
1279 ASSERT_NOT_REACHED();
1280 }
1281 }
1282
1283 JSObject* thisObj = base->toThisObject(exec);
1284 return func->call(exec, thisObj, argList);
1285 }
1286 ++iter;
1287 } while (iter != end);
1288
1289 return throwUndefinedVariableError(exec, ident);
1290}
1291
1292RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1293{
1294 RefPtr<RegisterID> base = generator.tempDestination(dst);
1295 RegisterID* func = generator.newTemporary();
1296 generator.emitResolveWithBase(base.get(), func, CommonIdentifiers::shared()->eval);
1297 return generator.emitCallEval(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get());
1298}
1299
1300void EvalFunctionCallNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1301{
1302 nodeStack.append(m_args.get());
1303}
1304
1305JSValue* EvalFunctionCallNode::evaluate(OldInterpreterExecState* exec)
1306{
1307 return resolveAndCall<EvalOperator, true>(exec, exec->propertyNames().eval, m_args.get());
1308}
1309
1310RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1311{
1312 RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
1313 return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get());
1314}
1315
1316void FunctionCallValueNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1317{
1318 nodeStack.append(m_args.get());
1319 nodeStack.append(m_expr.get());
1320}
1321
1322// ECMA 11.2.3
1323JSValue* FunctionCallValueNode::evaluate(OldInterpreterExecState* exec)
1324{
1325 JSValue* v = m_expr->evaluate(exec);
1326 KJS_CHECKEXCEPTIONVALUE
1327
1328 if (!v->isObject()) {
1329 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_expr.get());
1330 }
1331
1332 JSObject* func = static_cast<JSObject*>(v);
1333
1334 if (!func->implementsCall()) {
1335 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_expr.get());
1336 }
1337
1338 List argList;
1339 m_args->evaluateList(exec, argList);
1340 KJS_CHECKEXCEPTIONVALUE
1341
1342 JSObject* thisObj = exec->globalThisValue();
1343 return func->call(exec, thisObj, argList);
1344}
1345
1346RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1347{
1348 if (RegisterID* local = generator.registerForLocal(m_ident))
1349 return generator.emitCall(generator.finalDestination(dst), local, 0, m_args.get());
1350
1351 int index = 0;
1352 size_t depth = 0;
1353 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
1354 RegisterID* func = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
1355 return generator.emitCall(generator.finalDestination(dst), func, 0, m_args.get());
1356 }
1357
1358 RefPtr<RegisterID> base = generator.tempDestination(dst);
1359 RegisterID* func = generator.newTemporary();
1360 generator.emitResolveFunction(base.get(), func, m_ident);
1361 return generator.emitCall(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get());
1362}
1363
1364void FunctionCallResolveNode::optimizeVariableAccess(OldInterpreterExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
1365{
1366 nodeStack.append(m_args.get());
1367
1368 size_t depth = 0;
1369 int index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
1370 if (index != missingSymbolMarker()) {
1371 if (!depth)
1372 new (this) LocalVarFunctionCallNode(index);
1373 else
1374 new (this) ScopedVarFunctionCallNode(index, depth);
1375 return;
1376 }
1377
1378 if (!depth)
1379 return;
1380
1381 new (this) NonLocalVarFunctionCallNode(depth);
1382}
1383
1384// ECMA 11.2.3
1385JSValue* FunctionCallResolveNode::inlineEvaluate(OldInterpreterExecState* exec)
1386{
1387 // Check for missed optimization opportunity.
1388 ASSERT(!canSkipLookup(exec, m_ident));
1389
1390 return resolveAndCall<FunctionCall, true>(exec, m_ident, m_args.get());
1391}
1392
1393JSValue* FunctionCallResolveNode::evaluate(OldInterpreterExecState* exec)
1394{
1395 return inlineEvaluate(exec);
1396}
1397
1398double FunctionCallResolveNode::evaluateToNumber(OldInterpreterExecState* exec)
1399{
1400 JSValue* v = inlineEvaluate(exec);
1401 KJS_CHECKEXCEPTIONNUMBER
1402 return v->toNumber(exec);
1403}
1404
1405bool FunctionCallResolveNode::evaluateToBoolean(OldInterpreterExecState* exec)
1406{
1407 JSValue* v = inlineEvaluate(exec);
1408 KJS_CHECKEXCEPTIONBOOLEAN
1409 return v->toBoolean(exec);
1410}
1411
1412int32_t FunctionCallResolveNode::evaluateToInt32(OldInterpreterExecState* exec)
1413{
1414 JSValue* v = inlineEvaluate(exec);
1415 KJS_CHECKEXCEPTIONNUMBER
1416 return v->toInt32(exec);
1417}
1418
1419uint32_t FunctionCallResolveNode::evaluateToUInt32(OldInterpreterExecState* exec)
1420{
1421 JSValue* v = inlineEvaluate(exec);
1422 KJS_CHECKEXCEPTIONNUMBER
1423 return v->toUInt32(exec);
1424}
1425
1426JSValue* LocalVarFunctionCallNode::inlineEvaluate(OldInterpreterExecState* exec)
1427{
1428 ASSERT(exec->variableObject() == exec->scopeChain().top());
1429
1430 JSValue* v = exec->localStorage()[m_index].value;
1431
1432 if (!v->isObject())
1433 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
1434
1435 JSObject* func = static_cast<JSObject*>(v);
1436 if (!func->implementsCall())
1437 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
1438
1439 List argList;
1440 m_args->evaluateList(exec, argList);
1441 KJS_CHECKEXCEPTIONVALUE
1442
1443 JSObject* thisObj = exec->globalThisValue();
1444 return func->call(exec, thisObj, argList);
1445}
1446
1447JSValue* LocalVarFunctionCallNode::evaluate(OldInterpreterExecState* exec)
1448{
1449 return inlineEvaluate(exec);
1450}
1451
1452double LocalVarFunctionCallNode::evaluateToNumber(OldInterpreterExecState* exec)
1453{
1454 JSValue* v = inlineEvaluate(exec);
1455 KJS_CHECKEXCEPTIONNUMBER
1456 return v->toNumber(exec);
1457}
1458
1459bool LocalVarFunctionCallNode::evaluateToBoolean(OldInterpreterExecState* exec)
1460{
1461 JSValue* v = inlineEvaluate(exec);
1462 KJS_CHECKEXCEPTIONBOOLEAN
1463 return v->toBoolean(exec);
1464}
1465
1466int32_t LocalVarFunctionCallNode::evaluateToInt32(OldInterpreterExecState* exec)
1467{
1468 JSValue* v = inlineEvaluate(exec);
1469 KJS_CHECKEXCEPTIONNUMBER
1470 return v->toInt32(exec);
1471}
1472
1473uint32_t LocalVarFunctionCallNode::evaluateToUInt32(OldInterpreterExecState* exec)
1474{
1475 JSValue* v = inlineEvaluate(exec);
1476 KJS_CHECKEXCEPTIONNUMBER
1477 return v->toUInt32(exec);
1478}
1479
1480JSValue* ScopedVarFunctionCallNode::inlineEvaluate(OldInterpreterExecState* exec)
1481{
1482 ASSERT(exec->variableObject() == exec->scopeChain().top());
1483
1484 JSValue* v = getNonLocalSymbol(exec, m_index, m_scopeDepth);
1485
1486 if (!v->isObject())
1487 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
1488
1489 JSObject* func = static_cast<JSObject*>(v);
1490 if (!func->implementsCall())
1491 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
1492
1493 List argList;
1494 m_args->evaluateList(exec, argList);
1495 KJS_CHECKEXCEPTIONVALUE
1496
1497 JSObject* thisObj = exec->globalThisValue();
1498 return func->call(exec, thisObj, argList);
1499}
1500
1501JSValue* ScopedVarFunctionCallNode::evaluate(OldInterpreterExecState* exec)
1502{
1503 return inlineEvaluate(exec);
1504}
1505
1506double ScopedVarFunctionCallNode::evaluateToNumber(OldInterpreterExecState* exec)
1507{
1508 JSValue* v = inlineEvaluate(exec);
1509 KJS_CHECKEXCEPTIONNUMBER
1510 return v->toNumber(exec);
1511}
1512
1513bool ScopedVarFunctionCallNode::evaluateToBoolean(OldInterpreterExecState* exec)
1514{
1515 JSValue* v = inlineEvaluate(exec);
1516 KJS_CHECKEXCEPTIONBOOLEAN
1517 return v->toBoolean(exec);
1518}
1519
1520int32_t ScopedVarFunctionCallNode::evaluateToInt32(OldInterpreterExecState* exec)
1521{
1522 JSValue* v = inlineEvaluate(exec);
1523 KJS_CHECKEXCEPTIONNUMBER
1524 return v->toInt32(exec);
1525}
1526
1527uint32_t ScopedVarFunctionCallNode::evaluateToUInt32(OldInterpreterExecState* exec)
1528{
1529 JSValue* v = inlineEvaluate(exec);
1530 KJS_CHECKEXCEPTIONNUMBER
1531 return v->toUInt32(exec);
1532}
1533
1534JSValue* NonLocalVarFunctionCallNode::inlineEvaluate(OldInterpreterExecState* exec)
1535{
1536 // Check for missed optimization opportunity.
1537 ASSERT(!canSkipLookup(exec, m_ident));
1538
1539 return resolveAndCall<FunctionCall, false>(exec, m_ident, m_args.get(), m_scopeDepth);
1540}
1541
1542JSValue* NonLocalVarFunctionCallNode::evaluate(OldInterpreterExecState* exec)
1543{
1544 return inlineEvaluate(exec);
1545}
1546
1547double NonLocalVarFunctionCallNode::evaluateToNumber(OldInterpreterExecState* exec)
1548{
1549 JSValue* v = inlineEvaluate(exec);
1550 KJS_CHECKEXCEPTIONNUMBER
1551 return v->toNumber(exec);
1552}
1553
1554bool NonLocalVarFunctionCallNode::evaluateToBoolean(OldInterpreterExecState* exec)
1555{
1556 JSValue* v = inlineEvaluate(exec);
1557 KJS_CHECKEXCEPTIONBOOLEAN
1558 return v->toBoolean(exec);
1559}
1560
1561int32_t NonLocalVarFunctionCallNode::evaluateToInt32(OldInterpreterExecState* exec)
1562{
1563 JSValue* v = inlineEvaluate(exec);
1564 KJS_CHECKEXCEPTIONNUMBER
1565 return v->toInt32(exec);
1566}
1567
1568uint32_t NonLocalVarFunctionCallNode::evaluateToUInt32(OldInterpreterExecState* exec)
1569{
1570 JSValue* v = inlineEvaluate(exec);
1571 KJS_CHECKEXCEPTIONNUMBER
1572 return v->toUInt32(exec);
1573}
1574
1575RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1576{
1577 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1578 RegisterID* property = generator.emitNode(m_subscript.get());
1579 RegisterID* function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
1580 return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get());
1581}
1582
1583void FunctionCallBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1584{
1585 nodeStack.append(m_args.get());
1586 nodeStack.append(m_subscript.get());
1587 nodeStack.append(m_base.get());
1588}
1589
1590// ECMA 11.2.3
1591JSValue* FunctionCallBracketNode::evaluate(OldInterpreterExecState* exec)
1592{
1593 JSValue* baseVal = m_base->evaluate(exec);
1594 KJS_CHECKEXCEPTIONVALUE
1595
1596 JSValue* subscriptVal = m_subscript->evaluate(exec);
1597
1598 JSObject* baseObj = baseVal->toObject(exec);
1599 uint32_t i;
1600 PropertySlot slot;
1601
1602 JSValue* funcVal;
1603 if (subscriptVal->getUInt32(i)) {
1604 if (baseObj->getPropertySlot(exec, i, slot))
1605 funcVal = slot.getValue(exec, baseObj, i);
1606 else
1607 funcVal = jsUndefined();
1608 } else {
1609 Identifier ident(subscriptVal->toString(exec));
1610 if (baseObj->getPropertySlot(exec, ident, slot))
1611 funcVal = baseObj->get(exec, ident);
1612 else
1613 funcVal = jsUndefined();
1614 }
1615
1616 KJS_CHECKEXCEPTIONVALUE
1617
1618 if (!funcVal->isObject())
1619 return throwError(exec, TypeError, "Value %s (result of expression %s[%s]) is not object.", funcVal, m_base.get(), m_subscript.get());
1620
1621 JSObject* func = static_cast<JSObject*>(funcVal);
1622
1623 if (!func->implementsCall())
1624 return throwError(exec, TypeError, "Object %s (result of expression %s[%s]) does not allow calls.", funcVal, m_base.get(), m_subscript.get());
1625
1626 List argList;
1627 m_args->evaluateList(exec, argList);
1628 KJS_CHECKEXCEPTIONVALUE
1629
1630 JSObject* thisObj = baseObj;
1631 ASSERT(thisObj);
1632 ASSERT(thisObj->isObject());
1633 ASSERT(!thisObj->isActivationObject());
1634
1635 // No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
1636 return func->call(exec, thisObj, argList);
1637}
1638
1639static const char* dotExprNotAnObjectString() KJS_FAST_CALL;
1640static const char* dotExprNotAnObjectString()
1641{
1642 return "Value %s (result of expression %s.%s) is not object.";
1643}
1644
1645static const char* dotExprDoesNotAllowCallsString() KJS_FAST_CALL;
1646static const char* dotExprDoesNotAllowCallsString()
1647{
1648 return "Object %s (result of expression %s.%s) does not allow calls.";
1649}
1650
1651RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1652{
1653 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1654 RegisterID* function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
1655 return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get());
1656}
1657
1658void FunctionCallDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1659{
1660 nodeStack.append(m_args.get());
1661 nodeStack.append(m_base.get());
1662}
1663
1664// ECMA 11.2.3
1665JSValue* FunctionCallDotNode::inlineEvaluate(OldInterpreterExecState* exec)
1666{
1667 JSValue* baseVal = m_base->evaluate(exec);
1668 KJS_CHECKEXCEPTIONVALUE
1669
1670 JSObject* baseObj = baseVal->toObject(exec);
1671 PropertySlot slot;
1672 JSValue* funcVal = baseObj->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, baseObj, m_ident) : jsUndefined();
1673 KJS_CHECKEXCEPTIONVALUE
1674
1675 if (!funcVal->isObject())
1676 return throwError(exec, TypeError, dotExprNotAnObjectString(), funcVal, m_base.get(), m_ident);
1677
1678 JSObject* func = static_cast<JSObject*>(funcVal);
1679
1680 if (!func->implementsCall())
1681 return throwError(exec, TypeError, dotExprDoesNotAllowCallsString(), funcVal, m_base.get(), m_ident);
1682
1683 List argList;
1684 m_args->evaluateList(exec, argList);
1685 KJS_CHECKEXCEPTIONVALUE
1686
1687 JSObject* thisObj = baseObj;
1688 ASSERT(thisObj);
1689 ASSERT(thisObj->isObject());
1690 ASSERT(!thisObj->isActivationObject());
1691
1692 // No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
1693 return func->call(exec, thisObj, argList);
1694}
1695
1696JSValue* FunctionCallDotNode::evaluate(OldInterpreterExecState* exec)
1697{
1698 return inlineEvaluate(exec);
1699}
1700
1701double FunctionCallDotNode::evaluateToNumber(OldInterpreterExecState* exec)
1702{
1703 JSValue* v = inlineEvaluate(exec);
1704 KJS_CHECKEXCEPTIONNUMBER
1705 return v->toNumber(exec);
1706}
1707
1708bool FunctionCallDotNode::evaluateToBoolean(OldInterpreterExecState* exec)
1709{
1710 JSValue* v = inlineEvaluate(exec);
1711 KJS_CHECKEXCEPTIONBOOLEAN
1712 return v->toBoolean(exec);
1713}
1714
1715int32_t FunctionCallDotNode::evaluateToInt32(OldInterpreterExecState* exec)
1716{
1717 JSValue* v = inlineEvaluate(exec);
1718 KJS_CHECKEXCEPTIONNUMBER
1719 return v->toInt32(exec);
1720}
1721
1722uint32_t FunctionCallDotNode::evaluateToUInt32(OldInterpreterExecState* exec)
1723{
1724 JSValue* v = inlineEvaluate(exec);
1725 KJS_CHECKEXCEPTIONNUMBER
1726 return v->toUInt32(exec);
1727}
1728
1729// ECMA 11.3
1730
1731// ------------------------------ PostfixResolveNode ----------------------------------
1732
1733RegisterID* PostIncResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1734{
1735 // FIXME: I think we can detect the absense of dependent expressions here,
1736 // and emit a PreInc instead of a PostInc. A post-pass to eliminate dead
1737 // code would work, too.
1738 if (RegisterID* local = generator.registerForLocal(m_ident)) {
1739 if (generator.isLocalConstant(m_ident))
1740 return generator.emitToJSNumber(generator.finalDestination(dst), local);
1741
1742 return generator.emitPostInc(generator.finalDestination(dst), local);
1743 }
1744
1745 int index = 0;
1746 size_t depth = 0;
1747 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
1748 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
1749 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
1750 generator.emitPutScopedVar(depth, index, value.get());
1751 return oldValue;
1752 }
1753
1754 RefPtr<RegisterID> value = generator.newTemporary();
1755 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
1756 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
1757 generator.emitPutById(base.get(), m_ident, value.get());
1758 return oldValue;
1759}
1760
1761// Increment
1762void PostIncResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
1763{
1764 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
1765 if (index != missingSymbolMarker()) {
1766 if (isConstant(localStorage, index))
1767 new (this) PostIncConstNode(index);
1768 else
1769 new (this) PostIncLocalVarNode(index);
1770 }
1771}
1772
1773JSValue* PostIncResolveNode::evaluate(OldInterpreterExecState* exec)
1774{
1775 // Check for missed optimization opportunity.
1776 ASSERT(!canSkipLookup(exec, m_ident));
1777
1778 const ScopeChain& chain = exec->scopeChain();
1779 ScopeChainIterator iter = chain.begin();
1780 ScopeChainIterator end = chain.end();
1781
1782 // we must always have something in the scope chain
1783 ASSERT(iter != end);
1784
1785 PropertySlot slot;
1786 do {
1787 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
1788 // If m_ident is 'arguments', the base->getPropertySlot() may cause
1789 // base (which must be an ActivationImp in such this case) to be torn
1790 // off from the activation stack, in which case we need to get it again
1791 // from the ScopeChainIterator.
1792
1793 JSObject* base = *iter;
1794 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
1795 base->put(exec, m_ident, jsNumber(v->toNumber(exec) + 1));
1796 return v;
1797 }
1798
1799 ++iter;
1800 } while (iter != end);
1801
1802 return throwUndefinedVariableError(exec, m_ident);
1803}
1804
1805void PostIncResolveNode::optimizeForUnnecessaryResult()
1806{
1807 new (this) PreIncResolveNode(PlacementNewAdopt);
1808}
1809
1810JSValue* PostIncLocalVarNode::evaluate(OldInterpreterExecState* exec)
1811{
1812 ASSERT(exec->variableObject() == exec->scopeChain().top());
1813
1814 JSValue** slot = &exec->localStorage()[m_index].value;
1815 JSValue* v = (*slot)->toJSNumber(exec);
1816 *slot = jsNumber(v->toNumber(exec) + 1);
1817 return v;
1818}
1819
1820void PostIncLocalVarNode::optimizeForUnnecessaryResult()
1821{
1822 new (this) PreIncLocalVarNode(m_index);
1823}
1824
1825// Decrement
1826RegisterID* PostDecResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1827{
1828 // FIXME: I think we can detect the absense of dependent expressions here,
1829 // and emit a PreDec instead of a PostDec. A post-pass to eliminate dead
1830 // code would work, too.
1831 if (RegisterID* local = generator.registerForLocal(m_ident)) {
1832 if (generator.isLocalConstant(m_ident))
1833 return generator.emitToJSNumber(generator.finalDestination(dst), local);
1834
1835 return generator.emitPostDec(generator.finalDestination(dst), local);
1836 }
1837
1838 int index = 0;
1839 size_t depth = 0;
1840 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
1841 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
1842 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
1843 generator.emitPutScopedVar(depth, index, value.get());
1844 return oldValue;
1845 }
1846
1847 RefPtr<RegisterID> value = generator.newTemporary();
1848 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
1849 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
1850 generator.emitPutById(base.get(), m_ident, value.get());
1851 return oldValue;
1852}
1853
1854void PostDecResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
1855{
1856 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
1857 if (index != missingSymbolMarker()) {
1858 if (isConstant(localStorage, index))
1859 new (this) PostDecConstNode(index);
1860 else
1861 new (this) PostDecLocalVarNode(index);
1862 }
1863}
1864
1865JSValue* PostDecResolveNode::evaluate(OldInterpreterExecState* exec)
1866{
1867 // Check for missed optimization opportunity.
1868 ASSERT(!canSkipLookup(exec, m_ident));
1869
1870 const ScopeChain& chain = exec->scopeChain();
1871 ScopeChainIterator iter = chain.begin();
1872 ScopeChainIterator end = chain.end();
1873
1874 // we must always have something in the scope chain
1875 ASSERT(iter != end);
1876
1877 PropertySlot slot;
1878 do {
1879 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
1880 // See the comment in PostIncResolveNode::evaluate().
1881
1882 JSObject* base = *iter;
1883 JSValue* v = slot.getValue(exec, base, m_ident)->toJSNumber(exec);
1884 base->put(exec, m_ident, jsNumber(v->toNumber(exec) - 1));
1885 return v;
1886 }
1887
1888 ++iter;
1889 } while (iter != end);
1890
1891 return throwUndefinedVariableError(exec, m_ident);
1892}
1893
1894void PostDecResolveNode::optimizeForUnnecessaryResult()
1895{
1896 new (this) PreDecResolveNode(PlacementNewAdopt);
1897}
1898
1899JSValue* PostDecLocalVarNode::evaluate(OldInterpreterExecState* exec)
1900{
1901 ASSERT(exec->variableObject() == exec->scopeChain().top());
1902
1903 JSValue** slot = &exec->localStorage()[m_index].value;
1904 JSValue* v = (*slot)->toJSNumber(exec);
1905 *slot = jsNumber(v->toNumber(exec) - 1);
1906 return v;
1907}
1908
1909double PostDecLocalVarNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
1910{
1911 ASSERT(exec->variableObject() == exec->scopeChain().top());
1912
1913 JSValue** slot = &exec->localStorage()[m_index].value;
1914 double n = (*slot)->toNumber(exec);
1915 *slot = jsNumber(n - 1);
1916 return n;
1917}
1918
1919double PostDecLocalVarNode::evaluateToNumber(OldInterpreterExecState* exec)
1920{
1921 return inlineEvaluateToNumber(exec);
1922}
1923
1924bool PostDecLocalVarNode::evaluateToBoolean(OldInterpreterExecState* exec)
1925{
1926 double result = inlineEvaluateToNumber(exec);
1927 return result > 0.0 || 0.0 > result; // NaN produces false as well
1928}
1929
1930int32_t PostDecLocalVarNode::evaluateToInt32(OldInterpreterExecState* exec)
1931{
1932 return JSValue::toInt32(inlineEvaluateToNumber(exec));
1933}
1934
1935uint32_t PostDecLocalVarNode::evaluateToUInt32(OldInterpreterExecState* exec)
1936{
1937 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
1938}
1939
1940void PostDecLocalVarNode::optimizeForUnnecessaryResult()
1941{
1942 new (this) PreDecLocalVarNode(m_index);
1943}
1944
1945// ------------------------------ PostfixBracketNode ----------------------------------
1946
1947void PostfixBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
1948{
1949 nodeStack.append(m_subscript.get());
1950 nodeStack.append(m_base.get());
1951}
1952
1953RegisterID* PostIncBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1954{
1955 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1956 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
1957 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
1958 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
1959 generator.emitPutByVal(base.get(), property.get(), value.get());
1960 return oldValue;
1961}
1962
1963JSValue* PostIncBracketNode::evaluate(OldInterpreterExecState* exec)
1964{
1965 JSValue* baseValue = m_base->evaluate(exec);
1966 KJS_CHECKEXCEPTIONVALUE
1967 JSValue* subscript = m_subscript->evaluate(exec);
1968 KJS_CHECKEXCEPTIONVALUE
1969
1970 JSObject* base = baseValue->toObject(exec);
1971
1972 uint32_t propertyIndex;
1973 if (subscript->getUInt32(propertyIndex)) {
1974 PropertySlot slot;
1975 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1976 KJS_CHECKEXCEPTIONVALUE
1977
1978 JSValue* v2 = v->toJSNumber(exec);
1979 base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) + 1));
1980
1981 return v2;
1982 }
1983
1984 Identifier propertyName(subscript->toString(exec));
1985 PropertySlot slot;
1986 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1987 KJS_CHECKEXCEPTIONVALUE
1988
1989 JSValue* v2 = v->toJSNumber(exec);
1990 base->put(exec, propertyName, jsNumber(v2->toNumber(exec) + 1));
1991 return v2;
1992}
1993
1994RegisterID* PostDecBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1995{
1996 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1997 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
1998 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
1999 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
2000 generator.emitPutByVal(base.get(), property.get(), value.get());
2001 return oldValue;
2002}
2003
2004JSValue* PostDecBracketNode::evaluate(OldInterpreterExecState* exec)
2005{
2006 JSValue* baseValue = m_base->evaluate(exec);
2007 KJS_CHECKEXCEPTIONVALUE
2008 JSValue* subscript = m_subscript->evaluate(exec);
2009 KJS_CHECKEXCEPTIONVALUE
2010
2011 JSObject* base = baseValue->toObject(exec);
2012
2013 uint32_t propertyIndex;
2014 if (subscript->getUInt32(propertyIndex)) {
2015 PropertySlot slot;
2016 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2017 KJS_CHECKEXCEPTIONVALUE
2018
2019 JSValue* v2 = v->toJSNumber(exec);
2020 base->put(exec, propertyIndex, jsNumber(v2->toNumber(exec) - 1));
2021 return v2;
2022 }
2023
2024 Identifier propertyName(subscript->toString(exec));
2025 PropertySlot slot;
2026 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2027 KJS_CHECKEXCEPTIONVALUE
2028
2029 JSValue* v2 = v->toJSNumber(exec);
2030 base->put(exec, propertyName, jsNumber(v2->toNumber(exec) - 1));
2031 return v2;
2032}
2033
2034// ------------------------------ PostfixDotNode ----------------------------------
2035
2036void PostfixDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2037{
2038 nodeStack.append(m_base.get());
2039}
2040
2041RegisterID* PostIncDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2042{
2043 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2044 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
2045 RegisterID* oldValue = generator.emitPostInc(generator.finalDestination(dst), value.get());
2046 generator.emitPutById(base.get(), m_ident, value.get());
2047 return oldValue;
2048}
2049
2050JSValue* PostIncDotNode::evaluate(OldInterpreterExecState* exec)
2051{
2052 JSValue* baseValue = m_base->evaluate(exec);
2053 KJS_CHECKEXCEPTIONVALUE
2054 JSObject* base = baseValue->toObject(exec);
2055
2056 PropertySlot slot;
2057 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2058 KJS_CHECKEXCEPTIONVALUE
2059
2060 JSValue* v2 = v->toJSNumber(exec);
2061 base->put(exec, m_ident, jsNumber(v2->toNumber(exec) + 1));
2062 return v2;
2063}
2064
2065RegisterID* PostDecDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2066{
2067 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2068 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
2069 RegisterID* oldValue = generator.emitPostDec(generator.finalDestination(dst), value.get());
2070 generator.emitPutById(base.get(), m_ident, value.get());
2071 return oldValue;
2072}
2073
2074JSValue* PostDecDotNode::evaluate(OldInterpreterExecState* exec)
2075{
2076 JSValue* baseValue = m_base->evaluate(exec);
2077 KJS_CHECKEXCEPTIONVALUE
2078 JSObject* base = baseValue->toObject(exec);
2079
2080 PropertySlot slot;
2081 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2082 KJS_CHECKEXCEPTIONVALUE
2083
2084 JSValue* v2 = v->toJSNumber(exec);
2085 base->put(exec, m_ident, jsNumber(v2->toNumber(exec) - 1));
2086 return v2;
2087}
2088
2089// ------------------------------ PostfixErrorNode -----------------------------------
2090
2091RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
2092{
2093 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference.");
2094}
2095
2096JSValue* PostfixErrorNode::evaluate(OldInterpreterExecState* exec)
2097{
2098 throwError(exec, ReferenceError, "Postfix %s operator applied to value that is not a reference.",
2099 m_operator == OpPlusPlus ? "++" : "--");
2100 handleException(exec);
2101 return jsUndefined();
2102}
2103
2104// ------------------------------ DeleteResolveNode -----------------------------------
2105
2106RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2107{
2108 if (generator.registerForLocal(m_ident))
2109 return generator.emitLoad(generator.finalDestination(dst), false);
2110
2111 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
2112 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
2113}
2114
2115void DeleteResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
2116{
2117 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
2118 if (index != missingSymbolMarker())
2119 new (this) LocalVarDeleteNode();
2120}
2121
2122// ECMA 11.4.1
2123
2124JSValue* DeleteResolveNode::evaluate(OldInterpreterExecState* exec)
2125{
2126 // Check for missed optimization opportunity.
2127 ASSERT(!canSkipLookup(exec, m_ident));
2128
2129 const ScopeChain& chain = exec->scopeChain();
2130 ScopeChainIterator iter = chain.begin();
2131 ScopeChainIterator end = chain.end();
2132
2133 // We must always have something in the scope chain
2134 ASSERT(iter != end);
2135
2136 PropertySlot slot;
2137 JSObject* base;
2138 do {
2139 base = *iter;
2140 if (base->getPropertySlot(exec, m_ident, slot))
2141 return jsBoolean(base->deleteProperty(exec, m_ident));
2142
2143 ++iter;
2144 } while (iter != end);
2145
2146 return jsBoolean(true);
2147}
2148
2149JSValue* LocalVarDeleteNode::evaluate(OldInterpreterExecState*)
2150{
2151 return jsBoolean(false);
2152}
2153
2154// ------------------------------ DeleteBracketNode -----------------------------------
2155
2156RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2157{
2158 RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
2159 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript.get());
2160 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
2161}
2162
2163void DeleteBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2164{
2165 nodeStack.append(m_subscript.get());
2166 nodeStack.append(m_base.get());
2167}
2168
2169JSValue* DeleteBracketNode::evaluate(OldInterpreterExecState* exec)
2170{
2171 JSValue* baseValue = m_base->evaluate(exec);
2172 KJS_CHECKEXCEPTIONVALUE
2173 JSValue* subscript = m_subscript->evaluate(exec);
2174 KJS_CHECKEXCEPTIONVALUE
2175
2176 JSObject* base = baseValue->toObject(exec);
2177
2178 uint32_t propertyIndex;
2179 if (subscript->getUInt32(propertyIndex))
2180 return jsBoolean(base->deleteProperty(exec, propertyIndex));
2181
2182 Identifier propertyName(subscript->toString(exec));
2183 return jsBoolean(base->deleteProperty(exec, propertyName));
2184}
2185
2186// ------------------------------ DeleteDotNode -----------------------------------
2187
2188RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2189{
2190 RegisterID* r0 = generator.emitNode(m_base.get());
2191 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
2192}
2193
2194void DeleteDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2195{
2196 nodeStack.append(m_base.get());
2197}
2198
2199JSValue* DeleteDotNode::evaluate(OldInterpreterExecState* exec)
2200{
2201 JSValue* baseValue = m_base->evaluate(exec);
2202 JSObject* base = baseValue->toObject(exec);
2203 KJS_CHECKEXCEPTIONVALUE
2204
2205 return jsBoolean(base->deleteProperty(exec, m_ident));
2206}
2207
2208// ------------------------------ DeleteValueNode -----------------------------------
2209
2210RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2211{
2212 generator.emitNode(m_expr.get());
2213
2214 // delete on a non-location expression ignores the value and returns true
2215 return generator.emitLoad(generator.finalDestination(dst), true);
2216}
2217
2218void DeleteValueNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2219{
2220 nodeStack.append(m_expr.get());
2221}
2222
2223JSValue* DeleteValueNode::evaluate(OldInterpreterExecState* exec)
2224{
2225 m_expr->evaluate(exec);
2226 KJS_CHECKEXCEPTIONVALUE
2227
2228 // delete on a non-location expression ignores the value and returns true
2229 return jsBoolean(true);
2230}
2231
2232// ------------------------------ VoidNode -------------------------------------
2233
2234RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2235{
2236 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
2237 return generator.emitLoad(generator.finalDestination(dst, r0.get()), jsUndefined());
2238}
2239
2240void VoidNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2241{
2242 nodeStack.append(m_expr.get());
2243}
2244
2245// ECMA 11.4.2
2246JSValue* VoidNode::evaluate(OldInterpreterExecState* exec)
2247{
2248 m_expr->evaluate(exec);
2249 KJS_CHECKEXCEPTIONVALUE
2250
2251 return jsUndefined();
2252}
2253
2254// ECMA 11.4.3
2255
2256// ------------------------------ TypeOfValueNode -----------------------------------
2257
2258void TypeOfValueNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2259{
2260 nodeStack.append(m_expr.get());
2261}
2262
2263static JSValue* typeStringForValue(JSValue* v) KJS_FAST_CALL;
2264static JSValue* typeStringForValue(JSValue* v)
2265{
2266 switch (v->type()) {
2267 case UndefinedType:
2268 return jsString("undefined");
2269 case NullType:
2270 return jsString("object");
2271 case BooleanType:
2272 return jsString("boolean");
2273 case NumberType:
2274 return jsString("number");
2275 case StringType:
2276 return jsString("string");
2277 default:
2278 if (v->isObject()) {
2279 // Return "undefined" for objects that should be treated
2280 // as null when doing comparisons.
2281 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
2282 return jsString("undefined");
2283 else if (static_cast<JSObject*>(v)->implementsCall())
2284 return jsString("function");
2285 }
2286
2287 return jsString("object");
2288 }
2289}
2290
2291void TypeOfResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
2292{
2293 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
2294 if (index != missingSymbolMarker())
2295 new (this) LocalVarTypeOfNode(index);
2296}
2297
2298JSValue* LocalVarTypeOfNode::evaluate(OldInterpreterExecState* exec)
2299{
2300 ASSERT(exec->variableObject() == exec->scopeChain().top());
2301
2302 return typeStringForValue(exec->localStorage()[m_index].value);
2303}
2304
2305RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2306{
2307 if (RegisterID* local = generator.registerForLocal(m_ident))
2308 return generator.emitTypeOf(generator.finalDestination(dst), local);
2309
2310 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
2311 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
2312 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
2313}
2314
2315JSValue* TypeOfResolveNode::evaluate(OldInterpreterExecState* exec)
2316{
2317 const ScopeChain& chain = exec->scopeChain();
2318 ScopeChainIterator iter = chain.begin();
2319 ScopeChainIterator end = chain.end();
2320
2321 // We must always have something in the scope chain
2322 ASSERT(iter != end);
2323
2324 PropertySlot slot;
2325 JSObject* base;
2326 do {
2327 base = *iter;
2328 if (base->getPropertySlot(exec, m_ident, slot)) {
2329 JSValue* v = slot.getValue(exec, base, m_ident);
2330 return typeStringForValue(v);
2331 }
2332
2333 ++iter;
2334 } while (iter != end);
2335
2336 return jsString("undefined");
2337}
2338
2339// ------------------------------ TypeOfValueNode -----------------------------------
2340
2341RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2342{
2343 RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
2344 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
2345}
2346
2347JSValue* TypeOfValueNode::evaluate(OldInterpreterExecState* exec)
2348{
2349 JSValue* v = m_expr->evaluate(exec);
2350 KJS_CHECKEXCEPTIONVALUE
2351
2352 return typeStringForValue(v);
2353}
2354
2355// ECMA 11.4.4 and 11.4.5
2356
2357// ------------------------------ PrefixResolveNode ----------------------------------
2358
2359RegisterID* PreIncResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2360{
2361 if (RegisterID* local = generator.registerForLocal(m_ident)) {
2362 if (generator.isLocalConstant(m_ident)) {
2363 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), 1.0);
2364 return generator.emitAdd(r0.get(), local, r0.get());
2365 }
2366
2367 generator.emitPreInc(local);
2368 return generator.moveToDestinationIfNeeded(dst, local);
2369 }
2370
2371 int index = 0;
2372 size_t depth = 0;
2373 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
2374 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
2375 generator.emitPreInc(propDst.get());
2376 generator.emitPutScopedVar(depth, index, propDst.get());
2377 return generator.moveToDestinationIfNeeded(dst, propDst.get());;
2378 }
2379
2380 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2381 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
2382 generator.emitPreInc(propDst.get());
2383 generator.emitPutById(base.get(), m_ident, propDst.get());
2384 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2385}
2386
2387void PreIncResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
2388{
2389 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
2390 if (index != missingSymbolMarker()) {
2391 if (isConstant(localStorage, index))
2392 new (this) PreIncConstNode(index);
2393 else
2394 new (this) PreIncLocalVarNode(index);
2395 }
2396}
2397
2398JSValue* PreIncLocalVarNode::evaluate(OldInterpreterExecState* exec)
2399{
2400 ASSERT(exec->variableObject() == exec->scopeChain().top());
2401 JSValue** slot = &exec->localStorage()[m_index].value;
2402
2403 double n = (*slot)->toNumber(exec);
2404 JSValue* n2 = jsNumber(n + 1);
2405 *slot = n2;
2406 return n2;
2407}
2408
2409JSValue* PreIncResolveNode::evaluate(OldInterpreterExecState* exec)
2410{
2411 const ScopeChain& chain = exec->scopeChain();
2412 ScopeChainIterator iter = chain.begin();
2413 ScopeChainIterator end = chain.end();
2414
2415 // we must always have something in the scope chain
2416 ASSERT(iter != end);
2417
2418 PropertySlot slot;
2419 do {
2420 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
2421 // See the comment in PostIncResolveNode::evaluate().
2422
2423 JSObject* base = *iter;
2424 JSValue* v = slot.getValue(exec, base, m_ident);
2425
2426 double n = v->toNumber(exec);
2427 JSValue* n2 = jsNumber(n + 1);
2428 base->put(exec, m_ident, n2);
2429
2430 return n2;
2431 }
2432
2433 ++iter;
2434 } while (iter != end);
2435
2436 return throwUndefinedVariableError(exec, m_ident);
2437}
2438
2439RegisterID* PreDecResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2440{
2441 if (RegisterID* local = generator.registerForLocal(m_ident)) {
2442 if (generator.isLocalConstant(m_ident)) {
2443 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), -1.0);
2444 return generator.emitAdd(r0.get(), local, r0.get());
2445 }
2446
2447 generator.emitPreDec(local);
2448 return generator.moveToDestinationIfNeeded(dst, local);
2449 }
2450
2451 int index = 0;
2452 size_t depth = 0;
2453 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
2454 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
2455 generator.emitPreDec(propDst.get());
2456 generator.emitPutScopedVar(depth, index, propDst.get());
2457 return generator.moveToDestinationIfNeeded(dst, propDst.get());;
2458 }
2459
2460 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2461 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
2462 generator.emitPreDec(propDst.get());
2463 generator.emitPutById(base.get(), m_ident, propDst.get());
2464 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2465}
2466
2467void PreDecResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack&)
2468{
2469 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
2470 if (index != missingSymbolMarker()) {
2471 if (isConstant(localStorage, index))
2472 new (this) PreDecConstNode(index);
2473 else
2474 new (this) PreDecLocalVarNode(index);
2475 }
2476}
2477
2478JSValue* PreDecLocalVarNode::evaluate(OldInterpreterExecState* exec)
2479{
2480 ASSERT(exec->variableObject() == exec->scopeChain().top());
2481 JSValue** slot = &exec->localStorage()[m_index].value;
2482
2483 double n = (*slot)->toNumber(exec);
2484 JSValue* n2 = jsNumber(n - 1);
2485 *slot = n2;
2486 return n2;
2487}
2488
2489JSValue* PreDecResolveNode::evaluate(OldInterpreterExecState* exec)
2490{
2491 const ScopeChain& chain = exec->scopeChain();
2492 ScopeChainIterator iter = chain.begin();
2493 ScopeChainIterator end = chain.end();
2494
2495 // we must always have something in the scope chain
2496 ASSERT(iter != end);
2497
2498 PropertySlot slot;
2499 do {
2500 if ((*iter)->getPropertySlot(exec, m_ident, slot)) {
2501 // See the comment in PostIncResolveNode::evaluate().
2502
2503 JSObject* base = *iter;
2504 JSValue* v = slot.getValue(exec, base, m_ident);
2505
2506 double n = v->toNumber(exec);
2507 JSValue* n2 = jsNumber(n - 1);
2508 base->put(exec, m_ident, n2);
2509
2510 return n2;
2511 }
2512
2513 ++iter;
2514 } while (iter != end);
2515
2516 return throwUndefinedVariableError(exec, m_ident);
2517}
2518
2519// ------------------------------ PreIncConstNode ----------------------------------
2520
2521JSValue* PreIncConstNode::evaluate(OldInterpreterExecState* exec)
2522{
2523 ASSERT(exec->variableObject() == exec->scopeChain().top());
2524 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) + 1);
2525}
2526
2527// ------------------------------ PreDecConstNode ----------------------------------
2528
2529JSValue* PreDecConstNode::evaluate(OldInterpreterExecState* exec)
2530{
2531 ASSERT(exec->variableObject() == exec->scopeChain().top());
2532 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec) - 1);
2533}
2534
2535// ------------------------------ PostIncConstNode ----------------------------------
2536
2537JSValue* PostIncConstNode::evaluate(OldInterpreterExecState* exec)
2538{
2539 ASSERT(exec->variableObject() == exec->scopeChain().top());
2540 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
2541}
2542
2543// ------------------------------ PostDecConstNode ----------------------------------
2544
2545JSValue* PostDecConstNode::evaluate(OldInterpreterExecState* exec)
2546{
2547 ASSERT(exec->variableObject() == exec->scopeChain().top());
2548 return jsNumber(exec->localStorage()[m_index].value->toNumber(exec));
2549}
2550
2551// ------------------------------ PrefixBracketNode ----------------------------------
2552
2553void PrefixBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2554{
2555 nodeStack.append(m_subscript.get());
2556 nodeStack.append(m_base.get());
2557}
2558
2559RegisterID* PreIncBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2560{
2561 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2562 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
2563 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2564 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
2565 generator.emitPreInc(value);
2566 generator.emitPutByVal(base.get(), property.get(), value);
2567 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2568}
2569
2570JSValue* PreIncBracketNode::evaluate(OldInterpreterExecState* exec)
2571{
2572 JSValue* baseValue = m_base->evaluate(exec);
2573 KJS_CHECKEXCEPTIONVALUE
2574 JSValue* subscript = m_subscript->evaluate(exec);
2575 KJS_CHECKEXCEPTIONVALUE
2576
2577 JSObject* base = baseValue->toObject(exec);
2578
2579 uint32_t propertyIndex;
2580 if (subscript->getUInt32(propertyIndex)) {
2581 PropertySlot slot;
2582 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2583 KJS_CHECKEXCEPTIONVALUE
2584
2585 JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
2586 base->put(exec, propertyIndex, n2);
2587
2588 return n2;
2589 }
2590
2591 Identifier propertyName(subscript->toString(exec));
2592 PropertySlot slot;
2593 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2594 KJS_CHECKEXCEPTIONVALUE
2595
2596 JSValue* n2 = jsNumber(v->toNumber(exec) + 1);
2597 base->put(exec, propertyName, n2);
2598
2599 return n2;
2600}
2601
2602RegisterID* PreDecBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2603{
2604
2605 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2606 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
2607 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2608 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
2609 generator.emitPreDec(value);
2610 generator.emitPutByVal(base.get(), property.get(), value);
2611 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2612}
2613
2614JSValue* PreDecBracketNode::evaluate(OldInterpreterExecState* exec)
2615{
2616 JSValue* baseValue = m_base->evaluate(exec);
2617 KJS_CHECKEXCEPTIONVALUE
2618 JSValue* subscript = m_subscript->evaluate(exec);
2619 KJS_CHECKEXCEPTIONVALUE
2620
2621 JSObject* base = baseValue->toObject(exec);
2622
2623 uint32_t propertyIndex;
2624 if (subscript->getUInt32(propertyIndex)) {
2625 PropertySlot slot;
2626 JSValue* v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
2627 KJS_CHECKEXCEPTIONVALUE
2628
2629 JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
2630 base->put(exec, propertyIndex, n2);
2631
2632 return n2;
2633 }
2634
2635 Identifier propertyName(subscript->toString(exec));
2636 PropertySlot slot;
2637 JSValue* v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
2638 KJS_CHECKEXCEPTIONVALUE
2639
2640 JSValue* n2 = jsNumber(v->toNumber(exec) - 1);
2641 base->put(exec, propertyName, n2);
2642
2643 return n2;
2644}
2645
2646// ------------------------------ PrefixDotNode ----------------------------------
2647
2648void PrefixDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2649{
2650 nodeStack.append(m_base.get());
2651}
2652
2653RegisterID* PreIncDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2654{
2655 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2656 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2657 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
2658 generator.emitPreInc(value);
2659 generator.emitPutById(base.get(), m_ident, value);
2660 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2661}
2662
2663JSValue* PreIncDotNode::evaluate(OldInterpreterExecState* exec)
2664{
2665 JSValue* baseValue = m_base->evaluate(exec);
2666 KJS_CHECKEXCEPTIONVALUE
2667 JSObject* base = baseValue->toObject(exec);
2668
2669 PropertySlot slot;
2670 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2671 KJS_CHECKEXCEPTIONVALUE
2672
2673 double n = v->toNumber(exec);
2674 JSValue* n2 = jsNumber(n + 1);
2675 base->put(exec, m_ident, n2);
2676
2677 return n2;
2678}
2679
2680RegisterID* PreDecDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2681{
2682 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
2683 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
2684 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
2685 generator.emitPreDec(value);
2686 generator.emitPutById(base.get(), m_ident, value);
2687 return generator.moveToDestinationIfNeeded(dst, propDst.get());
2688}
2689
2690JSValue* PreDecDotNode::evaluate(OldInterpreterExecState* exec)
2691{
2692 JSValue* baseValue = m_base->evaluate(exec);
2693 KJS_CHECKEXCEPTIONVALUE
2694 JSObject* base = baseValue->toObject(exec);
2695
2696 PropertySlot slot;
2697 JSValue* v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
2698 KJS_CHECKEXCEPTIONVALUE
2699
2700 double n = v->toNumber(exec);
2701 JSValue* n2 = jsNumber(n - 1);
2702 base->put(exec, m_ident, n2);
2703
2704 return n2;
2705}
2706
2707// ------------------------------ PrefixErrorNode -----------------------------------
2708
2709RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
2710{
2711 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference.");
2712}
2713
2714JSValue* PrefixErrorNode::evaluate(OldInterpreterExecState* exec)
2715{
2716 throwError(exec, ReferenceError, "Prefix %s operator applied to value that is not a reference.",
2717 m_operator == OpPlusPlus ? "++" : "--");
2718 handleException(exec);
2719 return jsUndefined();
2720}
2721
2722// ------------------------------ UnaryPlusNode --------------------------------
2723
2724RegisterID* UnaryPlusNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2725{
2726 RegisterID* src = generator.emitNode(m_expr.get());
2727 return generator.emitToJSNumber(generator.finalDestination(dst), src);
2728}
2729
2730void UnaryPlusNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2731{
2732 nodeStack.append(m_expr.get());
2733}
2734
2735// ECMA 11.4.6
2736JSValue* UnaryPlusNode::evaluate(OldInterpreterExecState* exec)
2737{
2738 JSValue* v = m_expr->evaluate(exec);
2739 KJS_CHECKEXCEPTIONVALUE
2740 return v->toJSNumber(exec);
2741}
2742
2743bool UnaryPlusNode::evaluateToBoolean(OldInterpreterExecState* exec)
2744{
2745 return m_expr->evaluateToBoolean(exec);
2746}
2747
2748double UnaryPlusNode::evaluateToNumber(OldInterpreterExecState* exec)
2749{
2750 return m_expr->evaluateToNumber(exec);
2751}
2752
2753int32_t UnaryPlusNode::evaluateToInt32(OldInterpreterExecState* exec)
2754{
2755 return m_expr->evaluateToInt32(exec);
2756}
2757
2758uint32_t UnaryPlusNode::evaluateToUInt32(OldInterpreterExecState* exec)
2759{
2760 return m_expr->evaluateToInt32(exec);
2761}
2762
2763// ------------------------------ NegateNode -----------------------------------
2764
2765RegisterID* NegateNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2766{
2767 RegisterID* src = generator.emitNode(m_expr.get());
2768 return generator.emitNegate(generator.finalDestination(dst), src);
2769}
2770
2771void NegateNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2772{
2773 nodeStack.append(m_expr.get());
2774}
2775
2776// ECMA 11.4.7
2777JSValue* NegateNode::evaluate(OldInterpreterExecState* exec)
2778{
2779 // No need to check exception, caller will do so right after evaluate()
2780 return jsNumber(-m_expr->evaluateToNumber(exec));
2781}
2782
2783double NegateNode::evaluateToNumber(OldInterpreterExecState* exec)
2784{
2785 // No need to check exception, caller will do so right after evaluateToNumber()
2786 return -m_expr->evaluateToNumber(exec);
2787}
2788
2789// ------------------------------ BitwiseNotNode -------------------------------
2790
2791RegisterID* BitwiseNotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2792{
2793 RegisterID* src = generator.emitNode(m_expr.get());
2794 return generator.emitBitNot(generator.finalDestination(dst), src);
2795}
2796
2797void BitwiseNotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2798{
2799 nodeStack.append(m_expr.get());
2800}
2801
2802// ECMA 11.4.8
2803int32_t BitwiseNotNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
2804{
2805 return ~m_expr->evaluateToInt32(exec);
2806}
2807
2808JSValue* BitwiseNotNode::evaluate(OldInterpreterExecState* exec)
2809{
2810 return jsNumber(inlineEvaluateToInt32(exec));
2811}
2812
2813double BitwiseNotNode::evaluateToNumber(OldInterpreterExecState* exec)
2814{
2815 return inlineEvaluateToInt32(exec);
2816}
2817
2818bool BitwiseNotNode::evaluateToBoolean(OldInterpreterExecState* exec)
2819{
2820 return inlineEvaluateToInt32(exec);
2821}
2822
2823int32_t BitwiseNotNode::evaluateToInt32(OldInterpreterExecState* exec)
2824{
2825 return inlineEvaluateToInt32(exec);
2826}
2827
2828uint32_t BitwiseNotNode::evaluateToUInt32(OldInterpreterExecState* exec)
2829{
2830 return inlineEvaluateToInt32(exec);
2831}
2832
2833// ------------------------------ LogicalNotNode -------------------------------
2834
2835RegisterID* LogicalNotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2836{
2837 RegisterID* src = generator.emitNode(m_expr.get());
2838 return generator.emitNot(generator.finalDestination(dst), src);
2839}
2840
2841void LogicalNotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2842{
2843 nodeStack.append(m_expr.get());
2844}
2845
2846// ECMA 11.4.9
2847JSValue* LogicalNotNode::evaluate(OldInterpreterExecState* exec)
2848{
2849 return jsBoolean(!m_expr->evaluateToBoolean(exec));
2850}
2851
2852bool LogicalNotNode::evaluateToBoolean(OldInterpreterExecState* exec)
2853{
2854 return !m_expr->evaluateToBoolean(exec);
2855}
2856
2857// ------------------------------ Multiplicative Nodes -----------------------------------
2858
2859RegisterID* MultNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2860{
2861 RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
2862 RegisterID* src2 = generator.emitNode(m_term2.get());
2863 return generator.emitMul(generator.finalDestination(dst, src1.get()), src1.get(), src2);
2864}
2865
2866void MultNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2867{
2868 nodeStack.append(m_term1.get());
2869 nodeStack.append(m_term2.get());
2870}
2871
2872// ECMA 11.5.1
2873double MultNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
2874{
2875 double n1 = m_term1->evaluateToNumber(exec);
2876 KJS_CHECKEXCEPTIONNUMBER
2877 double n2 = m_term2->evaluateToNumber(exec);
2878 return n1 * n2;
2879}
2880
2881JSValue* MultNode::evaluate(OldInterpreterExecState* exec)
2882{
2883 return jsNumber(inlineEvaluateToNumber(exec));
2884}
2885
2886double MultNode::evaluateToNumber(OldInterpreterExecState* exec)
2887{
2888 return inlineEvaluateToNumber(exec);
2889}
2890
2891bool MultNode::evaluateToBoolean(OldInterpreterExecState* exec)
2892{
2893 double result = inlineEvaluateToNumber(exec);
2894 return result > 0.0 || 0.0 > result; // NaN produces false as well
2895}
2896
2897int32_t MultNode::evaluateToInt32(OldInterpreterExecState* exec)
2898{
2899 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2900}
2901
2902uint32_t MultNode::evaluateToUInt32(OldInterpreterExecState* exec)
2903{
2904 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2905}
2906
2907RegisterID* DivNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2908{
2909 RefPtr<RegisterID> dividend = generator.emitNode(m_term1.get());
2910 RegisterID* divisor = generator.emitNode(m_term2.get());
2911 return generator.emitDiv(generator.finalDestination(dst, dividend.get()), dividend.get(), divisor);
2912}
2913
2914void DivNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2915{
2916 nodeStack.append(m_term1.get());
2917 nodeStack.append(m_term2.get());
2918}
2919
2920// ECMA 11.5.2
2921double DivNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
2922{
2923 double n1 = m_term1->evaluateToNumber(exec);
2924 KJS_CHECKEXCEPTIONNUMBER
2925 double n2 = m_term2->evaluateToNumber(exec);
2926 return n1 / n2;
2927}
2928
2929JSValue* DivNode::evaluate(OldInterpreterExecState* exec)
2930{
2931 return jsNumber(inlineEvaluateToNumber(exec));
2932}
2933
2934double DivNode::evaluateToNumber(OldInterpreterExecState* exec)
2935{
2936 return inlineEvaluateToNumber(exec);
2937}
2938
2939int32_t DivNode::evaluateToInt32(OldInterpreterExecState* exec)
2940{
2941 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2942}
2943
2944uint32_t DivNode::evaluateToUInt32(OldInterpreterExecState* exec)
2945{
2946 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2947}
2948
2949RegisterID* ModNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2950{
2951 RefPtr<RegisterID> dividend = generator.emitNode(m_term1.get());
2952 RegisterID* divisor = generator.emitNode(m_term2.get());
2953 return generator.emitMod(generator.finalDestination(dst, dividend.get()), dividend.get(), divisor);
2954}
2955
2956void ModNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
2957{
2958 nodeStack.append(m_term1.get());
2959 nodeStack.append(m_term2.get());
2960}
2961
2962// ECMA 11.5.3
2963double ModNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
2964{
2965 double n1 = m_term1->evaluateToNumber(exec);
2966 KJS_CHECKEXCEPTIONNUMBER
2967 double n2 = m_term2->evaluateToNumber(exec);
2968 return fmod(n1, n2);
2969}
2970
2971JSValue* ModNode::evaluate(OldInterpreterExecState* exec)
2972{
2973 return jsNumber(inlineEvaluateToNumber(exec));
2974}
2975
2976double ModNode::evaluateToNumber(OldInterpreterExecState* exec)
2977{
2978 return inlineEvaluateToNumber(exec);
2979}
2980
2981bool ModNode::evaluateToBoolean(OldInterpreterExecState* exec)
2982{
2983 double result = inlineEvaluateToNumber(exec);
2984 return result > 0.0 || 0.0 > result; // NaN produces false as well
2985}
2986
2987int32_t ModNode::evaluateToInt32(OldInterpreterExecState* exec)
2988{
2989 return JSValue::toInt32(inlineEvaluateToNumber(exec));
2990}
2991
2992uint32_t ModNode::evaluateToUInt32(OldInterpreterExecState* exec)
2993{
2994 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
2995}
2996
2997// ------------------------------ Additive Nodes --------------------------------------
2998
2999static double throwOutOfMemoryErrorToNumber(OldInterpreterExecState* exec)
3000{
3001 JSObject* error = Error::create(exec, GeneralError, "Out of memory");
3002 exec->setException(error);
3003 return 0.0;
3004}
3005
3006// ECMA 11.6
3007static JSValue* addSlowCase(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3008{
3009 // exception for the Date exception in defaultValue()
3010 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
3011 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
3012
3013 if (p1->isString() || p2->isString()) {
3014 UString value = p1->toString(exec) + p2->toString(exec);
3015 if (value.isNull())
3016 return throwOutOfMemoryError(exec);
3017 return jsString(value);
3018 }
3019
3020 return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
3021}
3022
3023static double addSlowCaseToNumber(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3024{
3025 // exception for the Date exception in defaultValue()
3026 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
3027 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
3028
3029 if (p1->isString() || p2->isString()) {
3030 UString value = p1->toString(exec) + p2->toString(exec);
3031 if (value.isNull())
3032 return throwOutOfMemoryErrorToNumber(exec);
3033 return value.toDouble();
3034 }
3035
3036 return p1->toNumber(exec) + p2->toNumber(exec);
3037}
3038
3039// Fast-path choices here are based on frequency data from SunSpider:
3040// <times> Add case: <t1> <t2>
3041// ---------------------------
3042// 5627160 Add case: 1 1
3043// 247427 Add case: 5 5
3044// 20901 Add case: 5 6
3045// 13978 Add case: 5 1
3046// 4000 Add case: 1 5
3047// 1 Add case: 3 5
3048
3049static inline JSValue* add(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3050{
3051 JSType t1 = v1->type();
3052 JSType t2 = v2->type();
3053 const unsigned bothTypes = (t1 << 3) | t2;
3054
3055 if (bothTypes == ((NumberType << 3) | NumberType))
3056 return jsNumber(v1->toNumber(exec) + v2->toNumber(exec));
3057 if (bothTypes == ((StringType << 3) | StringType)) {
3058 UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
3059 if (value.isNull())
3060 return throwOutOfMemoryError(exec);
3061 return jsString(value);
3062 }
3063
3064 // All other cases are pretty uncommon
3065 return addSlowCase(exec, v1, v2);
3066}
3067
3068static inline double addToNumber(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3069{
3070 JSType t1 = v1->type();
3071 JSType t2 = v2->type();
3072 const unsigned bothTypes = (t1 << 3) | t2;
3073
3074 if (bothTypes == ((NumberType << 3) | NumberType))
3075 return v1->toNumber(exec) + v2->toNumber(exec);
3076 if (bothTypes == ((StringType << 3) | StringType)) {
3077 UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
3078 if (value.isNull())
3079 return throwOutOfMemoryErrorToNumber(exec);
3080 return value.toDouble();
3081 }
3082
3083 // All other cases are pretty uncommon
3084 return addSlowCaseToNumber(exec, v1, v2);
3085}
3086
3087RegisterID* AddNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3088{
3089 RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
3090 RegisterID* src2 = generator.emitNode(m_term2.get());
3091 return generator.emitAdd(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3092}
3093
3094void AddNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3095{
3096 nodeStack.append(m_term1.get());
3097 nodeStack.append(m_term2.get());
3098}
3099
3100// ECMA 11.6.1
3101JSValue* AddNode::evaluate(OldInterpreterExecState* exec)
3102{
3103 JSValue* v1 = m_term1->evaluate(exec);
3104 KJS_CHECKEXCEPTIONVALUE
3105
3106 JSValue* v2 = m_term2->evaluate(exec);
3107 KJS_CHECKEXCEPTIONVALUE
3108
3109 return add(exec, v1, v2);
3110}
3111
3112double AddNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
3113{
3114 JSValue* v1 = m_term1->evaluate(exec);
3115 KJS_CHECKEXCEPTIONNUMBER
3116
3117 JSValue* v2 = m_term2->evaluate(exec);
3118 KJS_CHECKEXCEPTIONNUMBER
3119
3120 return addToNumber(exec, v1, v2);
3121}
3122
3123double AddNode::evaluateToNumber(OldInterpreterExecState* exec)
3124{
3125 return inlineEvaluateToNumber(exec);
3126}
3127
3128int32_t AddNode::evaluateToInt32(OldInterpreterExecState* exec)
3129{
3130 return JSValue::toInt32(inlineEvaluateToNumber(exec));
3131}
3132
3133uint32_t AddNode::evaluateToUInt32(OldInterpreterExecState* exec)
3134{
3135 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
3136}
3137
3138double AddNumbersNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
3139{
3140 double n1 = m_term1->evaluateToNumber(exec);
3141 KJS_CHECKEXCEPTIONNUMBER
3142 double n2 = m_term2->evaluateToNumber(exec);
3143 return n1 + n2;
3144}
3145
3146JSValue* AddNumbersNode::evaluate(OldInterpreterExecState* exec)
3147{
3148 return jsNumber(inlineEvaluateToNumber(exec));
3149}
3150
3151double AddNumbersNode::evaluateToNumber(OldInterpreterExecState* exec)
3152{
3153 return inlineEvaluateToNumber(exec);
3154}
3155
3156int32_t AddNumbersNode::evaluateToInt32(OldInterpreterExecState* exec)
3157{
3158 return JSValue::toInt32(inlineEvaluateToNumber(exec));
3159}
3160
3161uint32_t AddNumbersNode::evaluateToUInt32(OldInterpreterExecState* exec)
3162{
3163 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
3164}
3165
3166JSValue* AddStringsNode::evaluate(OldInterpreterExecState* exec)
3167{
3168 JSValue* v1 = m_term1->evaluate(exec);
3169 KJS_CHECKEXCEPTIONVALUE
3170
3171 JSValue* v2 = m_term2->evaluate(exec);
3172 KJS_CHECKEXCEPTIONVALUE
3173
3174 return jsString(static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value());
3175}
3176
3177JSValue* AddStringLeftNode::evaluate(OldInterpreterExecState* exec)
3178{
3179 JSValue* v1 = m_term1->evaluate(exec);
3180 KJS_CHECKEXCEPTIONVALUE
3181
3182 JSValue* v2 = m_term2->evaluate(exec);
3183 KJS_CHECKEXCEPTIONVALUE
3184
3185 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
3186 return jsString(static_cast<StringImp*>(v1)->value() + p2->toString(exec));
3187}
3188
3189JSValue* AddStringRightNode::evaluate(OldInterpreterExecState* exec)
3190{
3191 JSValue* v1 = m_term1->evaluate(exec);
3192 KJS_CHECKEXCEPTIONVALUE
3193
3194 JSValue* v2 = m_term2->evaluate(exec);
3195 KJS_CHECKEXCEPTIONVALUE
3196
3197 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
3198 return jsString(p1->toString(exec) + static_cast<StringImp*>(v2)->value());
3199}
3200
3201RegisterID* SubNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3202{
3203 RefPtr<RegisterID> src1 = generator.emitNode(m_term1.get());
3204 RegisterID* src2 = generator.emitNode(m_term2.get());
3205 return generator.emitSub(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3206}
3207
3208void SubNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3209{
3210 nodeStack.append(m_term1.get());
3211 nodeStack.append(m_term2.get());
3212}
3213
3214// ECMA 11.6.2
3215double SubNode::inlineEvaluateToNumber(OldInterpreterExecState* exec)
3216{
3217 double n1 = m_term1->evaluateToNumber(exec);
3218 KJS_CHECKEXCEPTIONNUMBER
3219 double n2 = m_term2->evaluateToNumber(exec);
3220 return n1 - n2;
3221}
3222
3223JSValue* SubNode::evaluate(OldInterpreterExecState* exec)
3224{
3225 return jsNumber(inlineEvaluateToNumber(exec));
3226}
3227
3228double SubNode::evaluateToNumber(OldInterpreterExecState* exec)
3229{
3230 return inlineEvaluateToNumber(exec);
3231}
3232
3233int32_t SubNode::evaluateToInt32(OldInterpreterExecState* exec)
3234{
3235 return JSValue::toInt32(inlineEvaluateToNumber(exec));
3236}
3237
3238uint32_t SubNode::evaluateToUInt32(OldInterpreterExecState* exec)
3239{
3240 return JSValue::toUInt32(inlineEvaluateToNumber(exec));
3241}
3242
3243// ------------------------------ Shift Nodes ------------------------------------
3244
3245RegisterID* LeftShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3246{
3247 RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
3248 RegisterID* shift = generator.emitNode(m_term2.get());
3249 return generator.emitLeftShift(generator.finalDestination(dst, val.get()), val.get(), shift);
3250}
3251
3252void LeftShiftNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3253{
3254 nodeStack.append(m_term1.get());
3255 nodeStack.append(m_term2.get());
3256}
3257
3258// ECMA 11.7.1
3259int32_t LeftShiftNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
3260{
3261 int i1 = m_term1->evaluateToInt32(exec);
3262 KJS_CHECKEXCEPTIONNUMBER
3263 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
3264 return (i1 << i2);
3265}
3266
3267JSValue* LeftShiftNode::evaluate(OldInterpreterExecState* exec)
3268{
3269 return jsNumber(inlineEvaluateToInt32(exec));
3270}
3271
3272double LeftShiftNode::evaluateToNumber(OldInterpreterExecState* exec)
3273{
3274 return inlineEvaluateToInt32(exec);
3275}
3276
3277int32_t LeftShiftNode::evaluateToInt32(OldInterpreterExecState* exec)
3278{
3279 return inlineEvaluateToInt32(exec);
3280}
3281
3282uint32_t LeftShiftNode::evaluateToUInt32(OldInterpreterExecState* exec)
3283{
3284 return inlineEvaluateToInt32(exec);
3285}
3286
3287RegisterID* RightShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3288{
3289 RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
3290 RegisterID* shift = generator.emitNode(m_term2.get());
3291 return generator.emitRightShift(generator.finalDestination(dst, val.get()), val.get(), shift);
3292}
3293
3294void RightShiftNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3295{
3296 nodeStack.append(m_term1.get());
3297 nodeStack.append(m_term2.get());
3298}
3299
3300// ECMA 11.7.2
3301int32_t RightShiftNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
3302{
3303 int i1 = m_term1->evaluateToInt32(exec);
3304 KJS_CHECKEXCEPTIONNUMBER
3305 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
3306 return (i1 >> i2);
3307}
3308
3309JSValue* RightShiftNode::evaluate(OldInterpreterExecState* exec)
3310{
3311 return jsNumber(inlineEvaluateToInt32(exec));
3312}
3313
3314double RightShiftNode::evaluateToNumber(OldInterpreterExecState* exec)
3315{
3316 return inlineEvaluateToInt32(exec);
3317}
3318
3319int32_t RightShiftNode::evaluateToInt32(OldInterpreterExecState* exec)
3320{
3321 return inlineEvaluateToInt32(exec);
3322}
3323
3324uint32_t RightShiftNode::evaluateToUInt32(OldInterpreterExecState* exec)
3325{
3326 return inlineEvaluateToInt32(exec);
3327}
3328
3329RegisterID* UnsignedRightShiftNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3330{
3331 RefPtr<RegisterID> val = generator.emitNode(m_term1.get());
3332 RegisterID* shift = generator.emitNode(m_term2.get());
3333 return generator.emitUnsignedRightShift(generator.finalDestination(dst, val.get()), val.get(), shift);
3334}
3335
3336void UnsignedRightShiftNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3337{
3338 nodeStack.append(m_term1.get());
3339 nodeStack.append(m_term2.get());
3340}
3341
3342// ECMA 11.7.3
3343uint32_t UnsignedRightShiftNode::inlineEvaluateToUInt32(OldInterpreterExecState* exec)
3344{
3345 unsigned int i1 = m_term1->evaluateToUInt32(exec);
3346 KJS_CHECKEXCEPTIONNUMBER
3347 unsigned int i2 = m_term2->evaluateToUInt32(exec) & 0x1f;
3348 return (i1 >> i2);
3349}
3350
3351JSValue* UnsignedRightShiftNode::evaluate(OldInterpreterExecState* exec)
3352{
3353 return jsNumber(inlineEvaluateToUInt32(exec));
3354}
3355
3356double UnsignedRightShiftNode::evaluateToNumber(OldInterpreterExecState* exec)
3357{
3358 return inlineEvaluateToUInt32(exec);
3359}
3360
3361int32_t UnsignedRightShiftNode::evaluateToInt32(OldInterpreterExecState* exec)
3362{
3363 return inlineEvaluateToUInt32(exec);
3364}
3365
3366uint32_t UnsignedRightShiftNode::evaluateToUInt32(OldInterpreterExecState* exec)
3367{
3368 return inlineEvaluateToUInt32(exec);
3369}
3370
3371// ------------------------------ Relational Nodes -------------------------------
3372
3373static inline bool lessThan(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3374{
3375 double n1;
3376 double n2;
3377 JSValue* p1;
3378 JSValue* p2;
3379 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
3380 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
3381
3382 if (wasNotString1 | wasNotString2)
3383 return n1 < n2;
3384
3385 return static_cast<const StringImp*>(p1)->value() < static_cast<const StringImp*>(p2)->value();
3386}
3387
3388static inline bool lessThanEq(OldInterpreterExecState* exec, JSValue* v1, JSValue* v2)
3389{
3390 double n1;
3391 double n2;
3392 JSValue* p1;
3393 JSValue* p2;
3394 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
3395 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
3396
3397 if (wasNotString1 | wasNotString2)
3398 return n1 <= n2;
3399
3400 return !(static_cast<const StringImp*>(p2)->value() < static_cast<const StringImp*>(p1)->value());
3401}
3402
3403RegisterID* LessNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3404{
3405 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3406 RegisterID* src2 = generator.emitNode(m_expr2.get());
3407 return generator.emitLess(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3408}
3409
3410void LessNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3411{
3412 nodeStack.append(m_expr2.get());
3413 nodeStack.append(m_expr1.get());
3414}
3415
3416// ECMA 11.8.1
3417bool LessNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3418{
3419 JSValue* v1 = m_expr1->evaluate(exec);
3420 KJS_CHECKEXCEPTIONBOOLEAN
3421 JSValue* v2 = m_expr2->evaluate(exec);
3422 KJS_CHECKEXCEPTIONBOOLEAN
3423 return lessThan(exec, v1, v2);
3424}
3425
3426JSValue* LessNode::evaluate(OldInterpreterExecState* exec)
3427{
3428 return jsBoolean(inlineEvaluateToBoolean(exec));
3429}
3430
3431bool LessNode::evaluateToBoolean(OldInterpreterExecState* exec)
3432{
3433 return inlineEvaluateToBoolean(exec);
3434}
3435
3436bool LessNumbersNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3437{
3438 double n1 = m_expr1->evaluateToNumber(exec);
3439 KJS_CHECKEXCEPTIONVALUE
3440 double n2 = m_expr2->evaluateToNumber(exec);
3441 return n1 < n2;
3442}
3443
3444JSValue* LessNumbersNode::evaluate(OldInterpreterExecState* exec)
3445{
3446 return jsBoolean(inlineEvaluateToBoolean(exec));
3447}
3448
3449bool LessNumbersNode::evaluateToBoolean(OldInterpreterExecState* exec)
3450{
3451 return inlineEvaluateToBoolean(exec);
3452}
3453
3454bool LessStringsNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3455{
3456 JSValue* v1 = m_expr1->evaluate(exec);
3457 KJS_CHECKEXCEPTIONVALUE
3458 JSValue* v2 = m_expr2->evaluate(exec);
3459 return static_cast<StringImp*>(v1)->value() < static_cast<StringImp*>(v2)->value();
3460}
3461
3462JSValue* LessStringsNode::evaluate(OldInterpreterExecState* exec)
3463{
3464 return jsBoolean(inlineEvaluateToBoolean(exec));
3465}
3466
3467bool LessStringsNode::evaluateToBoolean(OldInterpreterExecState* exec)
3468{
3469 return inlineEvaluateToBoolean(exec);
3470}
3471
3472RegisterID* GreaterNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3473{
3474 RefPtr<RegisterID> src1 = generator.emitNode(m_expr2.get());
3475 RegisterID* src2 = generator.emitNode(m_expr1.get());
3476 return generator.emitLess(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3477}
3478
3479void GreaterNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3480{
3481 nodeStack.append(m_expr2.get());
3482 nodeStack.append(m_expr1.get());
3483}
3484
3485// ECMA 11.8.2
3486bool GreaterNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3487{
3488 JSValue* v1 = m_expr1->evaluate(exec);
3489 KJS_CHECKEXCEPTIONBOOLEAN
3490 JSValue* v2 = m_expr2->evaluate(exec);
3491 KJS_CHECKEXCEPTIONBOOLEAN
3492 return lessThan(exec, v2, v1);
3493}
3494
3495JSValue* GreaterNode::evaluate(OldInterpreterExecState* exec)
3496{
3497 return jsBoolean(inlineEvaluateToBoolean(exec));
3498}
3499
3500bool GreaterNode::evaluateToBoolean(OldInterpreterExecState* exec)
3501{
3502 return inlineEvaluateToBoolean(exec);
3503}
3504
3505RegisterID* LessEqNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3506{
3507 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3508 RegisterID* src2 = generator.emitNode(m_expr2.get());
3509 return generator.emitLessEq(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3510}
3511
3512void LessEqNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3513{
3514 nodeStack.append(m_expr2.get());
3515 nodeStack.append(m_expr1.get());
3516}
3517
3518// ECMA 11.8.3
3519bool LessEqNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3520{
3521 JSValue* v1 = m_expr1->evaluate(exec);
3522 KJS_CHECKEXCEPTIONBOOLEAN
3523 JSValue* v2 = m_expr2->evaluate(exec);
3524 KJS_CHECKEXCEPTIONBOOLEAN
3525 return lessThanEq(exec, v1, v2);
3526}
3527
3528JSValue* LessEqNode::evaluate(OldInterpreterExecState* exec)
3529{
3530 return jsBoolean(inlineEvaluateToBoolean(exec));
3531}
3532
3533bool LessEqNode::evaluateToBoolean(OldInterpreterExecState* exec)
3534{
3535 return inlineEvaluateToBoolean(exec);
3536}
3537
3538RegisterID* GreaterEqNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3539{
3540 RefPtr<RegisterID> src1 = generator.emitNode(m_expr2.get());
3541 RegisterID* src2 = generator.emitNode(m_expr1.get());
3542 return generator.emitLessEq(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3543}
3544
3545void GreaterEqNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3546{
3547 nodeStack.append(m_expr2.get());
3548 nodeStack.append(m_expr1.get());
3549}
3550
3551// ECMA 11.8.4
3552bool GreaterEqNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3553{
3554 JSValue* v1 = m_expr1->evaluate(exec);
3555 KJS_CHECKEXCEPTIONBOOLEAN
3556 JSValue* v2 = m_expr2->evaluate(exec);
3557 KJS_CHECKEXCEPTIONBOOLEAN
3558 return lessThanEq(exec, v2, v1);
3559}
3560
3561JSValue* GreaterEqNode::evaluate(OldInterpreterExecState* exec)
3562{
3563 return jsBoolean(inlineEvaluateToBoolean(exec));
3564}
3565
3566bool GreaterEqNode::evaluateToBoolean(OldInterpreterExecState* exec)
3567{
3568 return inlineEvaluateToBoolean(exec);
3569}
3570
3571RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3572{
3573 RefPtr<RegisterID> value = generator.emitNode(m_expr1.get());
3574 RegisterID* base = generator.emitNode(m_expr2.get());
3575 return generator.emitInstanceOf(generator.finalDestination(dst, value.get()), value.get(), base);
3576}
3577
3578void InstanceOfNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3579{
3580 nodeStack.append(m_expr2.get());
3581 nodeStack.append(m_expr1.get());
3582}
3583
3584// ECMA 11.8.6
3585JSValue* InstanceOfNode::evaluate(OldInterpreterExecState* exec)
3586{
3587 JSValue* v1 = m_expr1->evaluate(exec);
3588 KJS_CHECKEXCEPTIONVALUE
3589 JSValue* v2 = m_expr2->evaluate(exec);
3590 KJS_CHECKEXCEPTIONVALUE
3591
3592 if (!v2->isObject())
3593 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, m_expr2.get());
3594
3595 JSObject* o2 = static_cast<JSObject*>(v2);
3596
3597 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
3598 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
3599 // property. It seems that all objects have the property, but not all implement it, so in this
3600 // case we return false (consistent with Mozilla).
3601 if (!o2->implementsHasInstance())
3602 return jsBoolean(false);
3603
3604 return jsBoolean(o2->hasInstance(exec, v1));
3605}
3606
3607bool InstanceOfNode::evaluateToBoolean(OldInterpreterExecState* exec)
3608{
3609 JSValue* v1 = m_expr1->evaluate(exec);
3610 KJS_CHECKEXCEPTIONBOOLEAN
3611 JSValue* v2 = m_expr2->evaluate(exec);
3612 KJS_CHECKEXCEPTIONBOOLEAN
3613
3614 if (!v2->isObject()) {
3615 throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'instanceof' operator.", v2, m_expr2.get());
3616 return false;
3617 }
3618
3619 JSObject* o2 = static_cast<JSObject*>(v2);
3620
3621 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
3622 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
3623 // property. It seems that all objects have the property, but not all implement it, so in this
3624 // case we return false (consistent with Mozilla).
3625 if (!o2->implementsHasInstance())
3626 return false;
3627
3628 return o2->hasInstance(exec, v1);
3629}
3630
3631RegisterID* InNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3632{
3633 RefPtr<RegisterID> property = generator.emitNode(m_expr1.get());
3634 RegisterID* base = generator.emitNode(m_expr2.get());
3635 return generator.emitIn(generator.finalDestination(dst, property.get()), property.get(), base);
3636}
3637
3638void InNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3639{
3640 nodeStack.append(m_expr2.get());
3641 nodeStack.append(m_expr1.get());
3642}
3643
3644// ECMA 11.8.7
3645JSValue* InNode::evaluate(OldInterpreterExecState* exec)
3646{
3647 JSValue* v1 = m_expr1->evaluate(exec);
3648 KJS_CHECKEXCEPTIONVALUE
3649 JSValue* v2 = m_expr2->evaluate(exec);
3650 KJS_CHECKEXCEPTIONVALUE
3651
3652 if (!v2->isObject())
3653 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
3654
3655 return jsBoolean(static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec))));
3656}
3657
3658bool InNode::evaluateToBoolean(OldInterpreterExecState* exec)
3659{
3660 JSValue* v1 = m_expr1->evaluate(exec);
3661 KJS_CHECKEXCEPTIONBOOLEAN
3662 JSValue* v2 = m_expr2->evaluate(exec);
3663 KJS_CHECKEXCEPTIONBOOLEAN
3664
3665 if (!v2->isObject()) {
3666 throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with 'in' operator.", v2, m_expr2.get());
3667 return false;
3668 }
3669
3670 return static_cast<JSObject*>(v2)->hasProperty(exec, Identifier(v1->toString(exec)));
3671}
3672
3673// ------------------------------ Equality Nodes ------------------------------------
3674
3675RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3676{
3677 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3678 RegisterID* src2 = generator.emitNode(m_expr2.get());
3679 return generator.emitEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3680}
3681
3682void EqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3683{
3684 nodeStack.append(m_expr2.get());
3685 nodeStack.append(m_expr1.get());
3686}
3687
3688// ECMA 11.9.1
3689bool EqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3690{
3691 JSValue* v1 = m_expr1->evaluate(exec);
3692 KJS_CHECKEXCEPTIONBOOLEAN
3693 JSValue* v2 = m_expr2->evaluate(exec);
3694 KJS_CHECKEXCEPTIONBOOLEAN
3695
3696 return equal(exec, v1, v2);
3697}
3698
3699JSValue* EqualNode::evaluate(OldInterpreterExecState* exec)
3700{
3701 return jsBoolean(inlineEvaluateToBoolean(exec));
3702}
3703
3704bool EqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
3705{
3706 return inlineEvaluateToBoolean(exec);
3707}
3708
3709RegisterID* NotEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3710{
3711 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3712 RegisterID* src2 = generator.emitNode(m_expr2.get());
3713 return generator.emitNotEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3714}
3715
3716void NotEqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3717{
3718 nodeStack.append(m_expr2.get());
3719 nodeStack.append(m_expr1.get());
3720}
3721
3722// ECMA 11.9.2
3723bool NotEqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3724{
3725 JSValue* v1 = m_expr1->evaluate(exec);
3726 KJS_CHECKEXCEPTIONBOOLEAN
3727 JSValue* v2 = m_expr2->evaluate(exec);
3728 KJS_CHECKEXCEPTIONBOOLEAN
3729
3730 return !equal(exec,v1, v2);
3731}
3732
3733JSValue* NotEqualNode::evaluate(OldInterpreterExecState* exec)
3734{
3735 return jsBoolean(inlineEvaluateToBoolean(exec));
3736}
3737
3738bool NotEqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
3739{
3740 return inlineEvaluateToBoolean(exec);
3741}
3742
3743RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3744{
3745 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3746 RegisterID* src2 = generator.emitNode(m_expr2.get());
3747 return generator.emitStrictEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3748}
3749
3750void StrictEqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3751{
3752 nodeStack.append(m_expr2.get());
3753 nodeStack.append(m_expr1.get());
3754}
3755
3756// ECMA 11.9.4
3757bool StrictEqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3758{
3759 JSValue* v1 = m_expr1->evaluate(exec);
3760 KJS_CHECKEXCEPTIONBOOLEAN
3761 JSValue* v2 = m_expr2->evaluate(exec);
3762 KJS_CHECKEXCEPTIONBOOLEAN
3763
3764 return strictEqual(v1, v2);
3765}
3766
3767JSValue* StrictEqualNode::evaluate(OldInterpreterExecState* exec)
3768{
3769 return jsBoolean(inlineEvaluateToBoolean(exec));
3770}
3771
3772bool StrictEqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
3773{
3774 return inlineEvaluateToBoolean(exec);
3775}
3776
3777RegisterID* NotStrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3778{
3779 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3780 RegisterID* src2 = generator.emitNode(m_expr2.get());
3781 return generator.emitNotStrictEqual(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3782}
3783
3784void NotStrictEqualNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3785{
3786 nodeStack.append(m_expr2.get());
3787 nodeStack.append(m_expr1.get());
3788}
3789
3790// ECMA 11.9.5
3791bool NotStrictEqualNode::inlineEvaluateToBoolean(OldInterpreterExecState* exec)
3792{
3793 JSValue* v1 = m_expr1->evaluate(exec);
3794 KJS_CHECKEXCEPTIONBOOLEAN
3795 JSValue* v2 = m_expr2->evaluate(exec);
3796 KJS_CHECKEXCEPTIONBOOLEAN
3797
3798 return !strictEqual(v1, v2);
3799}
3800
3801JSValue* NotStrictEqualNode::evaluate(OldInterpreterExecState* exec)
3802{
3803 return jsBoolean(inlineEvaluateToBoolean(exec));
3804}
3805
3806bool NotStrictEqualNode::evaluateToBoolean(OldInterpreterExecState* exec)
3807{
3808 return inlineEvaluateToBoolean(exec);
3809}
3810
3811// ------------------------------ Bit Operation Nodes ----------------------------------
3812
3813RegisterID* BitAndNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3814{
3815 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3816 RegisterID* src2 = generator.emitNode(m_expr2.get());
3817 return generator.emitBitAnd(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3818}
3819
3820void BitAndNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3821{
3822 nodeStack.append(m_expr2.get());
3823 nodeStack.append(m_expr1.get());
3824}
3825
3826// ECMA 11.10
3827JSValue* BitAndNode::evaluate(OldInterpreterExecState* exec)
3828{
3829 JSValue* v1 = m_expr1->evaluate(exec);
3830 KJS_CHECKEXCEPTIONVALUE
3831 JSValue* v2 = m_expr2->evaluate(exec);
3832 KJS_CHECKEXCEPTIONVALUE
3833
3834 return jsNumberFromAnd(exec, v1, v2);
3835}
3836
3837int32_t BitAndNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
3838{
3839 int32_t i1 = m_expr1->evaluateToInt32(exec);
3840 KJS_CHECKEXCEPTIONNUMBER
3841 int32_t i2 = m_expr2->evaluateToInt32(exec);
3842 return (i1 & i2);
3843}
3844
3845double BitAndNode::evaluateToNumber(OldInterpreterExecState* exec)
3846{
3847 return inlineEvaluateToInt32(exec);
3848}
3849
3850bool BitAndNode::evaluateToBoolean(OldInterpreterExecState* exec)
3851{
3852 return inlineEvaluateToInt32(exec);
3853}
3854
3855int32_t BitAndNode::evaluateToInt32(OldInterpreterExecState* exec)
3856{
3857 return inlineEvaluateToInt32(exec);
3858}
3859
3860uint32_t BitAndNode::evaluateToUInt32(OldInterpreterExecState* exec)
3861{
3862 return inlineEvaluateToInt32(exec);
3863}
3864
3865RegisterID* BitXOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3866{
3867 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3868 RegisterID* src2 = generator.emitNode(m_expr2.get());
3869 return generator.emitBitXOr(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3870}
3871
3872void BitXOrNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3873{
3874 nodeStack.append(m_expr2.get());
3875 nodeStack.append(m_expr1.get());
3876}
3877
3878int32_t BitXOrNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
3879{
3880 int i1 = m_expr1->evaluateToInt32(exec);
3881 KJS_CHECKEXCEPTIONNUMBER
3882 int i2 = m_expr2->evaluateToInt32(exec);
3883 return (i1 ^ i2);
3884}
3885
3886JSValue* BitXOrNode::evaluate(OldInterpreterExecState* exec)
3887{
3888 return jsNumber(inlineEvaluateToInt32(exec));
3889}
3890
3891double BitXOrNode::evaluateToNumber(OldInterpreterExecState* exec)
3892{
3893 return inlineEvaluateToInt32(exec);
3894}
3895
3896bool BitXOrNode::evaluateToBoolean(OldInterpreterExecState* exec)
3897{
3898 return inlineEvaluateToInt32(exec);
3899}
3900
3901int32_t BitXOrNode::evaluateToInt32(OldInterpreterExecState* exec)
3902{
3903 return inlineEvaluateToInt32(exec);
3904}
3905
3906uint32_t BitXOrNode::evaluateToUInt32(OldInterpreterExecState* exec)
3907{
3908 return inlineEvaluateToInt32(exec);
3909}
3910
3911RegisterID* BitOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3912{
3913 RefPtr<RegisterID> src1 = generator.emitNode(m_expr1.get());
3914 RegisterID* src2 = generator.emitNode(m_expr2.get());
3915 return generator.emitBitOr(generator.finalDestination(dst, src1.get()), src1.get(), src2);
3916}
3917
3918void BitOrNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3919{
3920 nodeStack.append(m_expr2.get());
3921 nodeStack.append(m_expr1.get());
3922}
3923
3924int32_t BitOrNode::inlineEvaluateToInt32(OldInterpreterExecState* exec)
3925{
3926 int i1 = m_expr1->evaluateToInt32(exec);
3927 KJS_CHECKEXCEPTIONNUMBER
3928 int i2 = m_expr2->evaluateToInt32(exec);
3929 return (i1 | i2);
3930}
3931
3932JSValue* BitOrNode::evaluate(OldInterpreterExecState* exec)
3933{
3934 return jsNumber(inlineEvaluateToInt32(exec));
3935}
3936
3937double BitOrNode::evaluateToNumber(OldInterpreterExecState* exec)
3938{
3939 return inlineEvaluateToInt32(exec);
3940}
3941
3942bool BitOrNode::evaluateToBoolean(OldInterpreterExecState* exec)
3943{
3944 return inlineEvaluateToInt32(exec);
3945}
3946
3947int32_t BitOrNode::evaluateToInt32(OldInterpreterExecState* exec)
3948{
3949 return inlineEvaluateToInt32(exec);
3950}
3951
3952uint32_t BitOrNode::evaluateToUInt32(OldInterpreterExecState* exec)
3953{
3954 return inlineEvaluateToInt32(exec);
3955}
3956
3957// ------------------------------ Binary Logical Nodes ----------------------------
3958
3959RegisterID* LogicalAndNode::emitCode(CodeGenerator& generator, RegisterID* dst)
3960{
3961 RefPtr<RegisterID> temp = generator.tempDestination(dst);
3962 RefPtr<LabelID> target = generator.newLabel();
3963
3964 generator.emitNode(temp.get(), m_expr1.get());
3965 generator.emitJumpIfFalse(temp.get(), target.get());
3966 generator.emitNode(temp.get(), m_expr2.get());
3967 generator.emitLabel(target.get());
3968
3969 return generator.moveToDestinationIfNeeded(dst, temp.get());
3970}
3971
3972void LogicalAndNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
3973{
3974 nodeStack.append(m_expr2.get());
3975 nodeStack.append(m_expr1.get());
3976}
3977
3978// ECMA 11.11
3979JSValue* LogicalAndNode::evaluate(OldInterpreterExecState* exec)
3980{
3981 JSValue* v1 = m_expr1->evaluate(exec);
3982 KJS_CHECKEXCEPTIONVALUE
3983 bool b1 = v1->toBoolean(exec);
3984 KJS_CHECKEXCEPTIONVALUE
3985 if (!b1)
3986 return v1;
3987 JSValue* v2 = m_expr2->evaluate(exec);
3988 KJS_CHECKEXCEPTIONVALUE
3989 return v2;
3990}
3991
3992bool LogicalAndNode::evaluateToBoolean(OldInterpreterExecState* exec)
3993{
3994 bool b = m_expr1->evaluateToBoolean(exec);
3995 KJS_CHECKEXCEPTIONBOOLEAN
3996 return b && m_expr2->evaluateToBoolean(exec);
3997}
3998
3999RegisterID* LogicalOrNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4000{
4001 RefPtr<RegisterID> temp = generator.tempDestination(dst);
4002 RefPtr<LabelID> target = generator.newLabel();
4003
4004 generator.emitNode(temp.get(), m_expr1.get());
4005 generator.emitJumpIfTrue(temp.get(), target.get());
4006 generator.emitNode(temp.get(), m_expr2.get());
4007 generator.emitLabel(target.get());
4008
4009 return generator.moveToDestinationIfNeeded(dst, temp.get());
4010}
4011
4012void LogicalOrNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4013{
4014 nodeStack.append(m_expr2.get());
4015 nodeStack.append(m_expr1.get());
4016}
4017
4018JSValue* LogicalOrNode::evaluate(OldInterpreterExecState* exec)
4019{
4020 JSValue* v1 = m_expr1->evaluate(exec);
4021 KJS_CHECKEXCEPTIONVALUE
4022 if (v1->toBoolean(exec))
4023 return v1;
4024 return m_expr2->evaluate(exec);
4025}
4026
4027bool LogicalOrNode::evaluateToBoolean(OldInterpreterExecState* exec)
4028{
4029 bool b = m_expr1->evaluateToBoolean(exec);
4030 KJS_CHECKEXCEPTIONBOOLEAN
4031 return b || m_expr2->evaluateToBoolean(exec);
4032}
4033
4034// ------------------------------ ConditionalNode ------------------------------
4035
4036RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4037{
4038 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
4039 RefPtr<LabelID> beforeElse = generator.newLabel();
4040 RefPtr<LabelID> afterElse = generator.newLabel();
4041
4042 RegisterID* cond = generator.emitNode(m_logical.get());
4043 generator.emitJumpIfFalse(cond, beforeElse.get());
4044
4045 generator.emitNode(newDst.get(), m_expr1.get());
4046 generator.emitJump(afterElse.get());
4047
4048 generator.emitLabel(beforeElse.get());
4049 generator.emitNode(newDst.get(), m_expr2.get());
4050
4051 generator.emitLabel(afterElse.get());
4052
4053 return newDst.get();
4054}
4055
4056void ConditionalNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4057{
4058 nodeStack.append(m_expr2.get());
4059 nodeStack.append(m_expr1.get());
4060 nodeStack.append(m_logical.get());
4061}
4062
4063// ECMA 11.12
4064JSValue* ConditionalNode::evaluate(OldInterpreterExecState* exec)
4065{
4066 bool b = m_logical->evaluateToBoolean(exec);
4067 KJS_CHECKEXCEPTIONVALUE
4068 return b ? m_expr1->evaluate(exec) : m_expr2->evaluate(exec);
4069}
4070
4071bool ConditionalNode::evaluateToBoolean(OldInterpreterExecState* exec)
4072{
4073 bool b = m_logical->evaluateToBoolean(exec);
4074 KJS_CHECKEXCEPTIONBOOLEAN
4075 return b ? m_expr1->evaluateToBoolean(exec) : m_expr2->evaluateToBoolean(exec);
4076}
4077
4078double ConditionalNode::evaluateToNumber(OldInterpreterExecState* exec)
4079{
4080 bool b = m_logical->evaluateToBoolean(exec);
4081 KJS_CHECKEXCEPTIONNUMBER
4082 return b ? m_expr1->evaluateToNumber(exec) : m_expr2->evaluateToNumber(exec);
4083}
4084
4085int32_t ConditionalNode::evaluateToInt32(OldInterpreterExecState* exec)
4086{
4087 bool b = m_logical->evaluateToBoolean(exec);
4088 KJS_CHECKEXCEPTIONNUMBER
4089 return b ? m_expr1->evaluateToInt32(exec) : m_expr2->evaluateToInt32(exec);
4090}
4091
4092uint32_t ConditionalNode::evaluateToUInt32(OldInterpreterExecState* exec)
4093{
4094 bool b = m_logical->evaluateToBoolean(exec);
4095 KJS_CHECKEXCEPTIONNUMBER
4096 return b ? m_expr1->evaluateToUInt32(exec) : m_expr2->evaluateToUInt32(exec);
4097}
4098
4099// ECMA 11.13
4100
4101static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(OldInterpreterExecState* exec, JSValue* current, ExpressionNode* right, Operator oper) KJS_FAST_CALL;
4102static ALWAYS_INLINE JSValue* valueForReadModifyAssignment(OldInterpreterExecState* exec, JSValue* current, ExpressionNode* right, Operator oper)
4103{
4104 JSValue* v;
4105 int i1;
4106 int i2;
4107 unsigned int ui;
4108 switch (oper) {
4109 case OpMultEq:
4110 v = jsNumber(current->toNumber(exec) * right->evaluateToNumber(exec));
4111 break;
4112 case OpDivEq:
4113 v = jsNumber(current->toNumber(exec) / right->evaluateToNumber(exec));
4114 break;
4115 case OpPlusEq:
4116 v = add(exec, current, right->evaluate(exec));
4117 break;
4118 case OpMinusEq:
4119 v = jsNumber(current->toNumber(exec) - right->evaluateToNumber(exec));
4120 break;
4121 case OpLShift:
4122 i1 = current->toInt32(exec);
4123 i2 = right->evaluateToInt32(exec);
4124 v = jsNumber(i1 << i2);
4125 break;
4126 case OpRShift:
4127 i1 = current->toInt32(exec);
4128 i2 = right->evaluateToInt32(exec);
4129 v = jsNumber(i1 >> i2);
4130 break;
4131 case OpURShift:
4132 ui = current->toUInt32(exec);
4133 i2 = right->evaluateToInt32(exec);
4134 v = jsNumber(ui >> i2);
4135 break;
4136 case OpAndEq:
4137 i1 = current->toInt32(exec);
4138 i2 = right->evaluateToInt32(exec);
4139 v = jsNumber(i1 & i2);
4140 break;
4141 case OpXOrEq:
4142 i1 = current->toInt32(exec);
4143 i2 = right->evaluateToInt32(exec);
4144 v = jsNumber(i1 ^ i2);
4145 break;
4146 case OpOrEq:
4147 i1 = current->toInt32(exec);
4148 i2 = right->evaluateToInt32(exec);
4149 v = jsNumber(i1 | i2);
4150 break;
4151 case OpModEq: {
4152 double d1 = current->toNumber(exec);
4153 double d2 = right->evaluateToNumber(exec);
4154 v = jsNumber(fmod(d1, d2));
4155 }
4156 break;
4157 default:
4158 ASSERT_NOT_REACHED();
4159 v = jsUndefined();
4160 }
4161
4162 return v;
4163}
4164
4165// ------------------------------ ReadModifyResolveNode -----------------------------------
4166
4167// FIXME: should this be moved to be a method on CodeGenerator?
4168static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper)
4169{
4170 switch (oper) {
4171 case OpMultEq:
4172 return generator.emitMul(dst, src1, src2);
4173 case OpDivEq:
4174 return generator.emitDiv(dst, src1, src2);
4175 case OpPlusEq:
4176 return generator.emitAdd(dst, src1, src2);
4177 case OpMinusEq:
4178 return generator.emitSub(dst, src1, src2);
4179 case OpLShift:
4180 return generator.emitLeftShift(dst, src1, src2);
4181 case OpRShift:
4182 return generator.emitRightShift(dst, src1, src2);
4183 case OpURShift:
4184 return generator.emitUnsignedRightShift(dst, src1, src2);
4185 case OpAndEq:
4186 return generator.emitBitAnd(dst, src1, src2);
4187 case OpXOrEq:
4188 return generator.emitBitXOr(dst, src1, src2);
4189 case OpOrEq:
4190 return generator.emitBitOr(dst, src1, src2);
4191 case OpModEq:
4192 return generator.emitMod(dst, src1, src2);
4193 default:
4194 ASSERT_NOT_REACHED();
4195 }
4196
4197 return dst;
4198}
4199
4200RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4201{
4202 if (RegisterID* local = generator.registerForLocal(m_ident)) {
4203 if (generator.isLocalConstant(m_ident)) {
4204 RegisterID* src2 = generator.emitNode(m_right.get());
4205 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator);
4206 }
4207
4208 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments) && !m_right.get()->isNumber()) {
4209 RefPtr<RegisterID> result = generator.newTemporary();
4210 generator.emitMove(result.get(), local);
4211 RegisterID* src2 = generator.emitNode(m_right.get());
4212 emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator);
4213 generator.emitMove(local, result.get());
4214 return generator.moveToDestinationIfNeeded(dst, result.get());
4215 }
4216
4217 RegisterID* src2 = generator.emitNode(m_right.get());
4218 RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator);
4219 return generator.moveToDestinationIfNeeded(dst, result);
4220 }
4221
4222 int index = 0;
4223 size_t depth = 0;
4224 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
4225 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
4226 RegisterID* src2 = generator.emitNode(m_right.get());
4227 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
4228 generator.emitPutScopedVar(depth, index, result);
4229 return result;
4230 }
4231
4232 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
4233 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
4234 RegisterID* src2 = generator.emitNode(m_right.get());
4235 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
4236 return generator.emitPutById(base.get(), m_ident, result);
4237}
4238
4239void ReadModifyResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
4240{
4241 nodeStack.append(m_right.get());
4242 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
4243 if (index != missingSymbolMarker()) {
4244 if (isConstant(localStorage, index))
4245 new (this) ReadModifyConstNode(index);
4246 else
4247 new (this) ReadModifyLocalVarNode(index);
4248 }
4249}
4250
4251// ------------------------------ AssignResolveNode -----------------------------------
4252
4253RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4254{
4255 if (RegisterID* local = generator.registerForLocal(m_ident)) {
4256 if (generator.isLocalConstant(m_ident))
4257 return generator.emitNode(dst, m_right.get());
4258
4259 RegisterID* result = generator.emitNode(local, m_right.get());
4260 return generator.moveToDestinationIfNeeded(dst, result);
4261 }
4262
4263 int index = 0;
4264 size_t depth = 0;
4265 if (generator.findScopedProperty(m_ident, index, depth) && index != missingSymbolMarker()) {
4266 RegisterID* value = generator.emitNode(dst, m_right.get());
4267 generator.emitPutScopedVar(depth, index, value);
4268 return value;
4269 }
4270
4271 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
4272 RegisterID* value = generator.emitNode(dst, m_right.get());
4273 return generator.emitPutById(base.get(), m_ident, value);
4274}
4275
4276void AssignResolveNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
4277{
4278 nodeStack.append(m_right.get());
4279 int index = symbolTable.get(m_ident.ustring().rep()).getIndex();
4280 if (index != missingSymbolMarker()) {
4281 if (isConstant(localStorage, index))
4282 new (this) AssignConstNode;
4283 else
4284 new (this) AssignLocalVarNode(index);
4285 }
4286}
4287
4288// ------------------------------ ReadModifyLocalVarNode -----------------------------------
4289
4290JSValue* ReadModifyLocalVarNode::evaluate(OldInterpreterExecState* exec)
4291{
4292 ASSERT(exec->variableObject() == exec->scopeChain().top());
4293
4294 ASSERT(m_operator != OpEqual);
4295 JSValue* v = valueForReadModifyAssignment(exec, exec->localStorage()[m_index].value, m_right.get(), m_operator);
4296
4297 KJS_CHECKEXCEPTIONVALUE
4298
4299 // We can't store a pointer into localStorage() and use it throughout the function
4300 // body, because valueForReadModifyAssignment() might cause an ActivationImp tear-off,
4301 // changing the value of localStorage().
4302
4303 exec->localStorage()[m_index].value = v;
4304 return v;
4305}
4306
4307// ------------------------------ AssignLocalVarNode -----------------------------------
4308
4309JSValue* AssignLocalVarNode::evaluate(OldInterpreterExecState* exec)
4310{
4311 ASSERT(exec->variableObject() == exec->scopeChain().top());
4312 JSValue* v = m_right->evaluate(exec);
4313
4314 KJS_CHECKEXCEPTIONVALUE
4315
4316 exec->localStorage()[m_index].value = v;
4317
4318 return v;
4319}
4320
4321// ------------------------------ ReadModifyConstNode -----------------------------------
4322
4323JSValue* ReadModifyConstNode::evaluate(OldInterpreterExecState* exec)
4324{
4325 ASSERT(exec->variableObject() == exec->scopeChain().top());
4326 JSValue* left = exec->localStorage()[m_index].value;
4327 ASSERT(m_operator != OpEqual);
4328 JSValue* result = valueForReadModifyAssignment(exec, left, m_right.get(), m_operator);
4329 KJS_CHECKEXCEPTIONVALUE
4330 return result;
4331}
4332
4333// ------------------------------ AssignConstNode -----------------------------------
4334
4335JSValue* AssignConstNode::evaluate(OldInterpreterExecState* exec)
4336{
4337 return m_right->evaluate(exec);
4338}
4339
4340JSValue* ReadModifyResolveNode::evaluate(OldInterpreterExecState* exec)
4341{
4342 const ScopeChain& chain = exec->scopeChain();
4343 ScopeChainIterator iter = chain.begin();
4344 ScopeChainIterator end = chain.end();
4345
4346 // We must always have something in the scope chain
4347 ASSERT(iter != end);
4348
4349 PropertySlot slot;
4350 JSObject* base;
4351 do {
4352 base = *iter;
4353 if (base->getPropertySlot(exec, m_ident, slot)) {
4354 // See the comment in PostIncResolveNode::evaluate().
4355
4356 base = *iter;
4357 goto found;
4358 }
4359
4360 ++iter;
4361 } while (iter != end);
4362
4363 ASSERT(m_operator != OpEqual);
4364 return throwUndefinedVariableError(exec, m_ident);
4365
4366found:
4367 JSValue* v;
4368
4369 ASSERT(m_operator != OpEqual);
4370 JSValue* v1 = slot.getValue(exec, base, m_ident);
4371 KJS_CHECKEXCEPTIONVALUE
4372 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
4373
4374 KJS_CHECKEXCEPTIONVALUE
4375
4376 // Since valueForReadModifyAssignment() might cause an ActivationImp tear-off,
4377 // we need to get the base from the ScopeChainIterator again.
4378
4379 (*iter)->put(exec, m_ident, v);
4380 return v;
4381}
4382
4383JSValue* AssignResolveNode::evaluate(OldInterpreterExecState* exec)
4384{
4385 const ScopeChain& chain = exec->scopeChain();
4386 ScopeChainIterator iter = chain.begin();
4387 ScopeChainIterator end = chain.end();
4388
4389 // we must always have something in the scope chain
4390 ASSERT(iter != end);
4391
4392 PropertySlot slot;
4393 JSObject* base;
4394 do {
4395 base = *iter;
4396 if (base->getPropertySlot(exec, m_ident, slot)) {
4397 // See the comment in PostIncResolveNode::evaluate().
4398
4399 base = *iter;
4400 goto found;
4401 }
4402
4403 ++iter;
4404 } while (iter != end);
4405
4406found:
4407 JSValue* v = m_right->evaluate(exec);
4408
4409 KJS_CHECKEXCEPTIONVALUE
4410
4411 base->put(exec, m_ident, v);
4412 return v;
4413}
4414
4415// ------------------------------ ReadModifyDotNode -----------------------------------
4416
4417RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4418{
4419 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments);
4420 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
4421 RegisterID* result = generator.emitNode(value.get(), m_right.get());
4422 generator.emitPutById(base.get(), m_ident, result);
4423 return generator.moveToDestinationIfNeeded(dst, result);
4424}
4425
4426void AssignDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4427{
4428 nodeStack.append(m_right.get());
4429 nodeStack.append(m_base.get());
4430}
4431
4432JSValue* AssignDotNode::evaluate(OldInterpreterExecState* exec)
4433{
4434 JSValue* baseValue = m_base->evaluate(exec);
4435 KJS_CHECKEXCEPTIONVALUE
4436 JSObject* base = baseValue->toObject(exec);
4437
4438 JSValue* v = m_right->evaluate(exec);
4439
4440 KJS_CHECKEXCEPTIONVALUE
4441
4442 base->put(exec, m_ident, v);
4443 return v;
4444}
4445
4446RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4447{
4448 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments);
4449 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
4450 RegisterID* change = generator.emitNode(m_right.get());
4451 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
4452 return generator.emitPutById(base.get(), m_ident, updatedValue);
4453}
4454
4455void ReadModifyDotNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4456{
4457 nodeStack.append(m_right.get());
4458 nodeStack.append(m_base.get());
4459}
4460
4461JSValue* ReadModifyDotNode::evaluate(OldInterpreterExecState* exec)
4462{
4463 JSValue* baseValue = m_base->evaluate(exec);
4464 KJS_CHECKEXCEPTIONVALUE
4465 JSObject* base = baseValue->toObject(exec);
4466
4467 JSValue* v;
4468
4469 ASSERT(m_operator != OpEqual);
4470 PropertySlot slot;
4471 JSValue* v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
4472 KJS_CHECKEXCEPTIONVALUE
4473 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
4474
4475 KJS_CHECKEXCEPTIONVALUE
4476
4477 base->put(exec, m_ident, v);
4478 return v;
4479}
4480
4481// ------------------------------ AssignErrorNode -----------------------------------
4482
4483RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
4484{
4485 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
4486}
4487
4488JSValue* AssignErrorNode::evaluate(OldInterpreterExecState* exec)
4489{
4490 throwError(exec, ReferenceError, "Left side of assignment is not a reference.");
4491 handleException(exec);
4492 return jsUndefined();
4493}
4494
4495// ------------------------------ AssignBracketNode -----------------------------------
4496
4497RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4498{
4499 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments);
4500 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments);
4501 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
4502 RegisterID* result = generator.emitNode(value.get(), m_right.get());
4503 generator.emitPutByVal(base.get(), property.get(), result);
4504 return generator.moveToDestinationIfNeeded(dst, result);
4505}
4506
4507void AssignBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4508{
4509 nodeStack.append(m_right.get());
4510 nodeStack.append(m_subscript.get());
4511 nodeStack.append(m_base.get());
4512}
4513
4514JSValue* AssignBracketNode::evaluate(OldInterpreterExecState* exec)
4515{
4516 JSValue* baseValue = m_base->evaluate(exec);
4517 KJS_CHECKEXCEPTIONVALUE
4518 JSValue* subscript = m_subscript->evaluate(exec);
4519 KJS_CHECKEXCEPTIONVALUE
4520
4521 JSObject* base = baseValue->toObject(exec);
4522
4523 uint32_t propertyIndex;
4524 if (subscript->getUInt32(propertyIndex)) {
4525 JSValue* v = m_right->evaluate(exec);
4526 KJS_CHECKEXCEPTIONVALUE
4527
4528 base->put(exec, propertyIndex, v);
4529 return v;
4530 }
4531
4532 Identifier propertyName(subscript->toString(exec));
4533 JSValue* v = m_right->evaluate(exec);
4534 KJS_CHECKEXCEPTIONVALUE
4535
4536 base->put(exec, propertyName, v);
4537 return v;
4538}
4539
4540RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4541{
4542 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments);
4543 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments);
4544
4545 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
4546 RegisterID* change = generator.emitNode(m_right.get());
4547 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
4548
4549 generator.emitPutByVal(base.get(), property.get(), updatedValue);
4550
4551 return updatedValue;
4552}
4553
4554void ReadModifyBracketNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4555{
4556 nodeStack.append(m_right.get());
4557 nodeStack.append(m_subscript.get());
4558 nodeStack.append(m_base.get());
4559}
4560
4561JSValue* ReadModifyBracketNode::evaluate(OldInterpreterExecState* exec)
4562{
4563 JSValue* baseValue = m_base->evaluate(exec);
4564 KJS_CHECKEXCEPTIONVALUE
4565 JSValue* subscript = m_subscript->evaluate(exec);
4566 KJS_CHECKEXCEPTIONVALUE
4567
4568 JSObject* base = baseValue->toObject(exec);
4569
4570 uint32_t propertyIndex;
4571 if (subscript->getUInt32(propertyIndex)) {
4572 JSValue* v;
4573 ASSERT(m_operator != OpEqual);
4574 PropertySlot slot;
4575 JSValue* v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
4576 KJS_CHECKEXCEPTIONVALUE
4577 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
4578
4579 KJS_CHECKEXCEPTIONVALUE
4580
4581 base->put(exec, propertyIndex, v);
4582 return v;
4583 }
4584
4585 Identifier propertyName(subscript->toString(exec));
4586 JSValue* v;
4587
4588 ASSERT(m_operator != OpEqual);
4589 PropertySlot slot;
4590 JSValue* v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
4591 KJS_CHECKEXCEPTIONVALUE
4592 v = valueForReadModifyAssignment(exec, v1, m_right.get(), m_operator);
4593
4594 KJS_CHECKEXCEPTIONVALUE
4595
4596 base->put(exec, propertyName, v);
4597 return v;
4598}
4599
4600// ------------------------------ CommaNode ------------------------------------
4601
4602RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4603{
4604 generator.emitNode(m_expr1.get());
4605 return generator.emitNode(dst, m_expr2.get());
4606}
4607
4608void CommaNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4609{
4610 nodeStack.append(m_expr2.get());
4611 nodeStack.append(m_expr1.get());
4612}
4613
4614// ECMA 11.14
4615JSValue* CommaNode::evaluate(OldInterpreterExecState* exec)
4616{
4617 m_expr1->evaluate(exec);
4618 KJS_CHECKEXCEPTIONVALUE
4619 return m_expr2->evaluate(exec);
4620}
4621
4622// ------------------------------ ConstDeclNode ----------------------------------
4623
4624ConstDeclNode::ConstDeclNode(const Identifier& ident, ExpressionNode* init)
4625 : m_ident(ident)
4626 , m_init(init)
4627{
4628}
4629
4630void ConstDeclNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4631{
4632 if (m_next)
4633 nodeStack.append(m_next.get());
4634 if (m_init)
4635 nodeStack.append(m_init.get());
4636}
4637
4638void ConstDeclNode::handleSlowCase(OldInterpreterExecState* exec, const ScopeChain& chain, JSValue* val)
4639{
4640 ScopeChainIterator iter = chain.begin();
4641 ScopeChainIterator end = chain.end();
4642
4643 // We must always have something in the scope chain
4644 ASSERT(iter != end);
4645
4646 JSObject* base;
4647
4648 do {
4649 base = *iter;
4650 if (base->isVariableObject())
4651 break;
4652 ++iter;
4653 } while (iter != end);
4654
4655 ASSERT(base && base->isVariableObject());
4656
4657 static_cast<JSVariableObject*>(base)->putWithAttributes(exec, m_ident, val, ReadOnly);
4658}
4659
4660// ECMA 12.2
4661inline void ConstDeclNode::evaluateSingle(OldInterpreterExecState* exec)
4662{
4663 ASSERT(exec->variableObject()->hasOwnProperty(exec, m_ident) || exec->codeType() == EvalCode); // Guaranteed by processDeclarations.
4664 const ScopeChain& chain = exec->scopeChain();
4665 JSVariableObject* variableObject = exec->variableObject();
4666
4667 bool inGlobalScope = ++chain.begin() == chain.end();
4668
4669 if (m_init) {
4670 if (inGlobalScope) {
4671 JSValue* val = m_init->evaluate(exec);
4672 unsigned attributes = ReadOnly;
4673 if (exec->codeType() != EvalCode)
4674 attributes |= DontDelete;
4675 variableObject->putWithAttributes(exec, m_ident, val, attributes);
4676 } else {
4677 JSValue* val = m_init->evaluate(exec);
4678 KJS_CHECKEXCEPTIONVOID
4679
4680 // if the variable object is the top of the scope chain, then that must
4681 // be where this variable is declared, processVarDecls would have put
4682 // it there. Don't search the scope chain, to optimize this very common case.
4683 if (chain.top() != variableObject)
4684 return handleSlowCase(exec, chain, val);
4685
4686 variableObject->putWithAttributes(exec, m_ident, val, ReadOnly);
4687 }
4688 }
4689}
4690
4691RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
4692{
4693 if (RegisterID* local = generator.registerForLocalConstInit(m_ident)) {
4694 if (!m_init)
4695 return local;
4696
4697 return generator.emitNode(local, m_init.get());
4698 }
4699
4700 // FIXME: While this code should only be hit in eval code, it will potentially
4701 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
4702 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
4703 RegisterID* value = generator.emitNode(m_init.get());
4704 return generator.emitPutById(base.get(), m_ident, value);
4705}
4706
4707RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
4708{
4709 RegisterID* result = 0;
4710 for (ConstDeclNode* n = this; n; n = n->m_next.get())
4711 result = n->emitCodeSingle(generator);
4712
4713 return result;
4714}
4715
4716JSValue* ConstDeclNode::evaluate(OldInterpreterExecState* exec)
4717{
4718 evaluateSingle(exec);
4719
4720 if (ConstDeclNode* n = m_next.get()) {
4721 do {
4722 n->evaluateSingle(exec);
4723 KJS_CHECKEXCEPTIONVALUE
4724 n = n->m_next.get();
4725 } while (n);
4726 }
4727 return jsUndefined();
4728}
4729
4730// ------------------------------ ConstStatementNode -----------------------------
4731
4732void ConstStatementNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4733{
4734 ASSERT(m_next);
4735 nodeStack.append(m_next.get());
4736}
4737
4738RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
4739{
4740 return generator.emitNode(m_next.get());
4741}
4742
4743// ECMA 12.2
4744JSValue* ConstStatementNode::execute(OldInterpreterExecState* exec)
4745{
4746 m_next->evaluate(exec);
4747 KJS_CHECKEXCEPTION
4748
4749 return exec->setNormalCompletion();
4750}
4751
4752// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
4753
4754static inline RegisterID* statementListEmitCode(StatementVector& statements, CodeGenerator& generator, RegisterID* dst = 0)
4755{
4756 RefPtr<RegisterID> r0 = dst;
4757
4758 StatementVector::iterator end = statements.end();
4759 for (StatementVector::iterator it = statements.begin(); it != end; ++it) {
4760 StatementNode* n = it->get();
4761 generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
4762 if (RegisterID* r1 = generator.emitNode(dst, n))
4763 r0 = r1;
4764 }
4765
4766 return r0.get();
4767}
4768
4769static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
4770{
4771 StatementVector::iterator it = statements.end();
4772 StatementVector::iterator begin = statements.begin();
4773 while (it != begin) {
4774 --it;
4775 stack.append((*it).get());
4776 }
4777}
4778
4779static inline Node* statementListInitializeVariableAccessStack(StatementVector& statements, DeclarationStacks::NodeStack& stack)
4780{
4781 if (statements.isEmpty())
4782 return 0;
4783
4784 StatementVector::iterator it = statements.end();
4785 StatementVector::iterator begin = statements.begin();
4786 StatementVector::iterator beginPlusOne = begin + 1;
4787
4788 while (it != beginPlusOne) {
4789 --it;
4790 stack.append((*it).get());
4791 }
4792
4793 return (*begin).get();
4794}
4795
4796static inline JSValue* statementListExecute(StatementVector& statements, OldInterpreterExecState* exec)
4797{
4798 JSValue* value = 0;
4799 size_t size = statements.size();
4800 for (size_t i = 0; i != size; ++i) {
4801 JSValue* statementValue = statements[i]->execute(exec);
4802 if (statementValue)
4803 value = statementValue;
4804 if (exec->completionType() != Normal)
4805 return value;
4806 }
4807 return exec->setNormalCompletion(value);
4808}
4809
4810// ------------------------------ BlockNode ------------------------------------
4811
4812BlockNode::BlockNode(SourceElements* children)
4813{
4814 if (children)
4815 children->releaseContentsIntoVector(m_children);
4816}
4817
4818RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4819{
4820 return statementListEmitCode(m_children, generator, dst);
4821}
4822
4823void BlockNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4824{
4825 statementListPushFIFO(m_children, nodeStack);
4826}
4827
4828// ECMA 12.1
4829JSValue* BlockNode::execute(OldInterpreterExecState* exec)
4830{
4831 return statementListExecute(m_children, exec);
4832}
4833
4834// ------------------------------ EmptyStatementNode ---------------------------
4835
4836RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
4837{
4838 return dst;
4839}
4840
4841// ECMA 12.3
4842JSValue* EmptyStatementNode::execute(OldInterpreterExecState* exec)
4843{
4844 return exec->setNormalCompletion();
4845}
4846
4847// ------------------------------ ExprStatementNode ----------------------------
4848
4849RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4850{
4851 ASSERT(m_expr);
4852 return generator.emitNode(dst, m_expr.get());
4853}
4854
4855void ExprStatementNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4856{
4857 ASSERT(m_expr);
4858 nodeStack.append(m_expr.get());
4859}
4860
4861// ECMA 12.4
4862JSValue* ExprStatementNode::execute(OldInterpreterExecState* exec)
4863{
4864 JSValue* value = m_expr->evaluate(exec);
4865 KJS_CHECKEXCEPTION
4866
4867 return exec->setNormalCompletion(value);
4868}
4869
4870// ------------------------------ VarStatementNode ----------------------------
4871
4872RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
4873{
4874 ASSERT(m_expr);
4875 return generator.emitNode(m_expr.get());
4876}
4877
4878void VarStatementNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4879{
4880 ASSERT(m_expr);
4881 nodeStack.append(m_expr.get());
4882}
4883
4884JSValue* VarStatementNode::execute(OldInterpreterExecState* exec)
4885{
4886 m_expr->evaluate(exec);
4887 KJS_CHECKEXCEPTION
4888
4889 return exec->setNormalCompletion();
4890}
4891
4892// ------------------------------ IfNode ---------------------------------------
4893
4894RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4895{
4896 RefPtr<LabelID> afterThen = generator.newLabel();
4897
4898 RegisterID* cond = generator.emitNode(m_condition.get());
4899 generator.emitJumpIfFalse(cond, afterThen.get());
4900
4901 generator.emitNode(dst, m_ifBlock.get());
4902 generator.emitLabel(afterThen.get());
4903
4904 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
4905 return 0;
4906}
4907
4908void IfNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4909{
4910 nodeStack.append(m_ifBlock.get());
4911 nodeStack.append(m_condition.get());
4912}
4913
4914// ECMA 12.5
4915JSValue* IfNode::execute(OldInterpreterExecState* exec)
4916{
4917 bool b = m_condition->evaluateToBoolean(exec);
4918 KJS_CHECKEXCEPTION
4919
4920 if (b)
4921 return m_ifBlock->execute(exec);
4922 return exec->setNormalCompletion();
4923}
4924
4925RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4926{
4927 RefPtr<LabelID> beforeElse = generator.newLabel();
4928 RefPtr<LabelID> afterElse = generator.newLabel();
4929
4930 RegisterID* cond = generator.emitNode(m_condition.get());
4931 generator.emitJumpIfFalse(cond, beforeElse.get());
4932
4933 generator.emitNode(dst, m_ifBlock.get());
4934 generator.emitJump(afterElse.get());
4935
4936 generator.emitLabel(beforeElse.get());
4937 generator.emitNode(dst, m_elseBlock.get());
4938
4939 generator.emitLabel(afterElse.get());
4940
4941 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
4942 return 0;
4943}
4944
4945void IfElseNode::optimizeVariableAccess(OldInterpreterExecState* exec, const SymbolTable& symbolTable, const LocalStorage& localStorage, NodeStack& nodeStack)
4946{
4947 nodeStack.append(m_elseBlock.get());
4948 IfNode::optimizeVariableAccess(exec, symbolTable, localStorage, nodeStack);
4949}
4950
4951// ECMA 12.5
4952JSValue* IfElseNode::execute(OldInterpreterExecState* exec)
4953{
4954 bool b = m_condition->evaluateToBoolean(exec);
4955 KJS_CHECKEXCEPTION
4956
4957 if (b)
4958 return m_ifBlock->execute(exec);
4959 return m_elseBlock->execute(exec);
4960}
4961
4962// ------------------------------ DoWhileNode ----------------------------------
4963
4964RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
4965{
4966 RefPtr<LabelID> topOfLoop = generator.newLabel();
4967 generator.emitLabel(topOfLoop.get());
4968
4969 RefPtr<LabelID> continueTarget = generator.newLabel();
4970 RefPtr<LabelID> breakTarget = generator.newLabel();
4971
4972 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
4973 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
4974 generator.popJumpContext();
4975
4976 generator.emitLabel(continueTarget.get());
4977 RegisterID* cond = generator.emitNode(m_expr.get());
4978 generator.emitJumpIfTrue(cond, topOfLoop.get());
4979 generator.emitLabel(breakTarget.get());
4980 return result.get();
4981}
4982
4983void DoWhileNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
4984{
4985 nodeStack.append(m_statement.get());
4986 nodeStack.append(m_expr.get());
4987}
4988
4989// ECMA 12.6.1
4990JSValue* DoWhileNode::execute(OldInterpreterExecState* exec)
4991{
4992 JSValue* value = 0;
4993
4994 while (1) {
4995 exec->pushIteration();
4996 JSValue* statementValue = m_statement->execute(exec);
4997 exec->popIteration();
4998
4999 if (exec->dynamicGlobalObject()->timedOut())
5000 return exec->setInterruptedCompletion();
5001
5002 if (statementValue)
5003 value = statementValue;
5004
5005 if (exec->completionType() != Normal) {
5006 if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
5007 goto continueDoWhileLoop;
5008 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
5009 break;
5010 return statementValue;
5011 }
5012
5013 continueDoWhileLoop:
5014 bool b = m_expr->evaluateToBoolean(exec);
5015 KJS_CHECKEXCEPTION
5016 if (!b)
5017 break;
5018 }
5019
5020 return exec->setNormalCompletion(value);
5021}
5022
5023// ------------------------------ WhileNode ------------------------------------
5024
5025RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5026{
5027 RefPtr<LabelID> topOfLoop = generator.newLabel();
5028 RefPtr<LabelID> continueTarget = generator.newLabel();
5029 RefPtr<LabelID> breakTarget = generator.newLabel();
5030
5031 generator.emitJump(continueTarget.get());
5032 generator.emitLabel(topOfLoop.get());
5033
5034 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
5035 generator.emitNode(dst, m_statement.get());
5036 generator.popJumpContext();
5037
5038 generator.emitLabel(continueTarget.get());
5039 RegisterID* cond = generator.emitNode(m_expr.get());
5040 generator.emitJumpIfTrue(cond, topOfLoop.get());
5041
5042 generator.emitLabel(breakTarget.get());
5043
5044 // FIXME: This should return the last statement executed so that it can be returned as a Completion
5045 return 0;
5046}
5047
5048void WhileNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5049{
5050 nodeStack.append(m_statement.get());
5051 nodeStack.append(m_expr.get());
5052}
5053
5054// ECMA 12.6.2
5055JSValue* WhileNode::execute(OldInterpreterExecState* exec)
5056{
5057 JSValue* value = 0;
5058
5059 while (1) {
5060 bool b = m_expr->evaluateToBoolean(exec);
5061 KJS_CHECKEXCEPTION
5062 if (!b)
5063 break;
5064
5065 exec->pushIteration();
5066 JSValue* statementValue = m_statement->execute(exec);
5067 exec->popIteration();
5068
5069 if (exec->dynamicGlobalObject()->timedOut())
5070 return exec->setInterruptedCompletion();
5071
5072 if (statementValue)
5073 value = statementValue;
5074
5075 if (exec->completionType() != Normal) {
5076 if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
5077 continue;
5078 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
5079 break;
5080 return statementValue;
5081 }
5082 }
5083
5084 return exec->setNormalCompletion(value);
5085}
5086
5087// ------------------------------ ForNode --------------------------------------
5088
5089RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5090{
5091 generator.emitNode(m_expr1.get());
5092
5093 RefPtr<LabelID> topOfLoop = generator.newLabel();
5094 RefPtr<LabelID> beforeCondition = generator.newLabel();
5095 RefPtr<LabelID> continueTarget = generator.newLabel();
5096 RefPtr<LabelID> breakTarget = generator.newLabel();
5097 generator.emitJump(beforeCondition.get());
5098
5099 generator.emitLabel(topOfLoop.get());
5100 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
5101 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
5102 generator.popJumpContext();
5103 generator.emitLabel(continueTarget.get());
5104 generator.emitNode(m_expr3.get());
5105
5106 generator.emitLabel(beforeCondition.get());
5107 RegisterID* cond = generator.emitNode(m_expr2.get());
5108 generator.emitJumpIfTrue(cond, topOfLoop.get());
5109 generator.emitLabel(breakTarget.get());
5110 return result.get();
5111}
5112
5113void ForNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5114{
5115 nodeStack.append(m_statement.get());
5116 nodeStack.append(m_expr3.get());
5117 nodeStack.append(m_expr2.get());
5118 nodeStack.append(m_expr1.get());
5119}
5120
5121// ECMA 12.6.3
5122JSValue* ForNode::execute(OldInterpreterExecState* exec)
5123{
5124 JSValue* value = 0;
5125
5126 m_expr1->evaluate(exec);
5127 KJS_CHECKEXCEPTION
5128
5129 while (1) {
5130 bool b = m_expr2->evaluateToBoolean(exec);
5131 KJS_CHECKEXCEPTION
5132 if (!b)
5133 break;
5134
5135 exec->pushIteration();
5136 JSValue* statementValue = m_statement->execute(exec);
5137 exec->popIteration();
5138 if (statementValue)
5139 value = statementValue;
5140
5141 if (exec->dynamicGlobalObject()->timedOut())
5142 return exec->setInterruptedCompletion();
5143
5144 if (exec->completionType() != Normal) {
5145 if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
5146 goto continueForLoop;
5147 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
5148 break;
5149 return statementValue;
5150 }
5151
5152 continueForLoop:
5153 m_expr3->evaluate(exec);
5154 KJS_CHECKEXCEPTION
5155 }
5156
5157 return exec->setNormalCompletion(value);
5158}
5159
5160// ------------------------------ ForInNode ------------------------------------
5161
5162ForInNode::ForInNode(ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
5163 : m_init(0L)
5164 , m_lexpr(l)
5165 , m_expr(expr)
5166 , m_statement(statement)
5167 , m_identIsVarDecl(false)
5168{
5169}
5170
5171ForInNode::ForInNode(const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement)
5172 : m_ident(ident)
5173 , m_lexpr(new ResolveNode(ident))
5174 , m_expr(expr)
5175 , m_statement(statement)
5176 , m_identIsVarDecl(true)
5177{
5178 if (in)
5179 m_init = new AssignResolveNode(ident, in, true);
5180 // for( var foo = bar in baz )
5181}
5182
5183void ForInNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5184{
5185 nodeStack.append(m_statement.get());
5186 nodeStack.append(m_expr.get());
5187 nodeStack.append(m_lexpr.get());
5188 if (m_init)
5189 nodeStack.append(m_init.get());
5190}
5191
5192RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5193{
5194 RefPtr<LabelID> loopStart = generator.newLabel();
5195 RefPtr<LabelID> continueTarget = generator.newLabel();
5196 RefPtr<LabelID> breakTarget = generator.newLabel();
5197
5198 if (m_init)
5199 generator.emitNode(m_init.get());
5200 RegisterID* forInBase = generator.emitNode(m_expr.get());
5201 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
5202 generator.emitJump(continueTarget.get());
5203 generator.emitLabel(loopStart.get());
5204 RegisterID* propertyName;
5205 if (m_lexpr->isResolveNode()) {
5206 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
5207 propertyName = generator.registerForLocal(ident);
5208 if (!propertyName) {
5209 propertyName = generator.newTemporary();
5210 RefPtr<RegisterID> protect = propertyName;
5211 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
5212 generator.emitPutById(base, ident, propertyName);
5213 }
5214 } else if (m_lexpr->isDotAccessorNode()) {
5215 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
5216 const Identifier& ident = assignNode->identifier();
5217 propertyName = generator.newTemporary();
5218 RefPtr<RegisterID> protect = propertyName;
5219 RegisterID* base = generator.emitNode(assignNode->base());
5220 generator.emitPutById(base, ident, propertyName);
5221 } else {
5222 ASSERT(m_lexpr->isBracketAccessorNode());
5223 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
5224 propertyName = generator.newTemporary();
5225 RefPtr<RegisterID> protect = propertyName;
5226 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
5227 RegisterID* subscript = generator.emitNode(assignNode->subscript());
5228 generator.emitPutByVal(base.get(), subscript, propertyName);
5229 }
5230
5231 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
5232 generator.emitNode(dst, m_statement.get());
5233 generator.popJumpContext();
5234
5235 generator.emitLabel(continueTarget.get());
5236 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
5237 generator.emitLabel(breakTarget.get());
5238 return dst;
5239}
5240
5241// ECMA 12.6.4
5242JSValue* ForInNode::execute(OldInterpreterExecState* exec)
5243{
5244 JSValue* value = 0;
5245
5246 if (m_init) {
5247 m_init->evaluate(exec);
5248 KJS_CHECKEXCEPTION
5249 }
5250
5251 JSValue* e = m_expr->evaluate(exec);
5252 KJS_CHECKEXCEPTION
5253
5254 // For Null and Undefined, we want to make sure not to go through
5255 // the loop at all, because toObject will throw an exception.
5256 if (e->isUndefinedOrNull())
5257 return exec->setNormalCompletion();
5258
5259 JSObject* v = e->toObject(exec);
5260 PropertyNameArray propertyNames;
5261 v->getPropertyNames(exec, propertyNames);
5262
5263 PropertyNameArray::const_iterator end = propertyNames.end();
5264 for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != end; ++it) {
5265 const Identifier& name = *it;
5266 if (!v->hasProperty(exec, name))
5267 continue;
5268
5269 JSValue* str = jsOwnedString(name.ustring());
5270
5271 if (m_lexpr->isResolveNode()) {
5272 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
5273
5274 const ScopeChain& chain = exec->scopeChain();
5275 ScopeChainIterator iter = chain.begin();
5276 ScopeChainIterator end = chain.end();
5277
5278 // we must always have something in the scope chain
5279 ASSERT(iter != end);
5280
5281 PropertySlot slot;
5282 JSObject* o;
5283 do {
5284 o = *iter;
5285 if (o->getPropertySlot(exec, ident, slot)) {
5286 o->put(exec, ident, str);
5287 break;
5288 }
5289 ++iter;
5290 } while (iter != end);
5291
5292 if (iter == end)
5293 o->put(exec, ident, str);
5294 } else if (m_lexpr->isDotAccessorNode()) {
5295 const Identifier& ident = static_cast<DotAccessorNode*>(m_lexpr.get())->identifier();
5296 JSValue* v = static_cast<DotAccessorNode*>(m_lexpr.get())->base()->evaluate(exec);
5297 KJS_CHECKEXCEPTION
5298 JSObject* o = v->toObject(exec);
5299
5300 o->put(exec, ident, str);
5301 } else {
5302 ASSERT(m_lexpr->isBracketAccessorNode());
5303 JSValue* v = static_cast<BracketAccessorNode*>(m_lexpr.get())->base()->evaluate(exec);
5304 KJS_CHECKEXCEPTION
5305 JSValue* v2 = static_cast<BracketAccessorNode*>(m_lexpr.get())->subscript()->evaluate(exec);
5306 KJS_CHECKEXCEPTION
5307 JSObject* o = v->toObject(exec);
5308
5309 uint32_t i;
5310 if (v2->getUInt32(i))
5311 o->put(exec, i, str);
5312 o->put(exec, Identifier(v2->toString(exec)), str);
5313 }
5314
5315 KJS_CHECKEXCEPTION
5316
5317 exec->pushIteration();
5318 JSValue* statementValue = m_statement->execute(exec);
5319 exec->popIteration();
5320 if (statementValue)
5321 value = statementValue;
5322
5323 if (exec->dynamicGlobalObject()->timedOut())
5324 return exec->setInterruptedCompletion();
5325
5326 if (exec->completionType() != Normal) {
5327 if (exec->completionType() == Continue && m_labelStack.contains(exec->breakOrContinueTarget()))
5328 continue;
5329 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
5330 break;
5331 return statementValue;
5332 }
5333 }
5334
5335 return exec->setNormalCompletion(value);
5336}
5337
5338// ------------------------------ ContinueNode ---------------------------------
5339
5340// ECMA 12.7
5341RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5342{
5343 if (!generator.inContinueContext())
5344 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
5345
5346 JumpContext* targetContext = generator.jumpContextForContinue(m_ident);
5347
5348 if (!targetContext) {
5349 if (m_ident.isEmpty())
5350 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
5351 else
5352 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
5353 }
5354
5355 if (!targetContext->continueTarget)
5356 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
5357
5358 generator.emitJumpScopes(targetContext->continueTarget, targetContext->scopeDepth);
5359
5360 return dst;
5361}
5362
5363JSValue* ContinueNode::execute(OldInterpreterExecState* exec)
5364{
5365 if (m_ident.isEmpty() && !exec->inIteration())
5366 return setErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
5367 if (!m_ident.isEmpty() && !exec->seenLabels().contains(m_ident))
5368 return setErrorCompletion(exec, SyntaxError, "Label %s not found.", m_ident);
5369 return exec->setContinueCompletion(&m_ident);
5370}
5371
5372// ------------------------------ BreakNode ------------------------------------
5373
5374// ECMA 12.8
5375RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5376{
5377 if (!generator.inJumpContext())
5378 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
5379
5380 JumpContext* targetContext = generator.jumpContextForBreak(m_ident);
5381
5382 if (!targetContext) {
5383 if (m_ident.isEmpty())
5384 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
5385 else
5386 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
5387 }
5388
5389 ASSERT(targetContext->breakTarget);
5390
5391 generator.emitJumpScopes(targetContext->breakTarget, targetContext->scopeDepth);
5392
5393 return dst;
5394}
5395
5396JSValue* BreakNode::execute(OldInterpreterExecState* exec)
5397{
5398 if (m_ident.isEmpty() && !exec->inIteration() && !exec->inSwitch())
5399 return setErrorCompletion(exec, SyntaxError, "Invalid break statement.");
5400 if (!m_ident.isEmpty() && !exec->seenLabels().contains(m_ident))
5401 return setErrorCompletion(exec, SyntaxError, "Label %s not found.");
5402 return exec->setBreakCompletion(&m_ident);
5403}
5404
5405// ------------------------------ ReturnNode -----------------------------------
5406
5407RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5408{
5409 if (generator.codeType() != FunctionCode)
5410 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
5411
5412 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(generator.finalDestination(dst), jsUndefined());
5413 if (generator.scopeDepth()) {
5414 RefPtr<LabelID> l0 = generator.newLabel();
5415 generator.emitJumpScopes(l0.get(), 0);
5416 generator.emitLabel(l0.get());
5417 }
5418 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
5419 return generator.emitReturn(r0);
5420}
5421
5422void ReturnNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5423{
5424 if (m_value)
5425 nodeStack.append(m_value.get());
5426}
5427
5428// ECMA 12.9
5429JSValue* ReturnNode::execute(OldInterpreterExecState* exec)
5430{
5431 CodeType codeType = exec->codeType();
5432 if (codeType != FunctionCode)
5433 return setErrorCompletion(exec, SyntaxError, "Invalid return statement.");
5434
5435 if (!m_value)
5436 return exec->setReturnValueCompletion(jsUndefined());
5437
5438 JSValue* v = m_value->evaluate(exec);
5439 KJS_CHECKEXCEPTION
5440
5441 return exec->setReturnValueCompletion(v);
5442}
5443
5444// ------------------------------ WithNode -------------------------------------
5445
5446RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5447{
5448 RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
5449 generator.emitPushScope(scope.get());
5450 RegisterID* result = generator.emitNode(dst, m_statement.get());
5451 generator.emitPopScope();
5452 return result;
5453}
5454
5455void WithNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5456{
5457 // Can't optimize within statement because "with" introduces a dynamic scope.
5458 nodeStack.append(m_expr.get());
5459}
5460
5461// ECMA 12.10
5462JSValue* WithNode::execute(OldInterpreterExecState*)
5463{
5464 ASSERT_NOT_REACHED();
5465 return 0;
5466}
5467
5468// ------------------------------ CaseClauseNode -------------------------------
5469
5470void CaseClauseNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5471{
5472 if (m_expr)
5473 nodeStack.append(m_expr.get());
5474 statementListPushFIFO(m_children, nodeStack);
5475}
5476
5477// ECMA 12.11
5478JSValue* CaseClauseNode::evaluate(OldInterpreterExecState* exec)
5479{
5480 JSValue* v = m_expr->evaluate(exec);
5481 KJS_CHECKEXCEPTIONVALUE
5482
5483 return v;
5484}
5485
5486// ECMA 12.11
5487JSValue* CaseClauseNode::executeStatements(OldInterpreterExecState* exec)
5488{
5489 return statementListExecute(m_children, exec);
5490}
5491
5492// ------------------------------ ClauseListNode -------------------------------
5493
5494void ClauseListNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5495{
5496 if (m_next)
5497 nodeStack.append(m_next.get());
5498 nodeStack.append(m_clause.get());
5499}
5500
5501// ------------------------------ CaseBlockNode --------------------------------
5502
5503RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
5504{
5505 Vector<RefPtr<LabelID>, 8> labelVector;
5506
5507 // Setup jumps
5508 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
5509 RegisterID* clauseVal = generator.emitNode(list->getClause()->expr());
5510 generator.emitStrictEqual(clauseVal, clauseVal, switchExpression);
5511 labelVector.append(generator.newLabel());
5512 generator.emitJumpIfTrue(clauseVal, labelVector[labelVector.size() - 1].get());
5513 }
5514
5515 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
5516 RegisterID* clauseVal = generator.emitNode(list->getClause()->expr());
5517 generator.emitStrictEqual(clauseVal, clauseVal, switchExpression);
5518 labelVector.append(generator.newLabel());
5519 generator.emitJumpIfTrue(clauseVal, labelVector[labelVector.size() - 1].get());
5520 }
5521
5522 RefPtr<LabelID> defaultLabel;
5523 defaultLabel = generator.newLabel();
5524 generator.emitJump(defaultLabel.get());
5525
5526 RegisterID* result = 0;
5527
5528 size_t i = 0;
5529 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
5530 generator.emitLabel(labelVector[i++].get());
5531 result = statementListEmitCode(list->getClause()->children(), generator, dst);
5532 }
5533
5534 if (m_defaultClause) {
5535 generator.emitLabel(defaultLabel.get());
5536 result = statementListEmitCode(m_defaultClause->children(), generator, dst);
5537 }
5538
5539 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
5540 generator.emitLabel(labelVector[i++].get());
5541 result = statementListEmitCode(list->getClause()->children(), generator, dst);
5542 }
5543 if (!m_defaultClause)
5544 generator.emitLabel(defaultLabel.get());
5545
5546 ASSERT(i == labelVector.size());
5547
5548 return result;
5549}
5550
5551void CaseBlockNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5552{
5553 if (m_list2)
5554 nodeStack.append(m_list2.get());
5555 if (m_defaultClause)
5556 nodeStack.append(m_defaultClause.get());
5557 if (m_list1)
5558 nodeStack.append(m_list1.get());
5559}
5560
5561// ECMA 12.11
5562JSValue* CaseBlockNode::executeBlock(OldInterpreterExecState* exec, JSValue* input)
5563{
5564 ClauseListNode* a = m_list1.get();
5565 while (a) {
5566 CaseClauseNode* clause = a->getClause();
5567 a = a->getNext();
5568 JSValue* v = clause->evaluate(exec);
5569 KJS_CHECKEXCEPTION
5570 if (strictEqual(input, v)) {
5571 JSValue* res = clause->executeStatements(exec);
5572 if (exec->completionType() != Normal)
5573 return res;
5574 for (; a; a = a->getNext()) {
5575 JSValue* res = a->getClause()->executeStatements(exec);
5576 if (exec->completionType() != Normal)
5577 return res;
5578 }
5579 break;
5580 }
5581 }
5582
5583 ClauseListNode* b = m_list2.get();
5584 while (b) {
5585 CaseClauseNode* clause = b->getClause();
5586 b = b->getNext();
5587 JSValue* v = clause->evaluate(exec);
5588 KJS_CHECKEXCEPTION
5589 if (strictEqual(input, v)) {
5590 JSValue* res = clause->executeStatements(exec);
5591 if (exec->completionType() != Normal)
5592 return res;
5593 goto step18;
5594 }
5595 }
5596
5597 // default clause
5598 if (m_defaultClause) {
5599 JSValue* res = m_defaultClause->executeStatements(exec);
5600 if (exec->completionType() != Normal)
5601 return res;
5602 }
5603 b = m_list2.get();
5604step18:
5605 while (b) {
5606 CaseClauseNode* clause = b->getClause();
5607 JSValue* res = clause->executeStatements(exec);
5608 if (exec->completionType() != Normal)
5609 return res;
5610 b = b->getNext();
5611 }
5612
5613 // bail out on error
5614 KJS_CHECKEXCEPTION
5615
5616 return exec->setNormalCompletion();
5617}
5618
5619// ------------------------------ SwitchNode -----------------------------------
5620
5621RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5622{
5623 RefPtr<LabelID> breakTarget = generator.newLabel();
5624
5625 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
5626 generator.pushJumpContext(&m_labelStack, 0, breakTarget.get(), true);
5627 RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
5628 generator.popJumpContext();
5629
5630 generator.emitLabel(breakTarget.get());
5631
5632 return r1;
5633}
5634
5635void SwitchNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5636{
5637 nodeStack.append(m_block.get());
5638 nodeStack.append(m_expr.get());
5639}
5640
5641// ECMA 12.11
5642JSValue* SwitchNode::execute(OldInterpreterExecState* exec)
5643{
5644 JSValue* v = m_expr->evaluate(exec);
5645 KJS_CHECKEXCEPTION
5646
5647 exec->pushSwitch();
5648 JSValue* result = m_block->executeBlock(exec, v);
5649 exec->popSwitch();
5650
5651 if (exec->completionType() == Break && m_labelStack.contains(exec->breakOrContinueTarget()))
5652 exec->setCompletionType(Normal);
5653 return result;
5654}
5655
5656// ------------------------------ LabelNode ------------------------------------
5657RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5658{
5659 if (generator.jumpContextForBreak(m_label))
5660 return emitThrowError(generator, SyntaxError, "Duplicated label %s found.", m_label);
5661
5662 RefPtr<LabelID> l0 = generator.newLabel();
5663 m_labelStack.push(m_label);
5664 generator.pushJumpContext(&m_labelStack, 0, l0.get(), false);
5665
5666 RegisterID* r0 = generator.emitNode(dst, m_statement.get());
5667
5668 generator.popJumpContext();
5669 m_labelStack.pop();
5670
5671 generator.emitLabel(l0.get());
5672 return r0;
5673}
5674
5675void LabelNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5676{
5677 nodeStack.append(m_statement.get());
5678}
5679
5680// ECMA 12.12
5681JSValue* LabelNode::execute(OldInterpreterExecState* exec)
5682{
5683 if (!exec->seenLabels().push(m_label))
5684 return setErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", m_label);
5685 JSValue* result = m_statement->execute(exec);
5686 exec->seenLabels().pop();
5687
5688 if (exec->completionType() == Break && exec->breakOrContinueTarget() == m_label)
5689 exec->setCompletionType(Normal);
5690 return result;
5691}
5692
5693// ------------------------------ ThrowNode ------------------------------------
5694
5695RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5696{
5697 generator.emitThrow(generator.emitNode(dst, m_expr.get()));
5698 return dst;
5699}
5700
5701void ThrowNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5702{
5703 nodeStack.append(m_expr.get());
5704}
5705
5706// ECMA 12.13
5707JSValue* ThrowNode::execute(OldInterpreterExecState* exec)
5708{
5709 JSValue* v = m_expr->evaluate(exec);
5710 KJS_CHECKEXCEPTION
5711
5712 handleException(exec, v);
5713 return exec->setThrowCompletion(v);
5714}
5715
5716// ------------------------------ TryNode --------------------------------------
5717
5718RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
5719{
5720 RefPtr<LabelID> tryStartLabel = generator.newLabel();
5721 RefPtr<LabelID> tryEndLabel = generator.newLabel();
5722 RefPtr<LabelID> finallyStart;
5723 RefPtr<RegisterID> finallyReturnAddr;
5724 if (m_finallyBlock) {
5725 finallyStart = generator.newLabel();
5726 finallyReturnAddr = generator.newTemporary();
5727 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
5728 }
5729 generator.emitLabel(tryStartLabel.get());
5730 generator.emitNode(dst, m_tryBlock.get());
5731 generator.emitLabel(tryEndLabel.get());
5732
5733 if (m_catchBlock) {
5734 RefPtr<LabelID> handlerEndLabel = generator.newLabel();
5735 generator.emitJump(handlerEndLabel.get());
5736 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
5737 RefPtr<RegisterID> newScope = generator.emitNewObject(generator.newTemporary()); // scope must be protected until popped
5738 generator.emitPutById(newScope.get(), m_exceptionIdent, exceptionRegister.get());
5739 exceptionRegister = 0; // Release register used for temporaries
5740 generator.emitPushScope(newScope.get());
5741 generator.emitNode(dst, m_catchBlock.get());
5742 generator.emitPopScope();
5743 generator.emitLabel(handlerEndLabel.get());
5744 }
5745
5746 if (m_finallyBlock) {
5747 generator.popFinallyContext();
5748 // there may be important registers live at the time we jump
5749 // to a finally block (such as for a return or throw) so we
5750 // ref the highest register ever used as a conservative
5751 // approach to not clobbering anything important
5752 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
5753 RefPtr<LabelID> finallyEndLabel = generator.newLabel();
5754 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
5755 generator.emitJump(finallyEndLabel.get());
5756
5757 // Finally block for exception path
5758 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
5759 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
5760 generator.emitThrow(tempExceptionRegister.get());
5761
5762 // emit the finally block itself
5763 generator.emitLabel(finallyStart.get());
5764 generator.emitNode(dst, m_finallyBlock.get());
5765 generator.emitSubroutineReturn(finallyReturnAddr.get());
5766
5767 generator.emitLabel(finallyEndLabel.get());
5768 }
5769
5770 return dst;
5771}
5772
5773
5774void TryNode::optimizeVariableAccess(OldInterpreterExecState*, const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
5775{
5776 // Can't optimize within catchBlock because "catch" introduces a dynamic scope.
5777 if (m_finallyBlock)
5778 nodeStack.append(m_finallyBlock.get());
5779 nodeStack.append(m_tryBlock.get());
5780}
5781
5782// ECMA 12.14
5783JSValue* TryNode::execute(OldInterpreterExecState*)
5784{
5785 ASSERT_NOT_REACHED();
5786 return 0;
5787}
5788
5789// ------------------------------ FunctionBodyNode -----------------------------
5790
5791ScopeNode::ScopeNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
5792 : BlockNode(children)
5793 , m_sourceURL(parser().sourceURL())
5794 , m_sourceId(parser().sourceId())
5795 , m_usesEval(usesEval)
5796 , m_needsClosure(needsClosure)
5797{
5798 if (varStack)
5799 m_varStack = *varStack;
5800 if (funcStack)
5801 m_functionStack = *funcStack;
5802}
5803
5804// ------------------------------ ProgramNode -----------------------------
5805
5806ProgramNode::ProgramNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
5807 : ScopeNode(children, varStack, funcStack, usesEval, needsClosure)
5808{
5809}
5810
5811ProgramNode::~ProgramNode()
5812{
5813}
5814
5815ProgramNode* ProgramNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
5816{
5817 return new ProgramNode(children, varStack, funcStack, usesEval, needsClosure);
5818}
5819
5820// ------------------------------ EvalNode -----------------------------
5821
5822EvalNode::EvalNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
5823 : ScopeNode(children, varStack, funcStack, usesEval, needsClosure)
5824{
5825}
5826
5827EvalNode::~EvalNode()
5828{
5829}
5830
5831RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
5832{
5833 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
5834
5835 RefPtr<RegisterID> dstRegister = generator.newTemporary();
5836 generator.emitLoad(dstRegister.get(), jsUndefined());
5837 statementListEmitCode(m_children, generator, dstRegister.get());
5838
5839 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
5840 generator.emitEnd(dstRegister.get());
5841 return 0;
5842}
5843
5844void EvalNode::generateCode(ScopeChainNode* sc)
5845{
5846 ScopeChain scopeChain(sc);
5847 JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(scopeChain.bottom());
5848 ASSERT(globalObject->isGlobalObject());
5849
5850 m_code.set(new EvalCodeBlock(this, globalObject));
5851 SymbolTable symbolTable;
5852 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &symbolTable, m_code.get(), m_varStack, m_functionStack);
5853 generator.generate();
5854
5855 m_children.shrinkCapacity(0);
5856}
5857
5858EvalNode* EvalNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
5859{
5860 return new EvalNode(children, varStack, funcStack, usesEval, needsClosure);
5861}
5862
5863// ------------------------------ FunctionBodyNode -----------------------------
5864
5865FunctionBodyNode::FunctionBodyNode(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
5866 : ScopeNode(children, varStack, funcStack, usesEval, needsClosure)
5867{
5868}
5869
5870FunctionBodyNode::~FunctionBodyNode()
5871{
5872}
5873
5874void FunctionBodyNode::mark()
5875{
5876 if (m_code)
5877 m_code->mark();
5878}
5879
5880FunctionBodyNode* FunctionBodyNode::create(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure)
5881{
5882 return new FunctionBodyNode(children, varStack, funcStack, usesEval, needsClosure);
5883}
5884
5885void FunctionBodyNode::generateCode(ScopeChainNode* sc)
5886{
5887 m_code.set(new CodeBlock(this));
5888
5889 ScopeChain scopeChain(sc);
5890 JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(scopeChain.bottom());
5891 ASSERT(globalObject->isGlobalObject());
5892
5893 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get(), m_varStack, m_functionStack, m_parameters);
5894 generator.generate();
5895
5896 m_children.shrinkCapacity(0);
5897}
5898
5899RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
5900{
5901 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
5902 statementListEmitCode(m_children, generator);
5903 if (!m_children.size() || !m_children.last()->isReturnNode()) {
5904 RegisterID* r0 = generator.emitLoad(generator.newTemporary(), jsUndefined());
5905 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
5906 generator.emitReturn(r0);
5907 }
5908 return 0;
5909}
5910
5911RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
5912{
5913 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
5914
5915 RefPtr<RegisterID> dstRegister = generator.newTemporary();
5916 generator.emitLoad(dstRegister.get(), jsUndefined());
5917 statementListEmitCode(m_children, generator, dstRegister.get());
5918
5919 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
5920 generator.emitEnd(dstRegister.get());
5921 return 0;
5922}
5923
5924void ProgramNode::generateCode(ScopeChainNode* sc, bool canCreateGlobals)
5925{
5926 ScopeChain scopeChain(sc);
5927 JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(scopeChain.bottom());
5928 ASSERT(globalObject->isGlobalObject());
5929
5930 m_code.set(new ProgramCodeBlock(this, globalObject));
5931
5932 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack, canCreateGlobals);
5933 generator.generate();
5934
5935 m_children.shrinkCapacity(0);
5936}
5937
5938void ProgramNode::initializeSymbolTable(OldInterpreterExecState* exec)
5939{
5940 // If a previous script defined a symbol with the same name as one of our
5941 // symbols, to avoid breaking previously optimized nodes, we need to reuse
5942 // the symbol's existing storage index. So, we can't be as efficient as
5943 // FunctionBodyNode::initializeSymbolTable, which knows that no bindings
5944 // have yet been made.
5945
5946 JSVariableObject* variableObject = exec->variableObject();
5947 SymbolTable& symbolTable = variableObject->symbolTable();
5948
5949 size_t localStorageIndex = symbolTable.size();
5950 size_t size;
5951
5952 // Order must match the order in processDeclarations.
5953
5954 size = m_functionStack.size();
5955 m_functionIndexes.resize(size);
5956 for (size_t i = 0; i < size; ++i) {
5957 UString::Rep* rep = m_functionStack[i]->m_ident.ustring().rep();
5958 pair<SymbolTable::iterator, bool> result = symbolTable.add(rep, localStorageIndex);
5959 m_functionIndexes[i] = result.first->second.getIndex();
5960 if (result.second)
5961 ++localStorageIndex;
5962 }
5963
5964 size = m_varStack.size();
5965 m_varIndexes.resize(size);
5966 for (size_t i = 0; i < size; ++i) {
5967 const Identifier& ident = m_varStack[i].first;
5968 if (variableObject->hasProperty(exec, ident)) {
5969 m_varIndexes[i] = missingSymbolMarker(); // Signal not to initialize this declaration.
5970 continue;
5971 }
5972
5973 UString::Rep* rep = ident.ustring().rep();
5974 pair<SymbolTable::iterator, bool> result = symbolTable.add(rep, localStorageIndex);
5975 if (!result.second) {
5976 m_varIndexes[i] = missingSymbolMarker(); // Signal not to initialize this declaration.
5977 continue;
5978 }
5979
5980 m_varIndexes[i] = result.first->second.getIndex();
5981 ++localStorageIndex;
5982 }
5983}
5984
5985void ScopeNode::optimizeVariableAccess(OldInterpreterExecState* exec)
5986{
5987 NodeStack nodeStack;
5988 Node* node = statementListInitializeVariableAccessStack(m_children, nodeStack);
5989 if (!node)
5990 return;
5991
5992 const SymbolTable& symbolTable = exec->variableObject()->symbolTable();
5993 ASSERT_NOT_REACHED();
5994 const LocalStorage localStorage;
5995 while (true) {
5996 node->optimizeVariableAccess(exec, symbolTable, localStorage, nodeStack);
5997
5998 size_t size = nodeStack.size();
5999 if (!size)
6000 break;
6001 --size;
6002 node = nodeStack[size];
6003 nodeStack.shrink(size);
6004 }
6005}
6006
6007static void gccIsCrazy() KJS_FAST_CALL;
6008static void gccIsCrazy()
6009{
6010}
6011
6012void ProgramNode::processDeclarations(OldInterpreterExecState* exec)
6013{
6014 // If you remove this call, some SunSpider tests, including
6015 // bitops-nsieve-bits.js, will regress substantially on Mac, due to a ~40%
6016 // increase in L2 cache misses. FIXME: <rdar://problem/5657439> WTF?
6017 gccIsCrazy();
6018
6019 initializeSymbolTable(exec);
6020
6021 ASSERT_NOT_REACHED();
6022 LocalStorage localStorage;
6023
6024 // We can't just resize localStorage here because that would temporarily
6025 // leave uninitialized entries, which would crash GC during the mark phase.
6026 localStorage.reserveCapacity(localStorage.size() + m_varStack.size() + m_functionStack.size());
6027
6028 int minAttributes = DontDelete;
6029
6030 // In order for our localStorage indexes to be correct, we must match the
6031 // order of addition in initializeSymbolTable().
6032
6033 for (size_t i = 0, size = m_functionStack.size(); i < size; ++i) {
6034 FuncDeclNode* node = m_functionStack[i];
6035 LocalStorageEntry entry = LocalStorageEntry(node->makeFunction(exec, exec->scopeChain().node()), minAttributes);
6036 size_t index = m_functionIndexes[i];
6037
6038 if (index == localStorage.size())
6039 localStorage.uncheckedAppend(entry);
6040 else {
6041 ASSERT(index < localStorage.size());
6042 localStorage[index] = entry;
6043 }
6044 }
6045
6046 for (size_t i = 0, size = m_varStack.size(); i < size; ++i) {
6047 int index = m_varIndexes[i];
6048 if (index == missingSymbolMarker())
6049 continue;
6050
6051 int attributes = minAttributes;
6052 if (m_varStack[i].second & DeclarationStacks::IsConstant)
6053 attributes |= ReadOnly;
6054 LocalStorageEntry entry = LocalStorageEntry(jsUndefined(), attributes);
6055
6056 ASSERT(static_cast<unsigned>(index) == localStorage.size());
6057 localStorage.uncheckedAppend(entry);
6058 }
6059
6060 optimizeVariableAccess(exec);
6061}
6062
6063void EvalNode::processDeclarations(OldInterpreterExecState* exec)
6064{
6065 // We could optimize access to pre-existing symbols here, but SunSpider
6066 // reports that to be a net loss.
6067
6068 size_t i;
6069 size_t size;
6070
6071 JSVariableObject* variableObject = exec->variableObject();
6072
6073 for (i = 0, size = m_varStack.size(); i < size; ++i) {
6074 Identifier& ident = m_varStack[i].first;
6075 if (variableObject->hasProperty(exec, ident))
6076 continue;
6077 int attributes = 0;
6078 if (m_varStack[i].second & DeclarationStacks::IsConstant)
6079 attributes = ReadOnly;
6080 variableObject->putWithAttributes(exec, ident, jsUndefined(), attributes);
6081 }
6082
6083 for (i = 0, size = m_functionStack.size(); i < size; ++i) {
6084 FuncDeclNode* funcDecl = m_functionStack[i];
6085 variableObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, exec->scopeChain().node()), 0);
6086 }
6087}
6088
6089UString FunctionBodyNode::paramString() const
6090{
6091 UString s("");
6092 size_t count = m_parameters.size();
6093 for (size_t pos = 0; pos < count; ++pos) {
6094 if (!s.isEmpty())
6095 s += ", ";
6096 s += m_parameters[pos].ustring();
6097 }
6098
6099 return s;
6100}
6101
6102JSValue* ProgramNode::execute(OldInterpreterExecState* exec)
6103{
6104 processDeclarations(exec);
6105 return ScopeNode::execute(exec);
6106}
6107
6108JSValue* EvalNode::execute(OldInterpreterExecState* exec)
6109{
6110 processDeclarations(exec);
6111 return ScopeNode::execute(exec);
6112}
6113
6114// ------------------------------ FunctionBodyNodeWithDebuggerHooks ---------------------------------
6115
6116FunctionBodyNodeWithDebuggerHooks::FunctionBodyNodeWithDebuggerHooks(SourceElements* children, DeclarationStacks::VarStack* varStack, DeclarationStacks::FunctionStack* funcStack, bool usesEval, bool needsClosure)
6117 : FunctionBodyNode(children, varStack, funcStack, usesEval, needsClosure)
6118{
6119}
6120
6121JSValue* FunctionBodyNodeWithDebuggerHooks::execute(OldInterpreterExecState* exec)
6122{
6123 JSValue* result = FunctionBodyNode::execute(exec);
6124
6125 return result;
6126}
6127
6128// ------------------------------ FuncDeclNode ---------------------------------
6129
6130void FuncDeclNode::addParams()
6131{
6132 for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
6133 m_body->parameters().append(p->ident());
6134}
6135
6136FunctionImp* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
6137{
6138 FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), scopeChain);
6139
6140 JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
6141 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
6142 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
6143 func->putDirect(exec->propertyNames().length, jsNumber(m_body->parameters().size()), ReadOnly | DontDelete | DontEnum);
6144 return func;
6145}
6146
6147RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
6148{
6149 return dst;
6150}
6151
6152JSValue* FuncDeclNode::execute(OldInterpreterExecState* exec)
6153{
6154 return exec->setNormalCompletion();
6155}
6156
6157// ------------------------------ FuncExprNode ---------------------------------
6158
6159RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
6160{
6161 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
6162}
6163
6164FunctionImp* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
6165{
6166 FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), scopeChain);
6167 JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
6168 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
6169 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
6170
6171 /*
6172 The Identifier in a FunctionExpression can be referenced from inside
6173 the FunctionExpression's FunctionBody to allow the function to call
6174 itself recursively. However, unlike in a FunctionDeclaration, the
6175 Identifier in a FunctionExpression cannot be referenced from and
6176 does not affect the scope enclosing the FunctionExpression.
6177 */
6178
6179 if (!m_ident.isNull()) {
6180 JSObject* functionScopeObject = new JSObject;
6181 functionScopeObject->putDirect(m_ident, func, ReadOnly | DontDelete);
6182 func->scope().push(functionScopeObject);
6183 }
6184
6185 return func;
6186}
6187
6188// ECMA 13
6189void FuncExprNode::addParams()
6190{
6191 for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
6192 m_body->parameters().append(p->ident());
6193}
6194
6195JSValue* FuncExprNode::evaluate(OldInterpreterExecState* exec)
6196{
6197 ASSERT_NOT_REACHED();
6198
6199 bool named = !m_ident.isNull();
6200 JSObject* functionScopeObject = 0;
6201
6202 if (named) {
6203 // named FunctionExpressions can recursively call themselves,
6204 // but they won't register with the current scope chain and should
6205 // be contained as single property in an anonymous object.
6206 functionScopeObject = new JSObject;
6207 exec->pushScope(functionScopeObject);
6208 }
6209
6210 FunctionImp* func = new FunctionImp(exec, m_ident, m_body.get(), exec->scopeChain().node());
6211 JSObject* proto = exec->lexicalGlobalObject()->objectConstructor()->construct(exec, exec->emptyList());
6212 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
6213 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
6214
6215 if (named) {
6216 functionScopeObject->putDirect(m_ident, func, ReadOnly | (exec->codeType() == EvalCode ? 0 : DontDelete));
6217 exec->popScope();
6218 }
6219
6220 return func;
6221}
6222
6223} // namespace KJS
Note: See TracBrowser for help on using the repository browser.