915fca8e17b501556fe25ee7ac4c20ae8935920d
[WebKit-https.git] / JavaScriptCore / VM / Machine.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "Machine.h"
32
33 #include "CodeBlock.h"
34 #include "DebuggerCallFrame.h"
35 #include "ExceptionHelpers.h"
36 #include "ExecState.h"
37 #include "GlobalEvalFunction.h"
38 #include "JSActivation.h"
39 #include "JSArray.h"
40 #include "JSFunction.h"
41 #include "JSNotAnObject.h"
42 #include "JSPropertyNameIterator.h"
43 #include "JSStaticScopeObject.h"
44 #include "JSString.h"
45 #include "ObjectPrototype.h"
46 #include "Parser.h"
47 #include "Profiler.h"
48 #include "RegExpObject.h"
49 #include "RegExpPrototype.h"
50 #include "Register.h"
51 #include "collector.h"
52 #include "debugger.h"
53 #include "operations.h"
54 #include "SamplingTool.h"
55 #include <stdio.h>
56
57 #if HAVE(SYS_TIME_H)
58 #include <sys/time.h>
59 #endif
60
61 #if PLATFORM(WIN_OS)
62 #include <windows.h>
63 #endif
64
65 #if PLATFORM(QT)
66 #include <QDateTime>
67 #endif
68
69 using namespace std;
70
71 namespace KJS {
72
73 // Default number of ticks before a timeout check should be done.
74 static const int initialTickCountThreshold = 255;
75
76 // Preferred number of milliseconds between each timeout check
77 static const int preferredScriptCheckTimeInterval = 1000;
78
79 #if HAVE(COMPUTED_GOTO)
80 static void* op_throw_end_indirect;
81 static void* op_call_indirect;
82 #endif
83
84 // Returns the depth of the scope chain within a given call frame.
85 static int depth(ScopeChain& sc)
86 {
87     int scopeDepth = 0;
88     ScopeChainIterator iter = sc.begin();
89     ScopeChainIterator end = sc.end();
90     while (!(*iter)->isActivationObject()) {
91         ++iter;
92         if (iter == end)
93             break;
94         ++scopeDepth;
95     }
96     return scopeDepth;
97 }
98
99 static bool fastIsNumber(JSValue* value, double& arg) {
100     if (JSImmediate::isNumber(value))
101         arg = JSImmediate::getTruncatedInt32(value);
102     else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
103         arg = static_cast<JSNumberCell*>(value)->value();
104     else
105         return false;
106     return true;
107 }
108
109 static bool fastToInt32(JSValue* value, int32_t& arg) {
110     if (JSImmediate::isNumber(value))
111         arg = JSImmediate::getTruncatedInt32(value);
112     else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
113         arg = static_cast<JSNumberCell*>(value)->fastToInt32();
114     else
115         return false;
116     return true;
117 }
118
119 static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg) {
120     if (JSImmediate::isNumber(value)) {
121         if (JSImmediate::getTruncatedUInt32(value, arg))
122             return true;
123         bool scratch;
124         arg = JSValue::toUInt32SlowCase(JSImmediate::getTruncatedInt32(value), scratch);
125         return true;
126     } else if (Heap::fastIsNumber(static_cast<JSCell*>(value)))
127         arg = static_cast<JSNumberCell*>(value)->fastToUInt32();
128     else
129         return false;
130     return true;
131 }
132
133 static inline bool jsLess(ExecState* exec, JSValue* v1, JSValue* v2)
134 {
135     if (JSImmediate::areBothImmediateNumbers(v1, v2))
136         return JSImmediate::getTruncatedInt32(v1) < JSImmediate::getTruncatedInt32(v2);
137
138     double n1;
139     double n2;
140     if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
141         return n1 < n2;
142
143     JSValue* p1;
144     JSValue* p2;
145     bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
146     bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
147
148     if (wasNotString1 | wasNotString2)
149         return n1 < n2;
150
151     return static_cast<const JSString*>(p1)->value() < static_cast<const JSString*>(p2)->value();
152 }
153
154 static inline bool jsLessEq(ExecState* exec, JSValue* v1, JSValue* v2)
155 {
156     if (JSImmediate::areBothImmediateNumbers(v1, v2))
157         return JSImmediate::getTruncatedInt32(v1) <= JSImmediate::getTruncatedInt32(v2);
158
159     double n1;
160     double n2;
161     if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
162         return n1 <= n2;
163
164     JSValue* p1;
165     JSValue* p2;
166     bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
167     bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
168
169     if (wasNotString1 | wasNotString2)
170         return n1 <= n2;
171
172     return !(static_cast<const JSString*>(p2)->value() < static_cast<const JSString*>(p1)->value());
173 }
174
175 static JSValue* jsAddSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
176 {
177     // exception for the Date exception in defaultValue()
178     JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
179     JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
180
181     if (p1->isString() || p2->isString()) {
182         UString value = p1->toString(exec) + p2->toString(exec);
183         if (value.isNull())
184             return throwOutOfMemoryError(exec);
185         return jsString(exec, value);
186     }
187
188     return jsNumber(exec, p1->toNumber(exec) + p2->toNumber(exec));
189 }
190
191 // Fast-path choices here are based on frequency data from SunSpider:
192 //    <times> Add case: <t1> <t2>
193 //    ---------------------------
194 //    5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
195 //    247412  Add case: 5 5
196 //    20900   Add case: 5 6
197 //    13962   Add case: 5 3
198 //    4000    Add case: 3 5
199
200 static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
201 {
202     double left;
203     double right;
204     
205     if (fastIsNumber(v1, left) && fastIsNumber(v2, right))
206         return jsNumber(exec, left + right);
207     
208     JSType t1 = v1->type();
209     JSType t2 = v2->type();
210     const unsigned bothTypes = (t1 << 3) | t2;
211     ASSERT(bothTypes != ((NumberType << 3) | NumberType));
212     if (bothTypes == ((StringType << 3) | StringType)) {
213         UString value = static_cast<JSString*>(v1)->value() + static_cast<JSString*>(v2)->value();
214         if (value.isNull())
215             return throwOutOfMemoryError(exec);
216         return jsString(exec, value);
217     }
218
219     // All other cases are pretty uncommon
220     return jsAddSlowCase(exec, v1, v2);
221 }
222
223 static JSValue* jsTypeStringForValue(ExecState* exec, JSValue* v)
224 {
225     switch (v->type()) {
226         case UndefinedType:
227             return jsString(exec, "undefined");
228         case NullType:
229             return jsString(exec, "object");
230         case BooleanType:
231             return jsString(exec, "boolean");
232         case NumberType:
233             return jsString(exec, "number");
234         case StringType:
235             return jsString(exec, "string");
236         default:
237             if (v->isObject()) {
238                 // Return "undefined" for objects that should be treated
239                 // as null when doing comparisons.
240                 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
241                     return jsString(exec, "undefined");
242                 CallData callData;
243                 if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
244                     return jsString(exec, "function");
245             }
246
247             return jsString(exec, "object");
248     }
249 }
250
251 static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
252 {
253     int dst = (vPC + 1)->u.operand;
254     int property = (vPC + 2)->u.operand;
255
256     ScopeChainIterator iter = scopeChain->begin();
257     ScopeChainIterator end = scopeChain->end();
258     ASSERT(iter != end);
259
260     Identifier& ident = codeBlock->identifiers[property];
261     do {
262         JSObject* o = *iter;
263         PropertySlot slot(o);
264         if (o->getPropertySlot(exec, ident, slot)) {
265             JSValue* result = slot.getValue(exec, ident);
266             exceptionValue = exec->exception();
267             if (exceptionValue)
268                 return false;
269             r[dst] = result;
270             return true;
271         }
272     } while (++iter != end);
273     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
274     return false;
275 }
276
277 static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
278 {
279     int dst = (vPC + 1)->u.operand;
280     int property = (vPC + 2)->u.operand;
281     int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain;
282
283     ScopeChainIterator iter = scopeChain->begin();
284     ScopeChainIterator end = scopeChain->end();
285     ASSERT(iter != end);
286     while (skip--) {
287         ++iter;
288         ASSERT(iter != end);
289     }
290     Identifier& ident = codeBlock->identifiers[property];
291     do {
292         JSObject* o = *iter;
293         PropertySlot slot(o);
294         if (o->getPropertySlot(exec, ident, slot)) {
295             JSValue* result = slot.getValue(exec, ident);
296             exceptionValue = exec->exception();
297             if (exceptionValue)
298                 return false;
299             r[dst] = result;
300             return true;
301         }
302     } while (++iter != end);
303     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
304     return false;
305 }
306
307 static void NEVER_INLINE resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
308 {
309     int dst = (vPC + 1)->u.operand;
310     int property = (vPC + 2)->u.operand;
311
312     ScopeChainIterator iter = scopeChain->begin();
313     ScopeChainIterator next = iter;
314     ++next;
315     ScopeChainIterator end = scopeChain->end();
316     ASSERT(iter != end);
317
318     PropertySlot slot;
319     Identifier& ident = codeBlock->identifiers[property];
320     JSObject* base;
321     while (true) {
322         base = *iter;
323         if (next == end || base->getPropertySlot(exec, ident, slot)) {
324             r[dst] = base;
325             return;
326         }
327         iter = next;
328         ++next;
329     }
330 }
331
332 static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
333 {
334     int baseDst = (vPC + 1)->u.operand;
335     int propDst = (vPC + 2)->u.operand;
336     int property = (vPC + 3)->u.operand;
337
338     ScopeChainIterator iter = scopeChain->begin();
339     ScopeChainIterator end = scopeChain->end();
340
341     // FIXME: add scopeDepthIsZero optimization
342
343     ASSERT(iter != end);
344
345     Identifier& ident = codeBlock->identifiers[property];
346     JSObject* base;
347     do {
348         base = *iter;
349         PropertySlot slot(base);
350         if (base->getPropertySlot(exec, ident, slot)) {
351             JSValue* result = slot.getValue(exec, ident);
352             exceptionValue = exec->exception();
353             if (exceptionValue)
354                 return false;
355             r[propDst] = result;
356             r[baseDst] = base;
357             return true;
358         }
359         ++iter;
360     } while (iter != end);
361
362     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
363     return false;
364 }
365
366 static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
367 {
368     int baseDst = (vPC + 1)->u.operand;
369     int funcDst = (vPC + 2)->u.operand;
370     int property = (vPC + 3)->u.operand;
371
372     ScopeChainIterator iter = scopeChain->begin();
373     ScopeChainIterator end = scopeChain->end();
374
375     // FIXME: add scopeDepthIsZero optimization
376
377     ASSERT(iter != end);
378
379     Identifier& ident = codeBlock->identifiers[property];
380     JSObject* base;
381     do {
382         base = *iter;
383         PropertySlot slot(base);
384         if (base->getPropertySlot(exec, ident, slot)) {            
385             // ECMA 11.2.3 says that if we hit an activation the this value should be null.
386             // However, section 10.2.3 says that in the case where the value provided
387             // by the caller is null, the global object should be used. It also says
388             // that the section does not apply to internal functions, but for simplicity
389             // of implementation we use the global object anyway here. This guarantees
390             // that in host objects you always get a valid object for this.
391             // We also handle wrapper substitution for the global object at the same time.
392             JSObject* thisObj = base->toThisObject(exec);
393             JSValue* result = slot.getValue(exec, ident);
394             exceptionValue = exec->exception();
395             if (exceptionValue)
396                 return false;
397
398             r[baseDst] = thisObj;
399             r[funcDst] = result;
400             return true;
401         }
402         ++iter;
403     } while (iter != end);
404
405     exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
406     return false;
407 }
408
409 ALWAYS_INLINE void Machine::initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, Register* r, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function)
410 {
411     callFrame[RegisterFile::CallerCodeBlock] = codeBlock;
412     callFrame[RegisterFile::ReturnVPC] = vPC + 1;
413     callFrame[RegisterFile::CallerScopeChain] = scopeChain;
414     callFrame[RegisterFile::CallerRegisters] = r;
415     callFrame[RegisterFile::ReturnValueRegister] = returnValueRegister;
416     callFrame[RegisterFile::ArgumentStartRegister] = argv; // original argument vector (for the sake of the "arguments" object)
417     callFrame[RegisterFile::ArgumentCount] = argc; // original argument count (for the sake of the "arguments" object)
418     callFrame[RegisterFile::CalledAsConstructor] = calledAsConstructor;
419     callFrame[RegisterFile::Callee] = function;
420     callFrame[RegisterFile::OptionalCalleeActivation] = nullJSValue;
421 }
422
423 ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register* registerBase, Register* r, int argv, int argc, JSValue*& exceptionValue)
424 {
425     size_t registerOffset = argv + newCodeBlock->numLocals;
426     size_t size = r - registerBase + registerOffset + newCodeBlock->numConstants + newCodeBlock->numTemporaries;
427
428     if (argc == newCodeBlock->numParameters) { // correct number of arguments
429         if (!registerFile->grow(size)) {
430             exceptionValue = createStackOverflowError(exec);
431             return r;
432         }
433         r += registerOffset;
434     } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
435         if (!registerFile->grow(size)) {
436             exceptionValue = createStackOverflowError(exec);
437             return r;
438         }
439         r += registerOffset;
440
441         int omittedArgCount = newCodeBlock->numParameters - argc;
442         Register* endOfParams = r - newCodeBlock->numVars;
443         for (Register* it = endOfParams - omittedArgCount; it != endOfParams; ++it)
444             (*it) = jsUndefined();
445     } else { // too many arguments -- copy return info and expected arguments, leaving the extra arguments behind
446         int shift = argc + RegisterFile::CallFrameHeaderSize;
447         registerOffset += shift;
448         size += shift;
449
450         if (!registerFile->grow(size)) {
451             exceptionValue = createStackOverflowError(exec);
452             return r;
453         }
454         r += registerOffset;
455
456         Register* it = r - newCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize - shift;
457         Register* end = it + RegisterFile::CallFrameHeaderSize + newCodeBlock->numParameters;
458         for ( ; it != end; ++it)
459             *(it + shift) = *it;
460     }
461     
462     // initialize local variable slots
463     for (Register* it = r - newCodeBlock->numVars; it != r; ++it)
464         (*it) = jsUndefined();
465
466
467     for (size_t i = 0; i < newCodeBlock->constantRegisters.size(); ++i)
468         r[i] = newCodeBlock->constantRegisters[i];
469
470     return r;
471 }
472
473 ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register* r)
474 {
475     if (newCodeBlock->needsFullScopeChain) {
476         JSActivation* activation = new (exec) JSActivation(functionBodyNode, r);
477         r[RegisterFile::OptionalCalleeActivation - RegisterFile::CallFrameHeaderSize - newCodeBlock->numLocals] = activation;
478
479         return callDataScopeChain->copy()->push(activation);
480     }
481
482     return callDataScopeChain;
483 }
484
485 static NEVER_INLINE bool isNotObject(ExecState* exec, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exceptionData)
486 {
487     if (value->isObject())
488         return false;
489     exceptionData = createInvalidParamError(exec, forInstanceOf ? "instanceof" : "in" , value, vPC, codeBlock);
490     return true;
491 }
492
493 NEVER_INLINE JSValue* Machine::callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
494 {
495     if (argc < 2)
496         return jsUndefined();
497
498     JSValue* program = r[argv + 1].jsValue(exec);
499
500     if (!program->isString())
501         return program;
502
503     Profiler** profiler = Profiler::enabledProfilerReference();
504     if (*profiler)
505         (*profiler)->willExecute(exec, scopeChain->globalObject()->evalFunction());
506
507     int sourceId;
508     int errLine;
509     UString errMsg;
510     RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(static_cast<JSString*>(program)->value()), &sourceId, &errLine, &errMsg);
511
512     if (!evalNode) {
513         exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
514         if (*profiler)
515             (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
516         return 0;
517     }
518
519     JSValue* result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - registerFile->base() + argv + argc, scopeChain, &exceptionValue);
520
521     if (*profiler)
522         (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
523
524     return result;
525 }
526
527 Machine::Machine()
528     : m_sampler(0)
529     , m_reentryDepth(0)
530     , m_timeoutTime(0)
531     , m_timeAtLastCheckTimeout(0)
532     , m_timeExecuting(0)
533     , m_timeoutCheckCount(0)
534     , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
535 {
536     privateExecute(InitializeAndReturn);
537     
538     // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
539     void* storage = fastMalloc(sizeof(CollectorBlock));
540
541     JSArray* jsArray = new (storage) JSArray(jsNull(), 0);
542     m_jsArrayVptr = jsArray->vptr();
543     static_cast<JSCell*>(jsArray)->~JSCell();
544
545     JSString* jsString = new (storage) JSString("");
546     m_jsStringVptr = jsString->vptr();
547     static_cast<JSCell*>(jsString)->~JSCell();
548     
549     fastFree(storage);
550 }
551
552 #ifndef NDEBUG
553
554 void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
555 {
556     ScopeChain sc(scopeChain);
557     JSGlobalObject* globalObject = sc.globalObject();
558     codeBlock->dump(globalObject->globalExec());
559     dumpRegisters(codeBlock, registerFile, r);
560 }
561
562 void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFile, const Register* r)
563 {
564     printf("Register frame: \n\n");
565     printf("----------------------------------------------------\n");
566     printf("            use            |   address  |   value   \n");
567     printf("----------------------------------------------------\n");
568
569     const Register* it;
570     const Register* end;
571
572     if (codeBlock->codeType == GlobalCode) {
573         it = registerFile->lastGlobal();
574         end = it + registerFile->numGlobals();
575         while (it != end) {
576             printf("[global var]               | %10p | %10p \n", it, (*it).v());
577             ++it;
578         }
579         printf("----------------------------------------------------\n");
580     }
581     
582     it = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
583     printf("[CallerCodeBlock]          | %10p | %10p \n", it, (*it).v()); ++it;
584     printf("[ReturnVPC]                | %10p | %10p \n", it, (*it).v()); ++it;
585     printf("[CallerScopeChain]         | %10p | %10p \n", it, (*it).v()); ++it;
586     printf("[CallerRegisterOffset]     | %10p | %10p \n", it, (*it).v()); ++it;
587     printf("[ReturnValueRegister]      | %10p | %10p \n", it, (*it).v()); ++it;
588     printf("[ArgumentStartRegister]    | %10p | %10p \n", it, (*it).v()); ++it;
589     printf("[ArgumentCount]            | %10p | %10p \n", it, (*it).v()); ++it;
590     printf("[CalledAsConstructor]      | %10p | %10p \n", it, (*it).v()); ++it;
591     printf("[Callee]                   | %10p | %10p \n", it, (*it).v()); ++it;
592     printf("[OptionalCalleeActivation] | %10p | %10p \n", it, (*it).v()); ++it;
593     printf("----------------------------------------------------\n");
594
595     printf("[this]                     | %10p | %10p \n", it, (*it).v()); ++it;
596     end = it + max(codeBlock->numParameters - 1, 0); // - 1 to skip "this"
597     if (it != end) {
598         do {
599             printf("[param]                    | %10p | %10p \n", it, (*it).v());
600             ++it;
601         } while (it != end);
602     }
603     printf("----------------------------------------------------\n");
604
605     if (codeBlock->codeType != GlobalCode) {
606         end = it + codeBlock->numVars;
607         if (it != end) {
608             do {
609                 printf("[var]                      | %10p | %10p \n", it, (*it).v());
610                 ++it;
611             } while (it != end);
612         printf("----------------------------------------------------\n");
613         }
614     }
615
616     end = it + codeBlock->numTemporaries;
617     if (it != end) {
618         do {
619             printf("[temp]                     | %10p | %10p \n", it, (*it).v());
620             ++it;
621         } while (it != end);
622     }
623 }
624
625 #endif
626
627 #if !defined(NDEBUG) || HAVE(SAMPLING_TOOL)
628
629 bool Machine::isOpcode(Opcode opcode)
630 {
631 #if HAVE(COMPUTED_GOTO)
632     return opcode != HashTraits<Opcode>::emptyValue()
633         && !HashTraits<Opcode>::isDeletedValue(opcode)
634         && m_opcodeIDTable.contains(opcode);
635 #else
636     return opcode >= 0 && opcode <= op_end;
637 #endif
638 }
639
640 #endif
641
642 NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r)
643 {
644     CodeBlock* oldCodeBlock = codeBlock;
645     Register* callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
646
647     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
648         DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
649         if (callFrame[RegisterFile::Callee].jsValue(exec))
650             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
651         else
652             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
653     }
654
655     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
656         if (callFrame[RegisterFile::Callee].jsValue(exec))
657             profiler->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
658         else
659             profiler->didExecute(exec, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo());
660     }
661
662     if (oldCodeBlock->needsFullScopeChain)
663         scopeChain->deref();
664
665     // If this call frame created an activation, tear it off.
666     if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
667         ASSERT(activation->isActivationObject());
668         activation->copyRegisters();
669     }
670     
671     codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
672     if (!codeBlock)
673         return false;
674
675     scopeChain = callFrame[RegisterFile::CallerScopeChain].scopeChain();
676     r = callFrame[RegisterFile::CallerRegisters].r();
677     exec->m_callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
678     vPC = callFrame[RegisterFile::ReturnVPC].vPC();
679
680     return true;
681 }
682
683 NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue*& exceptionValue, const Instruction* vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r, bool explicitThrow)
684 {
685     // Set up the exception object
686
687     if (exceptionValue->isObject()) {
688         JSObject* exception = static_cast<JSObject*>(exceptionValue);
689         if (exception->isNotAnObjectErrorStub()) {
690             exception = createNotAnObjectError(exec, static_cast<JSNotAnObjectErrorStub*>(exception), vPC, codeBlock);
691             exceptionValue = exception;
692         } else {
693             if (!exception->hasProperty(exec, Identifier(exec, "line")) && 
694                 !exception->hasProperty(exec, Identifier(exec, "sourceId")) && 
695                 !exception->hasProperty(exec, Identifier(exec, "sourceURL")) && 
696                 !exception->hasProperty(exec, Identifier(exec, expressionBeginOffsetPropertyName)) && 
697                 !exception->hasProperty(exec, Identifier(exec, expressionCaretOffsetPropertyName)) && 
698                 !exception->hasProperty(exec, Identifier(exec, expressionEndOffsetPropertyName))) {
699                 if (explicitThrow) {
700                     int startOffset = 0;
701                     int endOffset = 0;
702                     int divotPoint = 0;
703                     int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset);
704                     exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, line), ReadOnly | DontDelete);
705                     
706                     // We only hit this path for error messages and throw statements, which don't have a specific failure position
707                     // So we just give the full range of the error/throw statement.
708                     exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
709                     exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
710                 } else
711                     exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, codeBlock->lineNumberForVPC(vPC)), ReadOnly | DontDelete);
712                 exception->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, codeBlock->ownerNode->sourceId()), ReadOnly | DontDelete);
713                 exception->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsOwnedString(exec, codeBlock->ownerNode->sourceURL()), ReadOnly | DontDelete);
714             }
715             
716             if (exception->isWatchdogException()) {
717                 while (unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r)) {
718                     // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
719                 }
720                 return 0;
721             }
722         }
723     }
724
725     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
726         DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
727         debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
728     }
729
730     // Calculate an exception handler vPC, unwinding call frames as necessary.
731
732     int scopeDepth;
733     Instruction* handlerVPC;
734
735     while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) {
736         if (!unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r))
737             return 0;
738     }
739
740     // Now unwind the scope chain within the exception handler's call frame.
741
742     ScopeChain sc(scopeChain);
743     int scopeDelta = depth(sc) - scopeDepth;
744     ASSERT(scopeDelta >= 0);
745     while (scopeDelta--)
746         sc.pop();
747     setScopeChain(exec, scopeChain, sc.node());
748
749     return handlerVPC;
750 }
751
752 JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue** exception)
753 {
754     if (m_reentryDepth >= MaxReentryDepth) {
755         *exception = createStackOverflowError(exec);
756         return 0;
757     }
758
759     CodeBlock* codeBlock = &programNode->byteCode(scopeChain);
760
761     size_t oldSize = m_registerFile.size();
762     size_t newSize = oldSize + RegisterFile::CallFrameHeaderSize + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries;
763     if (!m_registerFile.grow(newSize)) {
764         *exception = createStackOverflowError(exec);
765         return 0;
766     }
767
768     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
769     JSGlobalObject* globalObject = exec->dynamicGlobalObject();
770     globalObject->copyGlobalsTo(m_registerFile);
771
772     Register* callFrame = m_registerFile.base() + oldSize;
773
774     // a 0 codeBlock indicates a built-in caller
775     initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
776
777     Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
778     r[codeBlock->thisRegister] = thisObj;
779
780     for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
781         r[i] = codeBlock->constantRegisters[i];
782
783     if (codeBlock->needsFullScopeChain)
784         scopeChain = scopeChain->copy();
785
786     ExecState newExec(exec, &m_registerFile, scopeChain, 0);
787
788     Profiler** profiler = Profiler::enabledProfilerReference();
789     if (*profiler)
790         (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
791
792     m_reentryDepth++;
793     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
794     m_reentryDepth--;
795
796     MACHINE_SAMPLING_privateExecuteReturned();
797
798     if (*profiler) {
799         (*profiler)->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
800         if (!m_reentryDepth)
801             (*profiler)->didFinishAllExecution(exec);
802     }
803
804     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
805         lastGlobalObject->copyGlobalsTo(m_registerFile);
806
807     m_registerFile.shrink(oldSize);
808     return result;
809 }
810
811 JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue** exception)
812 {
813     if (m_reentryDepth >= MaxReentryDepth) {
814         *exception = createStackOverflowError(exec);
815         return 0;
816     }
817
818     int argv = RegisterFile::CallFrameHeaderSize;
819     int argc = args.size() + 1; // implicit "this" parameter
820
821     size_t oldSize = m_registerFile.size();
822     if (!m_registerFile.grow(oldSize + RegisterFile::CallFrameHeaderSize + argc)) {
823         *exception = createStackOverflowError(exec);
824         return 0;
825     }
826
827     Register* callFrame = m_registerFile.base() + oldSize;
828
829     // put args in place, including "this"
830     Register* dst = callFrame + RegisterFile::CallFrameHeaderSize;
831     (*dst) = thisObj;
832
833     ArgList::const_iterator end = args.end();
834     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
835         (*++dst) = *it;
836
837     // a 0 codeBlock indicates a built-in caller
838     initializeCallFrame(callFrame, 0, 0, 0, callFrame, 0, argv, argc, 0, function);
839
840     CodeBlock* newCodeBlock = &functionBodyNode->byteCode(scopeChain);
841     Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, m_registerFile.base(), callFrame, argv, argc, *exception);
842     if (*exception) {
843         m_registerFile.shrink(oldSize);
844         return 0;
845     }
846
847     scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, r);
848
849     ExecState newExec(exec, &m_registerFile, scopeChain, callFrame);
850
851     Profiler** profiler = Profiler::enabledProfilerReference();
852     if (*profiler)
853         (*profiler)->willExecute(exec, function);
854
855     m_reentryDepth++;
856     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
857     m_reentryDepth--;
858
859     MACHINE_SAMPLING_privateExecuteReturned();
860
861     if (*profiler && !m_reentryDepth)
862         (*profiler)->didFinishAllExecution(exec);
863
864     m_registerFile.shrink(oldSize);
865     return result;
866 }
867
868 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
869 {
870     if (m_reentryDepth >= MaxReentryDepth) {
871         *exception = createStackOverflowError(exec);
872         return 0;
873     }
874
875     EvalCodeBlock* codeBlock = &evalNode->byteCode(scopeChain);
876
877     JSVariableObject* variableObject;
878     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
879         ASSERT(node);
880         if (node->object->isVariableObject()) {
881             variableObject = static_cast<JSVariableObject*>(node->object);
882             break;
883         }
884     }
885
886     const Node::VarStack& varStack = codeBlock->ownerNode->varStack();
887     Node::VarStack::const_iterator varStackEnd = varStack.end();
888     for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
889         const Identifier& ident = (*it).first;
890         if (!variableObject->hasProperty(exec, ident))
891             variableObject->put(exec, ident, jsUndefined());
892     }
893
894     const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack();
895     Node::FunctionStack::const_iterator functionStackEnd = functionStack.end();
896     for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it)
897         variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain));
898
899     size_t oldSize = m_registerFile.size();
900     size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries + RegisterFile::CallFrameHeaderSize;
901     if (!m_registerFile.grow(newSize)) {
902         *exception = createStackOverflowError(exec);
903         return 0;
904     }
905
906     Register* callFrame = m_registerFile.base() + registerOffset;
907
908     // a 0 codeBlock indicates a built-in caller
909     initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
910
911     Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
912     r[codeBlock->thisRegister] = thisObj;
913
914     for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
915         r[i] = codeBlock->constantRegisters[i];
916
917     if (codeBlock->needsFullScopeChain)
918         scopeChain = scopeChain->copy();
919
920     ExecState newExec(exec, &m_registerFile, scopeChain, 0);
921
922     Profiler** profiler = Profiler::enabledProfilerReference();
923     if (*profiler)
924         (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
925
926     m_reentryDepth++;
927     JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
928     m_reentryDepth--;
929
930     MACHINE_SAMPLING_privateExecuteReturned();
931
932     if (*profiler) {
933         (*profiler)->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
934         if (!m_reentryDepth)
935             (*profiler)->didFinishAllExecution(exec);
936     }
937
938     m_registerFile.shrink(oldSize);
939     return result;
940 }
941
942 ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scopeChain, ScopeChainNode* newScopeChain)
943 {
944     scopeChain = newScopeChain;
945     exec->m_scopeChain = newScopeChain;
946 }
947
948 NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r)
949 {
950     int debugHookID = (++vPC)->u.operand;
951     int firstLine = (++vPC)->u.operand;
952     int lastLine = (++vPC)->u.operand;
953
954     Debugger* debugger = exec->dynamicGlobalObject()->debugger();
955     if (!debugger)
956         return;
957
958     DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, 0);
959
960     switch((DebugHookID)debugHookID) {
961     case DidEnterCallFrame: {
962         debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
963         return;
964     }
965     case WillLeaveCallFrame: {
966         debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
967         return;
968     }
969     case WillExecuteStatement: {
970         debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
971         return;
972     }
973     case WillExecuteProgram: {
974         debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
975         return;
976     }
977     case DidExecuteProgram: {
978         debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
979         return;
980     }
981     case DidReachBreakpoint: {
982         debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
983         return;
984     }
985     }
986 }
987
988 void Machine::resetTimeoutCheck()
989 {
990     m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
991     m_timeAtLastCheckTimeout = 0;
992     m_timeExecuting = 0;
993 }
994
995 // Returns the current time in milliseconds
996 // It doesn't matter what "current time" is here, just as long as
997 // it's possible to measure the time difference correctly.
998 // In an ideal world this would just be getCurrentUTCTimeWithMicroseconds
999 // from DateMath.h, but unfortunately there's a slowdown if we use tha.
1000 static inline unsigned getCurrentTime()
1001 {
1002 #if HAVE(SYS_TIME_H)
1003     struct timeval tv;
1004     gettimeofday(&tv, 0);
1005     return tv.tv_sec * 1000 + tv.tv_usec / 1000;
1006 #elif PLATFORM(QT)
1007     QDateTime t = QDateTime::currentDateTime();
1008     return t.toTime_t() * 1000 + t.time().msec();
1009 #elif PLATFORM(WIN_OS)
1010     return timeGetTime();
1011 #else
1012 #error Platform does not have getCurrentTime function
1013 #endif
1014 }
1015
1016 // We have to return a JSValue here, gcc seems to produce worse code if 
1017 // we attempt to return a bool
1018 ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject)
1019 {
1020     unsigned currentTime = getCurrentTime();
1021     
1022     if (!m_timeAtLastCheckTimeout) {
1023         // Suspicious amount of looping in a script -- start timing it
1024         m_timeAtLastCheckTimeout = currentTime;
1025         return 0;
1026     }
1027     
1028     unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
1029     
1030     if (timeDiff == 0)
1031         timeDiff = 1;
1032     
1033     m_timeExecuting += timeDiff;
1034     m_timeAtLastCheckTimeout = currentTime;
1035     
1036     // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in 
1037     // preferredScriptCheckTimeInterval
1038     m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
1039     // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
1040     // preferred script check time interval.
1041     if (m_ticksUntilNextTimeoutCheck == 0)
1042         m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1043     
1044     if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
1045         if (globalObject->shouldInterruptScript())
1046             return jsNull(); // Appeasing GCC, all we need is a non-null js value.
1047         
1048         resetTimeoutCheck();
1049     }
1050     
1051     return 0;
1052 }
1053
1054 static int32_t offsetForStringSwitch(StringJumpTable& jumpTable, JSValue* scrutinee, int32_t defaultOffset) {
1055     StringJumpTable::const_iterator end = jumpTable.end();
1056     UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
1057     StringJumpTable::const_iterator loc = jumpTable.find(value);
1058     if (loc == end)
1059         return defaultOffset;
1060     return loc->second;
1061 }
1062
1063 static NEVER_INLINE ScopeChainNode* createExceptionScope(ExecState* exec, CodeBlock* codeBlock, const Instruction* vPC, Register* r, ScopeChainNode* scopeChain)
1064 {
1065     int dst = (++vPC)->u.operand;
1066     Identifier& property = codeBlock->identifiers[(++vPC)->u.operand];
1067     JSValue* value = r[(++vPC)->u.operand].jsValue(exec);
1068     JSObject* scope = new (exec) JSStaticScopeObject(property, value, DontDelete);
1069     r[dst] = scope;
1070     return scopeChain->push(scope);
1071 }
1072
1073 JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
1074 {
1075     // One-time initialization of our address tables. We have to put this code
1076     // here because our labels are only in scope inside this function.
1077     if (flag == InitializeAndReturn) {
1078         #if HAVE(COMPUTED_GOTO)
1079             #define ADD_OPCODE(id) m_opcodeTable[id] = &&id;
1080                 FOR_EACH_OPCODE_ID(ADD_OPCODE);
1081             #undef ADD_OPCODE
1082
1083             #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id);
1084                 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
1085             #undef ADD_OPCODE_ID
1086             ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
1087             op_throw_end_indirect = &&op_throw_end;
1088             op_call_indirect = &&op_call;
1089         #endif // HAVE(COMPUTED_GOTO)
1090         return 0;
1091     }
1092
1093     JSValue* exceptionValue = 0;
1094     Instruction* handlerVPC = 0;
1095
1096     Register* registerBase = registerFile->base();
1097     Instruction* vPC = codeBlock->instructions.begin();
1098     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1099     unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
1100
1101 #define VM_CHECK_EXCEPTION() \
1102      do { \
1103         if (UNLIKELY(exec->hadException())) { \
1104             exceptionValue = exec->exception(); \
1105             goto vm_throw; \
1106         } \
1107     } while (0)
1108
1109 #if DUMP_OPCODE_STATS
1110     OpcodeStats::resetLastInstruction();
1111 #endif
1112
1113 #define CHECK_FOR_TIMEOUT() \
1114     if (!--tickCount) { \
1115         if ((exceptionValue = checkTimeout(exec->dynamicGlobalObject()))) \
1116             goto vm_throw; \
1117         tickCount = m_ticksUntilNextTimeoutCheck; \
1118     }
1119     
1120 #if HAVE(COMPUTED_GOTO)
1121     #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); goto *vPC->u.opcode
1122 #if DUMP_OPCODE_STATS
1123     #define BEGIN_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
1124 #else
1125     #define BEGIN_OPCODE(opcode) opcode:
1126 #endif
1127     NEXT_OPCODE;
1128 #else
1129     #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); continue
1130 #if DUMP_OPCODE_STATS
1131     #define BEGIN_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1132 #else
1133     #define BEGIN_OPCODE(opcode) case opcode:
1134 #endif
1135     while (1) // iterator loop begins
1136     switch (vPC->u.opcode)
1137 #endif
1138     {
1139     BEGIN_OPCODE(op_new_object) {
1140         /* new_object dst(r)
1141
1142            Constructs a new empty Object instance using the original
1143            constructor, and puts the result in register dst.
1144         */
1145         int dst = (++vPC)->u.operand;
1146         r[dst] = constructEmptyObject(exec);
1147
1148         ++vPC;
1149         NEXT_OPCODE;
1150     }
1151     BEGIN_OPCODE(op_new_array) {
1152         /* new_array dst(r) firstArg(r) argCount(n)
1153
1154            Constructs a new Array instance using the original
1155            constructor, and puts the result in register dst.
1156            The array will contain argCount elements with values
1157            taken from registers starting at register firstArg.
1158         */
1159         int dst = (++vPC)->u.operand;
1160         int firstArg = (++vPC)->u.operand;
1161         int argCount = (++vPC)->u.operand;
1162         ArgList args(r + firstArg, argCount);
1163         r[dst] = constructArray(exec, args);
1164
1165         ++vPC;
1166         NEXT_OPCODE;
1167     }
1168     BEGIN_OPCODE(op_new_regexp) {
1169         /* new_regexp dst(r) regExp(re)
1170
1171            Constructs a new RegExp instance using the original
1172            constructor from regexp regExp, and puts the result in
1173            register dst.
1174         */
1175         int dst = (++vPC)->u.operand;
1176         int regExp = (++vPC)->u.operand;
1177         r[dst] = new (exec) RegExpObject(scopeChain->globalObject()->regExpPrototype(), codeBlock->regexps[regExp]);
1178
1179         ++vPC;
1180         NEXT_OPCODE;
1181     }
1182     BEGIN_OPCODE(op_mov) {
1183         /* mov dst(r) src(r)
1184
1185            Copies register src to register dst.
1186         */
1187         int dst = (++vPC)->u.operand;
1188         int src = (++vPC)->u.operand;
1189         r[dst] = r[src];
1190
1191         ++vPC;
1192         NEXT_OPCODE;
1193     }
1194     BEGIN_OPCODE(op_eq) {
1195         /* eq dst(r) src1(r) src2(r)
1196
1197            Checks whether register src1 and register src2 are equal,
1198            as with the ECMAScript '==' operator, and puts the result
1199            as a boolean in register dst.
1200         */
1201         int dst = (++vPC)->u.operand;
1202         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1203         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1204         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1205             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1206         else {
1207             JSValue* result = jsBoolean(equal(exec, src1, src2));
1208             VM_CHECK_EXCEPTION();
1209             r[dst] = result;
1210         }
1211
1212         ++vPC;
1213         NEXT_OPCODE;
1214     }
1215     BEGIN_OPCODE(op_neq) {
1216         /* neq dst(r) src1(r) src2(r)
1217
1218            Checks whether register src1 and register src2 are not
1219            equal, as with the ECMAScript '!=' operator, and puts the
1220            result as a boolean in register dst.
1221         */
1222         int dst = (++vPC)->u.operand;
1223         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1224         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1225         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1226             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1227         else {
1228             JSValue* result = jsBoolean(!equal(exec, src1, src2));
1229             VM_CHECK_EXCEPTION();
1230             r[dst] = result;
1231         }
1232
1233         ++vPC;
1234         NEXT_OPCODE;
1235     }
1236     BEGIN_OPCODE(op_stricteq) {
1237         /* stricteq dst(r) src1(r) src2(r)
1238
1239            Checks whether register src1 and register src2 are strictly
1240            equal, as with the ECMAScript '===' operator, and puts the
1241            result as a boolean in register dst.
1242         */
1243         int dst = (++vPC)->u.operand;
1244         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1245         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1246         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1247             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1248         else
1249             r[dst] = jsBoolean(strictEqual(src1, src2));
1250
1251         ++vPC;
1252         NEXT_OPCODE;
1253     }
1254     BEGIN_OPCODE(op_nstricteq) {
1255         /* nstricteq dst(r) src1(r) src2(r)
1256
1257            Checks whether register src1 and register src2 are not
1258            strictly equal, as with the ECMAScript '!==' operator, and
1259            puts the result as a boolean in register dst.
1260         */
1261         int dst = (++vPC)->u.operand;
1262         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1263         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1264         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1265             r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1266         else
1267             r[dst] = jsBoolean(!strictEqual(src1, src2));
1268
1269         ++vPC;
1270         NEXT_OPCODE;
1271     }
1272     BEGIN_OPCODE(op_less) {
1273         /* less dst(r) src1(r) src2(r)
1274
1275            Checks whether register src1 is less than register src2, as
1276            with the ECMAScript '<' operator, and puts the result as
1277            a boolean in register dst.
1278         */
1279         int dst = (++vPC)->u.operand;
1280         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1281         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1282         JSValue* result = jsBoolean(jsLess(exec, src1, src2));
1283         VM_CHECK_EXCEPTION();
1284         r[dst] = result;
1285
1286         ++vPC;
1287         NEXT_OPCODE;
1288     }
1289     BEGIN_OPCODE(op_lesseq) {
1290         /* lesseq dst(r) src1(r) src2(r)
1291
1292            Checks whether register src1 is less than or equal to
1293            register src2, as with the ECMAScript '<=' operator, and
1294            puts the result as a boolean in register dst.
1295         */
1296         int dst = (++vPC)->u.operand;
1297         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1298         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1299         JSValue* result = jsBoolean(jsLessEq(exec, src1, src2));
1300         VM_CHECK_EXCEPTION();
1301         r[dst] = result;
1302
1303         ++vPC;
1304         NEXT_OPCODE;
1305     }
1306     BEGIN_OPCODE(op_pre_inc) {
1307         /* pre_inc srcDst(r)
1308
1309            Converts register srcDst to number, adds one, and puts the result
1310            back in register srcDst.
1311         */
1312         int srcDst = (++vPC)->u.operand;
1313         JSValue* v = r[srcDst].jsValue(exec);
1314         if (JSImmediate::canDoFastAdditiveOperations(v))
1315             r[srcDst] = JSImmediate::incImmediateNumber(v);
1316         else {
1317             JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
1318             VM_CHECK_EXCEPTION();
1319             r[srcDst] = result;
1320         }
1321
1322         ++vPC;
1323         NEXT_OPCODE;
1324     }
1325     BEGIN_OPCODE(op_pre_dec) {
1326         /* pre_dec srcDst(r)
1327
1328            Converts register srcDst to number, subtracts one, and puts the result
1329            back in register srcDst.
1330         */
1331         int srcDst = (++vPC)->u.operand;
1332         JSValue* v = r[srcDst].jsValue(exec);
1333         if (JSImmediate::canDoFastAdditiveOperations(v))
1334             r[srcDst] = JSImmediate::decImmediateNumber(v);
1335         else {
1336             JSValue* result = jsNumber(exec, v->toNumber(exec) - 1);
1337             VM_CHECK_EXCEPTION();
1338             r[srcDst] = result;
1339         }
1340
1341         ++vPC;
1342         NEXT_OPCODE;
1343     }
1344     BEGIN_OPCODE(op_post_inc) {
1345         /* post_inc dst(r) srcDst(r)
1346
1347            Converts register srcDst to number. The number itself is
1348            written to register dst, and the number plus one is written
1349            back to register srcDst.
1350         */
1351         int dst = (++vPC)->u.operand;
1352         int srcDst = (++vPC)->u.operand;
1353         JSValue* v = r[srcDst].jsValue(exec);
1354         if (JSImmediate::canDoFastAdditiveOperations(v)) {
1355             r[dst] = v;
1356             r[srcDst] = JSImmediate::incImmediateNumber(v);
1357         } else {
1358             JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1359             VM_CHECK_EXCEPTION();
1360             r[dst] = number;
1361             r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() + 1);
1362         }
1363
1364         ++vPC;
1365         NEXT_OPCODE;
1366     }
1367     BEGIN_OPCODE(op_post_dec) {
1368         /* post_dec dst(r) srcDst(r)
1369
1370            Converts register srcDst to number. The number itself is
1371            written to register dst, and the number minus one is written
1372            back to register srcDst.
1373         */
1374         int dst = (++vPC)->u.operand;
1375         int srcDst = (++vPC)->u.operand;
1376         JSValue* v = r[srcDst].jsValue(exec);
1377         if (JSImmediate::canDoFastAdditiveOperations(v)) {
1378             r[dst] = v;
1379             r[srcDst] = JSImmediate::decImmediateNumber(v);
1380         } else {
1381             JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1382             VM_CHECK_EXCEPTION();
1383             r[dst] = number;
1384             r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() - 1);
1385         }
1386
1387         ++vPC;
1388         NEXT_OPCODE;
1389     }
1390     BEGIN_OPCODE(op_to_jsnumber) {
1391         /* to_jsnumber dst(r) src(r)
1392
1393            Converts register src to number, and puts the result
1394            in register dst.
1395         */
1396         int dst = (++vPC)->u.operand;
1397         int src = (++vPC)->u.operand;
1398         JSValue* result = r[src].jsValue(exec)->toJSNumber(exec);
1399         VM_CHECK_EXCEPTION();
1400
1401         r[dst] = result;
1402
1403         ++vPC;
1404         NEXT_OPCODE;
1405     }
1406     BEGIN_OPCODE(op_negate) {
1407         /* negate dst(r) src(r)
1408
1409            Converts register src to number, negates it, and puts the
1410            result in register dst.
1411         */
1412         int dst = (++vPC)->u.operand;
1413         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1414         double v;
1415         if (fastIsNumber(src, v))
1416             r[dst] = jsNumber(exec, -v);
1417         else {
1418             JSValue* result = jsNumber(exec, -src->toNumber(exec));
1419             VM_CHECK_EXCEPTION();
1420             r[dst] = result;
1421         }
1422
1423         ++vPC;
1424         NEXT_OPCODE;
1425     }
1426     BEGIN_OPCODE(op_add) {
1427         /* add dst(r) src1(r) src2(r)
1428
1429            Adds register src1 and register src2, and puts the result
1430            in register dst. (JS add may be string concatenation or
1431            numeric add, depending on the types of the operands.)
1432         */
1433         int dst = (++vPC)->u.operand;
1434         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1435         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1436         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1437             r[dst] = JSImmediate::addImmediateNumbers(src1, src2);
1438         else {
1439             JSValue* result = jsAdd(exec, src1, src2);
1440             VM_CHECK_EXCEPTION();
1441             r[dst] = result;
1442         }
1443         ++vPC;
1444         NEXT_OPCODE;
1445     }
1446     BEGIN_OPCODE(op_mul) {
1447         /* mul dst(r) src1(r) src2(r)
1448
1449            Multiplies register src1 and register src2 (converted to
1450            numbers), and puts the product in register dst.
1451         */
1452         int dst = (++vPC)->u.operand;
1453         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1454         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1455         double left;
1456         double right;
1457         if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1458             r[dst] = jsNumber(exec, left * right);
1459         else {
1460             JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
1461             VM_CHECK_EXCEPTION();
1462             r[dst] = result;
1463         }
1464
1465         ++vPC;
1466         NEXT_OPCODE;
1467     }
1468     BEGIN_OPCODE(op_div) {
1469         /* div dst(r) dividend(r) divisor(r)
1470
1471            Divides register dividend (converted to number) by the
1472            register divisor (converted to number), and puts the
1473            quotient in register dst.
1474         */
1475         int dst = (++vPC)->u.operand;
1476         JSValue* dividend = r[(++vPC)->u.operand].jsValue(exec);
1477         JSValue* divisor = r[(++vPC)->u.operand].jsValue(exec);
1478         double left;
1479         double right;
1480         if (fastIsNumber(dividend, left) && fastIsNumber(divisor, right))
1481             r[dst] = jsNumber(exec, left / right);
1482         else {
1483             JSValue* result = jsNumber(exec, dividend->toNumber(exec) / divisor->toNumber(exec));
1484             VM_CHECK_EXCEPTION();
1485             r[dst] = result;
1486         }
1487         ++vPC;
1488         NEXT_OPCODE;
1489     }
1490     BEGIN_OPCODE(op_mod) {
1491         /* mod dst(r) dividend(r) divisor(r)
1492
1493            Divides register dividend (converted to number) by
1494            register divisor (converted to number), and puts the
1495            remainder in register dst.
1496         */
1497         int dst = (++vPC)->u.operand;
1498         int dividend = (++vPC)->u.operand;
1499         int divisor = (++vPC)->u.operand;
1500
1501         JSValue* dividendValue = r[dividend].jsValue(exec);
1502         JSValue* divisorValue = r[divisor].jsValue(exec);
1503
1504         if (JSImmediate::areBothImmediateNumbers(dividendValue, divisorValue) && divisorValue != JSImmediate::from(0)) {
1505             r[dst] = JSImmediate::from(JSImmediate::getTruncatedInt32(dividendValue) % JSImmediate::getTruncatedInt32(divisorValue));
1506             ++vPC;
1507             NEXT_OPCODE;
1508         }
1509
1510         double d = dividendValue->toNumber(exec);
1511         JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
1512         VM_CHECK_EXCEPTION();
1513         r[dst] = result;
1514         ++vPC;
1515         NEXT_OPCODE;
1516     }
1517     BEGIN_OPCODE(op_sub) {
1518         /* sub dst(r) src1(r) src2(r)
1519
1520            Subtracts register src2 (converted to number) from register
1521            src1 (converted to number), and puts the difference in
1522            register dst.
1523         */
1524         int dst = (++vPC)->u.operand;
1525         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1526         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1527         double left;
1528         double right;
1529         if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1530             r[dst] = JSImmediate::subImmediateNumbers(src1, src2);
1531         else if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1532             r[dst] = jsNumber(exec, left - right);
1533         else {
1534             JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
1535             VM_CHECK_EXCEPTION();
1536             r[dst] = result;
1537         }
1538         ++vPC;
1539         NEXT_OPCODE;
1540     }
1541     BEGIN_OPCODE(op_lshift) {
1542         /* lshift dst(r) val(r) shift(r)
1543
1544            Performs left shift of register val (converted to int32) by
1545            register shift (converted to uint32), and puts the result
1546            in register dst.
1547         */
1548         int dst = (++vPC)->u.operand;
1549         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1550         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1551         int32_t left;
1552         uint32_t right;
1553         if (JSImmediate::areBothImmediateNumbers(val, shift))
1554             r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::toTruncatedUInt32(shift) & 0x1f));
1555         else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1556             r[dst] = jsNumber(exec, left << (right & 0x1f));
1557         else {
1558             JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
1559             VM_CHECK_EXCEPTION();
1560             r[dst] = result;
1561         }
1562
1563         ++vPC;
1564         NEXT_OPCODE;
1565     }
1566     BEGIN_OPCODE(op_rshift) {
1567         /* rshift dst(r) val(r) shift(r)
1568
1569            Performs arithmetic right shift of register val (converted
1570            to int32) by register shift (converted to
1571            uint32), and puts the result in register dst.
1572         */
1573         int dst = (++vPC)->u.operand;
1574         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1575         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1576         int32_t left;
1577         uint32_t right;
1578         if (JSImmediate::areBothImmediateNumbers(val, shift))
1579             r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1580         else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1581             r[dst] = jsNumber(exec, left >> (right & 0x1f));
1582         else {
1583             JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1584             VM_CHECK_EXCEPTION();
1585             r[dst] = result;
1586         }
1587
1588         ++vPC;
1589         NEXT_OPCODE;
1590     }
1591     BEGIN_OPCODE(op_urshift) {
1592         /* rshift dst(r) val(r) shift(r)
1593
1594            Performs logical right shift of register val (converted
1595            to uint32) by register shift (converted to
1596            uint32), and puts the result in register dst.
1597         */
1598         int dst = (++vPC)->u.operand;
1599         JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1600         JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1601         if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
1602             r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1603         else {
1604             JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1605             VM_CHECK_EXCEPTION();
1606             r[dst] = result;
1607         }
1608
1609         ++vPC;
1610         NEXT_OPCODE;
1611     }
1612     BEGIN_OPCODE(op_bitand) {
1613         /* bitand dst(r) src1(r) src2(r)
1614
1615            Computes bitwise AND of register src1 (converted to int32)
1616            and register src2 (converted to int32), and puts the result
1617            in register dst.
1618         */
1619         int dst = (++vPC)->u.operand;
1620         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1621         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1622         int32_t left;
1623         int32_t right;
1624         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1625             r[dst] = JSImmediate::andImmediateNumbers(src1, src2);
1626         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1627             r[dst] = jsNumber(exec, left & right);
1628         else {
1629             JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
1630             VM_CHECK_EXCEPTION();
1631             r[dst] = result;
1632         }
1633
1634         ++vPC;
1635         NEXT_OPCODE;
1636     }
1637     BEGIN_OPCODE(op_bitxor) {
1638         /* bitxor dst(r) src1(r) src2(r)
1639
1640            Computes bitwise XOR of register src1 (converted to int32)
1641            and register src2 (converted to int32), and puts the result
1642            in register dst.
1643         */
1644         int dst = (++vPC)->u.operand;
1645         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1646         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1647         int32_t left;
1648         int32_t right;
1649         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1650             r[dst] = JSImmediate::xorImmediateNumbers(src1, src2);
1651         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1652             r[dst] = jsNumber(exec, left ^ right);
1653         else {
1654             JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
1655             VM_CHECK_EXCEPTION();
1656             r[dst] = result;
1657         }
1658
1659         ++vPC;
1660         NEXT_OPCODE;
1661     }
1662     BEGIN_OPCODE(op_bitor) {
1663         /* bitor dst(r) src1(r) src2(r)
1664
1665            Computes bitwise OR of register src1 (converted to int32)
1666            and register src2 (converted to int32), and puts the
1667            result in register dst.
1668         */
1669         int dst = (++vPC)->u.operand;
1670         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1671         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1672         int32_t left;
1673         int32_t right;
1674         if (JSImmediate::areBothImmediateNumbers(src1, src2))
1675             r[dst] = JSImmediate::orImmediateNumbers(src1, src2);
1676         else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1677             r[dst] = jsNumber(exec, left | right);
1678         else {
1679             JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
1680             VM_CHECK_EXCEPTION();
1681             r[dst] = result;
1682         }
1683
1684         ++vPC;
1685         NEXT_OPCODE;
1686     }
1687     BEGIN_OPCODE(op_bitnot) {
1688         /* bitnot dst(r) src(r)
1689
1690            Computes bitwise NOT of register src1 (converted to int32),
1691            and puts the result in register dst.
1692         */
1693         int dst = (++vPC)->u.operand;
1694         JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1695         int32_t value;
1696         if (fastToInt32(src, value))
1697             r[dst] = jsNumber(exec, ~value);
1698         else {
1699             JSValue* result = jsNumber(exec, ~src->toInt32(exec));
1700             VM_CHECK_EXCEPTION();
1701             r[dst] = result;
1702         }
1703         ++vPC;
1704         NEXT_OPCODE;
1705     }
1706     BEGIN_OPCODE(op_not) {
1707         /* not dst(r) src(r)
1708
1709            Computes logical NOT of register src (converted to
1710            boolean), and puts the result in register dst.
1711         */
1712         int dst = (++vPC)->u.operand;
1713         int src = (++vPC)->u.operand;
1714         JSValue* result = jsBoolean(!r[src].jsValue(exec)->toBoolean(exec));
1715         VM_CHECK_EXCEPTION();
1716         r[dst] = result;
1717
1718         ++vPC;
1719         NEXT_OPCODE;
1720     }
1721     BEGIN_OPCODE(op_instanceof) {
1722         /* instanceof dst(r) value(r) constructor(r)
1723
1724            Tests whether register value is an instance of register
1725            constructor, and puts the boolean result in register dst.
1726
1727            Raises an exception if register constructor is not an
1728            object.
1729         */
1730         int dst = (++vPC)->u.operand;
1731         int value = (++vPC)->u.operand;
1732         int base = (++vPC)->u.operand;
1733
1734         JSValue* baseVal = r[base].jsValue(exec);
1735
1736         if (isNotObject(exec, true, codeBlock, vPC, baseVal, exceptionValue))
1737             goto vm_throw;
1738
1739         JSObject* baseObj = static_cast<JSObject*>(baseVal);
1740         r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec)) : false);
1741
1742         ++vPC;
1743         NEXT_OPCODE;
1744     }
1745     BEGIN_OPCODE(op_typeof) {
1746         /* typeof dst(r) src(r)
1747
1748            Determines the type string for src according to ECMAScript
1749            rules, and puts the result in register dst.
1750         */
1751         int dst = (++vPC)->u.operand;
1752         int src = (++vPC)->u.operand;
1753         r[dst] = jsTypeStringForValue(exec, r[src].jsValue(exec));
1754
1755         ++vPC;
1756         NEXT_OPCODE;
1757     }
1758     BEGIN_OPCODE(op_in) {
1759         /* in dst(r) property(r) base(r)
1760
1761            Tests whether register base has a property named register
1762            property, and puts the boolean result in register dst.
1763
1764            Raises an exception if register constructor is not an
1765            object.
1766         */
1767         int dst = (++vPC)->u.operand;
1768         int property = (++vPC)->u.operand;
1769         int base = (++vPC)->u.operand;
1770
1771         JSValue* baseVal = r[base].jsValue(exec);
1772         if (isNotObject(exec, false, codeBlock, vPC, baseVal, exceptionValue))
1773             goto vm_throw;
1774
1775         JSObject* baseObj = static_cast<JSObject*>(baseVal);
1776
1777         JSValue* propName = r[property].jsValue(exec);
1778
1779         uint32_t i;
1780         if (propName->getUInt32(i))
1781             r[dst] = jsBoolean(baseObj->hasProperty(exec, i));
1782         else {
1783             Identifier property(exec, propName->toString(exec));
1784             VM_CHECK_EXCEPTION();
1785             r[dst] = jsBoolean(baseObj->hasProperty(exec, property));
1786         }
1787
1788         ++vPC;
1789         NEXT_OPCODE;
1790     }
1791     BEGIN_OPCODE(op_resolve) {
1792         /* resolve dst(r) property(id)
1793
1794            Looks up the property named by identifier property in the
1795            scope chain, and writes the resulting value to register
1796            dst. If the property is not found, raises an exception.
1797         */
1798         if (UNLIKELY(!resolve(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1799             goto vm_throw;
1800
1801         vPC += 3;
1802         NEXT_OPCODE;
1803     }
1804     BEGIN_OPCODE(op_resolve_skip) {
1805         /* resolve_skip dst(r) property(id) skip(n)
1806
1807          Looks up the property named by identifier property in the
1808          scope chain skipping the top 'skip' levels, and writes the resulting
1809          value to register dst. If the property is not found, raises an exception.
1810          */
1811         if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1812             goto vm_throw;
1813
1814         vPC += 4;
1815
1816         NEXT_OPCODE;
1817     }
1818     BEGIN_OPCODE(op_get_scoped_var) {
1819         /* get_scoped_var dst(r) index(n) skip(n)
1820
1821          Loads the contents of the index-th local from the scope skip nodes from
1822          the top of the scope chain, and places it in register dst
1823          */
1824         int dst = (++vPC)->u.operand;
1825         int index = (++vPC)->u.operand;
1826         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1827
1828         ScopeChainIterator iter = scopeChain->begin();
1829         ScopeChainIterator end = scopeChain->end();
1830         ASSERT(iter != end);
1831         while (skip--) {
1832             ++iter;
1833             ASSERT(iter != end);
1834         }
1835
1836         ASSERT((*iter)->isVariableObject());
1837         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1838         r[dst] = scope->registerAt(index);
1839         ++vPC;
1840         NEXT_OPCODE;
1841     }
1842     BEGIN_OPCODE(op_put_scoped_var) {
1843         /* put_scoped_var index(n) skip(n) value(r)
1844
1845          */
1846         int index = (++vPC)->u.operand;
1847         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1848         int value = (++vPC)->u.operand;
1849
1850         ScopeChainIterator iter = scopeChain->begin();
1851         ScopeChainIterator end = scopeChain->end();
1852         ASSERT(iter != end);
1853         while (skip--) {
1854             ++iter;
1855             ASSERT(iter != end);
1856         }
1857
1858         ASSERT((*iter)->isVariableObject());
1859         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1860         scope->registerAt(index) = r[value].jsValue(exec);
1861         ++vPC;
1862         NEXT_OPCODE;
1863     }
1864     BEGIN_OPCODE(op_resolve_base) {
1865         /* resolve_base dst(r) property(id)
1866
1867            Searches the scope chain for an object containing
1868            identifier property, and if one is found, writes it to
1869            register dst. If none is found, the outermost scope (which
1870            will be the global object) is stored in register dst.
1871         */
1872         resolveBase(exec, vPC, r, scopeChain, codeBlock);
1873
1874         vPC += 3;
1875         NEXT_OPCODE;
1876     }
1877     BEGIN_OPCODE(op_resolve_with_base) {
1878         /* resolve_with_base baseDst(r) propDst(r) property(id)
1879
1880            Searches the scope chain for an object containing
1881            identifier property, and if one is found, writes it to
1882            register srcDst, and the retrieved property value to register
1883            propDst. If the property is not found, raises an exception.
1884
1885            This is more efficient than doing resolve_base followed by
1886            resolve, or resolve_base followed by get_by_id, as it
1887            avoids duplicate hash lookups.
1888         */
1889         if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1890             goto vm_throw;
1891
1892         vPC += 4;
1893         NEXT_OPCODE;
1894     }
1895     BEGIN_OPCODE(op_resolve_func) {
1896         /* resolve_func baseDst(r) funcDst(r) property(id)
1897
1898            Searches the scope chain for an object containing
1899            identifier property, and if one is found, writes the
1900            appropriate object to use as "this" when calling its
1901            properties to register baseDst; and the retrieved property
1902            value to register propDst. If the property is not found,
1903            raises an exception.
1904
1905            This differs from resolve_with_base, because the
1906            global this value will be substituted for activations or
1907            the global object, which is the right behavior for function
1908            calls but not for other property lookup.
1909         */
1910         if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1911             goto vm_throw;
1912
1913         vPC += 4;
1914         NEXT_OPCODE;
1915     }
1916     BEGIN_OPCODE(op_get_by_id) {
1917         /* get_by_id dst(r) base(r) property(id)
1918
1919            Converts register base to Object, gets the property
1920            named by identifier property from the object, and puts the
1921            result in register dst.
1922         */
1923         int dst = (++vPC)->u.operand;
1924         int base = (++vPC)->u.operand;
1925         int property = (++vPC)->u.operand;
1926
1927         Identifier& ident = codeBlock->identifiers[property];
1928         JSValue *result = r[base].jsValue(exec)->get(exec, ident);
1929         VM_CHECK_EXCEPTION();
1930         r[dst] = result;
1931         ++vPC;
1932         NEXT_OPCODE;
1933     }
1934     BEGIN_OPCODE(op_put_by_id) {
1935         /* put_by_id base(r) property(id) value(r)
1936
1937            Sets register value on register base as the property named
1938            by identifier property. Base is converted to object first.
1939
1940            Unlike many opcodes, this one does not write any output to
1941            the register file.
1942         */
1943         int base = (++vPC)->u.operand;
1944         int property = (++vPC)->u.operand;
1945         int value = (++vPC)->u.operand;
1946
1947         Identifier& ident = codeBlock->identifiers[property];
1948         r[base].jsValue(exec)->put(exec, ident, r[value].jsValue(exec));
1949
1950         VM_CHECK_EXCEPTION();
1951         ++vPC;
1952         NEXT_OPCODE;
1953     }
1954     BEGIN_OPCODE(op_del_by_id) {
1955         /* del_by_id dst(r) base(r) property(id)
1956
1957            Converts register base to Object, deletes the property
1958            named by identifier property from the object, and writes a
1959            boolean indicating success (if true) or failure (if false)
1960            to register dst.
1961         */
1962         int dst = (++vPC)->u.operand;
1963         int base = (++vPC)->u.operand;
1964         int property = (++vPC)->u.operand;
1965
1966         JSObject* baseObj = r[base].jsValue(exec)->toObject(exec);
1967
1968         Identifier& ident = codeBlock->identifiers[property];
1969         JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
1970         VM_CHECK_EXCEPTION();
1971         r[dst] = result;
1972         ++vPC;
1973         NEXT_OPCODE;
1974     }
1975     BEGIN_OPCODE(op_get_by_val) {
1976         /* get_by_val dst(r) base(r) property(r)
1977
1978            Converts register base to Object, gets the property named
1979            by register property from the object, and puts the result
1980            in register dst. property is nominally converted to string
1981            but numbers are treated more efficiently.
1982         */
1983         int dst = (++vPC)->u.operand;
1984         int base = (++vPC)->u.operand;
1985         int property = (++vPC)->u.operand;
1986
1987         JSValue* baseValue = r[base].jsValue(exec);
1988         JSValue* subscript = r[property].jsValue(exec);
1989
1990         JSValue* result;
1991         unsigned i;
1992
1993         bool isUInt32 = JSImmediate::getUInt32(subscript, i);
1994         if (LIKELY(isUInt32)) {
1995             if (isJSArray(baseValue)) {
1996                 JSArray* jsArray = static_cast<JSArray*>(baseValue);
1997                 if (jsArray->canGetIndex(i))
1998                     result = jsArray->getIndex(i);
1999                 else
2000                     result = jsArray->JSArray::get(exec, i);
2001             } else if (isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
2002                 result = static_cast<JSString*>(baseValue)->getIndex(exec, i);
2003             else
2004                 result = baseValue->get(exec, i);
2005         } else {
2006             Identifier property(exec, subscript->toString(exec));
2007             result = baseValue->get(exec, property);
2008         }
2009
2010         VM_CHECK_EXCEPTION();
2011         r[dst] = result;
2012         ++vPC;
2013         NEXT_OPCODE;
2014     }
2015     BEGIN_OPCODE(op_put_by_val) {
2016         /* put_by_val base(r) property(r) value(r)
2017
2018            Sets register value on register base as the property named
2019            by register property. Base is converted to object
2020            first. register property is nominally converted to string
2021            but numbers are treated more efficiently.
2022
2023            Unlike many opcodes, this one does not write any output to
2024            the register file.
2025         */
2026         int base = (++vPC)->u.operand;
2027         int property = (++vPC)->u.operand;
2028         int value = (++vPC)->u.operand;
2029
2030         JSValue* baseValue = r[base].jsValue(exec);
2031         JSValue* subscript = r[property].jsValue(exec);
2032
2033         unsigned i;
2034
2035         bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2036         if (LIKELY(isUInt32)) {
2037             if (isJSArray(baseValue)) {
2038                 JSArray* jsArray = static_cast<JSArray*>(baseValue);
2039                 if (jsArray->canSetIndex(i))
2040                     jsArray->setIndex(i, r[value].jsValue(exec));
2041                 else
2042                     jsArray->JSArray::put(exec, i, r[value].jsValue(exec));
2043             } else
2044                 baseValue->put(exec, i, r[value].jsValue(exec));
2045         } else {
2046             Identifier property(exec, subscript->toString(exec));
2047             if (!exec->hadException()) // Don't put to an object if toString threw an exception.
2048                 baseValue->put(exec, property, r[value].jsValue(exec));
2049         }
2050
2051         VM_CHECK_EXCEPTION();
2052         ++vPC;
2053         NEXT_OPCODE;
2054     }
2055     BEGIN_OPCODE(op_del_by_val) {
2056         /* del_by_val dst(r) base(r) property(r)
2057
2058            Converts register base to Object, deletes the property
2059            named by register property from the object, and writes a
2060            boolean indicating success (if true) or failure (if false)
2061            to register dst.
2062         */
2063         int dst = (++vPC)->u.operand;
2064         int base = (++vPC)->u.operand;
2065         int property = (++vPC)->u.operand;
2066
2067         JSObject* baseObj = r[base].jsValue(exec)->toObject(exec); // may throw
2068
2069         JSValue* subscript = r[property].jsValue(exec);
2070         JSValue* result;
2071         uint32_t i;
2072         if (subscript->getUInt32(i))
2073             result = jsBoolean(baseObj->deleteProperty(exec, i));
2074         else {
2075             VM_CHECK_EXCEPTION();
2076             Identifier property(exec, subscript->toString(exec));
2077             VM_CHECK_EXCEPTION();
2078             result = jsBoolean(baseObj->deleteProperty(exec, property));
2079         }
2080
2081         VM_CHECK_EXCEPTION();
2082         r[dst] = result;
2083         ++vPC;
2084         NEXT_OPCODE;
2085     }
2086     BEGIN_OPCODE(op_put_by_index) {
2087         /* put_by_index base(r) property(n) value(r)
2088
2089            Sets register value on register base as the property named
2090            by the immediate number property. Base is converted to
2091            object first.
2092
2093            Unlike many opcodes, this one does not write any output to
2094            the register file.
2095
2096            This opcode is mainly used to initialize array literals.
2097         */
2098         int base = (++vPC)->u.operand;
2099         unsigned property = (++vPC)->u.operand;
2100         int value = (++vPC)->u.operand;
2101
2102         r[base].jsValue(exec)->put(exec, property, r[value].jsValue(exec));
2103
2104         ++vPC;
2105         NEXT_OPCODE;
2106     }
2107     BEGIN_OPCODE(op_loop) {
2108         /* loop target(offset)
2109          
2110            Jumps unconditionally to offset target from the current
2111            instruction.
2112
2113            Additionally this loop instruction may terminate JS execution is
2114            the JS timeout is reached.
2115          */
2116 #if DUMP_OPCODE_STATS
2117         OpcodeStats::resetLastInstruction();
2118 #endif
2119         int target = (++vPC)->u.operand;
2120         CHECK_FOR_TIMEOUT();
2121         vPC += target;
2122         NEXT_OPCODE;
2123     }
2124     BEGIN_OPCODE(op_jmp) {
2125         /* jmp target(offset)
2126
2127            Jumps unconditionally to offset target from the current
2128            instruction.
2129         */
2130 #if DUMP_OPCODE_STATS
2131         OpcodeStats::resetLastInstruction();
2132 #endif
2133         int target = (++vPC)->u.operand;
2134
2135         vPC += target;
2136         NEXT_OPCODE;
2137     }
2138     BEGIN_OPCODE(op_loop_if_true) {
2139         /* loop_if_true cond(r) target(offset)
2140          
2141            Jumps to offset target from the current instruction, if and
2142            only if register cond converts to boolean as true.
2143
2144            Additionally this loop instruction may terminate JS execution is
2145            the JS timeout is reached.
2146          */
2147         int cond = (++vPC)->u.operand;
2148         int target = (++vPC)->u.operand;
2149         if (r[cond].jsValue(exec)->toBoolean(exec)) {
2150             vPC += target;
2151             CHECK_FOR_TIMEOUT();
2152             NEXT_OPCODE;
2153         }
2154         
2155         ++vPC;
2156         NEXT_OPCODE;
2157     }
2158     BEGIN_OPCODE(op_jtrue) {
2159         /* jtrue cond(r) target(offset)
2160
2161            Jumps to offset target from the current instruction, if and
2162            only if register cond converts to boolean as true.
2163         */
2164         int cond = (++vPC)->u.operand;
2165         int target = (++vPC)->u.operand;
2166         if (r[cond].jsValue(exec)->toBoolean(exec)) {
2167             vPC += target;
2168             NEXT_OPCODE;
2169         }
2170
2171         ++vPC;
2172         NEXT_OPCODE;
2173     }
2174     BEGIN_OPCODE(op_jfalse) {
2175         /* jfalse cond(r) target(offset)
2176
2177            Jumps to offset target from the current instruction, if and
2178            only if register cond converts to boolean as false.
2179         */
2180         int cond = (++vPC)->u.operand;
2181         int target = (++vPC)->u.operand;
2182         if (!r[cond].jsValue(exec)->toBoolean(exec)) {
2183             vPC += target;
2184             NEXT_OPCODE;
2185         }
2186
2187         ++vPC;
2188         NEXT_OPCODE;
2189     }
2190     BEGIN_OPCODE(op_loop_if_less) {
2191         /* loop_if_less src1(r) src2(r) target(offset)
2192
2193            Checks whether register src1 is less than register src2, as
2194            with the ECMAScript '<' operator, and then jumps to offset
2195            target from the current instruction, if and only if the 
2196            result of the comparison is true.
2197
2198            Additionally this loop instruction may terminate JS execution is
2199            the JS timeout is reached.
2200          */
2201         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2202         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2203         int target = (++vPC)->u.operand;
2204         
2205         bool result = jsLess(exec, src1, src2);
2206         VM_CHECK_EXCEPTION();
2207         
2208         if (result) {
2209             vPC += target;
2210             CHECK_FOR_TIMEOUT();
2211             NEXT_OPCODE;
2212         }
2213         
2214         ++vPC;
2215         NEXT_OPCODE;
2216     }
2217     BEGIN_OPCODE(op_jnless) {
2218         /* jnless src1(r) src2(r) target(offset)
2219
2220            Checks whether register src1 is less than register src2, as
2221            with the ECMAScript '<' operator, and then jumps to offset
2222            target from the current instruction, if and only if the 
2223            result of the comparison is false.
2224         */
2225         JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2226         JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2227         int target = (++vPC)->u.operand;
2228
2229         bool result = jsLess(exec, src1, src2);
2230         VM_CHECK_EXCEPTION();
2231         
2232         if (!result) {
2233             vPC += target;
2234             NEXT_OPCODE;
2235         }
2236
2237         ++vPC;
2238         NEXT_OPCODE;
2239     }
2240     BEGIN_OPCODE(op_switch_imm) {
2241         /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
2242
2243            Performs a range checked switch on the scrutinee value, using
2244            the tableIndex-th immediate switch jump table.  If the scrutinee value
2245            is an immediate number in the range covered by the referenced jump
2246            table, and the value at jumpTable[scrutinee value] is non-zero, then
2247            that value is used as the jump offset, otherwise defaultOffset is used.
2248          */
2249         int tableIndex = (++vPC)->u.operand;
2250         int defaultOffset = (++vPC)->u.operand;
2251         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2252         if (!JSImmediate::isNumber(scrutinee))
2253             vPC += defaultOffset;
2254         else {
2255             int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
2256             vPC += codeBlock->immediateSwitchJumpTables[tableIndex].offsetForValue(value, defaultOffset);
2257         }
2258         NEXT_OPCODE;
2259     }
2260     BEGIN_OPCODE(op_switch_char) {
2261         /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
2262
2263            Performs a range checked switch on the scrutinee value, using
2264            the tableIndex-th character switch jump table.  If the scrutinee value
2265            is a single character string in the range covered by the referenced jump
2266            table, and the value at jumpTable[scrutinee value] is non-zero, then
2267            that value is used as the jump offset, otherwise defaultOffset is used.
2268          */
2269         int tableIndex = (++vPC)->u.operand;
2270         int defaultOffset = (++vPC)->u.operand;
2271         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2272         if (scrutinee->type() != StringType)
2273             vPC += defaultOffset;
2274         else {
2275             UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
2276             if (value->size() != 1)
2277                 vPC += defaultOffset;
2278             else
2279                 vPC += codeBlock->characterSwitchJumpTables[tableIndex].offsetForValue(value->data()[0], defaultOffset);
2280         }
2281         NEXT_OPCODE;
2282     }
2283     BEGIN_OPCODE(op_switch_string) {
2284         /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
2285
2286            Performs a sparse hashmap based switch on the value in the scrutinee
2287            register, using the tableIndex-th string switch jump table.  If the 
2288            scrutinee value is a string that exists as a key in the referenced 
2289            jump table, then the value associated with the string is used as the 
2290            jump offset, otherwise defaultOffset is used.
2291          */
2292         int tableIndex = (++vPC)->u.operand;
2293         int defaultOffset = (++vPC)->u.operand;
2294         JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2295         if (scrutinee->type() != StringType)
2296             vPC += defaultOffset;
2297         else 
2298             vPC += offsetForStringSwitch(codeBlock->stringSwitchJumpTables[tableIndex], scrutinee, defaultOffset);
2299         NEXT_OPCODE;
2300     }
2301     BEGIN_OPCODE(op_new_func) {
2302         /* new_func dst(r) func(f)
2303
2304            Constructs a new Function instance from function func and
2305            the current scope chain using the original Function
2306            constructor, using the rules for function declarations, and
2307            puts the result in register dst.
2308         */
2309         int dst = (++vPC)->u.operand;
2310         int func = (++vPC)->u.operand;
2311
2312         r[dst] = codeBlock->functions[func]->makeFunction(exec, scopeChain);
2313
2314         ++vPC;
2315         NEXT_OPCODE;
2316     }
2317     BEGIN_OPCODE(op_new_func_exp) {
2318         /* new_func_exp dst(r) func(f)
2319
2320            Constructs a new Function instance from function func and
2321            the current scope chain using the original Function
2322            constructor, using the rules for function expressions, and
2323            puts the result in register dst.
2324         */
2325         int dst = (++vPC)->u.operand;
2326         int func = (++vPC)->u.operand;
2327
2328         r[dst] = codeBlock->functionExpressions[func]->makeFunction(exec, scopeChain);
2329
2330         ++vPC;
2331         NEXT_OPCODE;
2332     }
2333     BEGIN_OPCODE(op_call_eval) {
2334         /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2335
2336            Call a function named "eval" with no explicit "this" value
2337            (which may therefore be the eval operator). If register
2338            thisVal is the global object, and register func contains
2339            that global object's original global eval function, then
2340            perform the eval operator in local scope (interpreting
2341            the argument registers as for the "call"
2342            opcode). Otherwise, act exactly as the "call" opcode would.
2343          */
2344
2345         int dst = (++vPC)->u.operand;
2346         int func = (++vPC)->u.operand;
2347         int thisVal = (++vPC)->u.operand;
2348         int firstArg = (++vPC)->u.operand;
2349         int argCount = (++vPC)->u.operand;
2350
2351         JSValue* funcVal = r[func].jsValue(exec);
2352         JSValue* baseVal = r[thisVal].jsValue(exec);
2353
2354         if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
2355             JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
2356             JSValue* result = callEval(exec, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
2357             if (exceptionValue)
2358                 goto vm_throw;
2359
2360             r[dst] = result;
2361
2362             ++vPC;
2363             NEXT_OPCODE;
2364         }
2365
2366         // We didn't find the blessed version of eval, so reset vPC and process
2367         // this instruction as a normal function call, supplying the proper 'this'
2368         // value.
2369         vPC -= 5;
2370         r[thisVal] = baseVal->toThisObject(exec);
2371
2372 #if HAVE(COMPUTED_GOTO)
2373         // Hack around gcc performance quirk by performing an indirect goto
2374         // in order to set the vPC -- attempting to do so directly results in a
2375         // significant regression.
2376         goto *op_call_indirect; // indirect goto -> op_call
2377 #endif
2378         // fall through to op_call
2379     }
2380     BEGIN_OPCODE(op_call) {
2381         /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2382
2383            Perform a function call. Specifically, call register func
2384            with a "this" value of register thisVal, and put the result
2385            in register dst.
2386
2387            The arguments start at register firstArg and go up to
2388            argCount, but the "this" value is considered an implicit
2389            first argument, so the argCount should be one greater than
2390            the number of explicit arguments passed, and the register
2391            after firstArg should contain the actual first
2392            argument. This opcode will copy from the thisVal register
2393            to the firstArg register, unless the register index of
2394            thisVal is the special missing this object marker, which is
2395            2^31-1; in that case, the global object will be used as the
2396            "this" value.
2397
2398            If func is a native code function, then this opcode calls
2399            it and returns the value immediately. 
2400
2401            But if it is a JS function, then the current scope chain
2402            and code block is set to the function's, and we slide the
2403            register window so that the arguments would form the first
2404            few local registers of the called function's register
2405            window. In addition, a call frame header is written
2406            immediately before the arguments; see the call frame
2407            documentation for an explanation of how many registers a
2408            call frame takes and what they contain. That many registers
2409            before the firstArg register will be overwritten by the
2410            call. In addition, any registers higher than firstArg +
2411            argCount may be overwritten. Once this setup is complete,
2412            execution continues from the called function's first
2413            argument, and does not return until a "ret" opcode is
2414            encountered.
2415          */
2416
2417         int dst = (++vPC)->u.operand;
2418         int func = (++vPC)->u.operand;
2419         int thisVal = (++vPC)->u.operand;
2420         int firstArg = (++vPC)->u.operand;
2421         int argCount = (++vPC)->u.operand;
2422
2423         JSValue* v = r[func].jsValue(exec);
2424
2425         CallData callData;
2426         CallType callType = v->getCallData(callData);
2427
2428         if (callType == CallTypeJS) {
2429             if (*enabledProfilerReference)
2430                 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2431
2432             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
2433             FunctionBodyNode* functionBodyNode = callData.js.functionBody;
2434             CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
2435
2436             r[firstArg] = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2437
2438             Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
2439             initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 0, v);
2440             exec->m_callFrame = callFrame;
2441
2442             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
2443             if (UNLIKELY(exceptionValue != 0))
2444                 goto vm_throw;
2445
2446             codeBlock = newCodeBlock;
2447             setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
2448             vPC = codeBlock->instructions.begin();
2449
2450 #if DUMP_OPCODE_STATS
2451             OpcodeStats::resetLastInstruction();
2452 #endif
2453             
2454             NEXT_OPCODE;
2455         }
2456
2457         if (callType == CallTypeHost) {
2458             if (*enabledProfilerReference)
2459                 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2460
2461             JSValue* thisValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2462             ArgList args(r + firstArg + 1, argCount - 1);
2463
2464             MACHINE_SAMPLING_callingHostFunction();
2465
2466             JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
2467             VM_CHECK_EXCEPTION();
2468
2469             r[dst] = returnValue;
2470
2471             if (*enabledProfilerReference)
2472                 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
2473
2474             ++vPC;
2475             NEXT_OPCODE;
2476         }
2477
2478         ASSERT(callType == CallTypeNone);
2479
2480         exceptionValue = createNotAFunctionError(exec, v, vPC, codeBlock);
2481         goto vm_throw;
2482     }
2483     BEGIN_OPCODE(op_ret) {
2484         /* ret result(r)
2485            
2486            Return register result as the return value of the current
2487            function call, writing it into the caller's expected return
2488            value register. In addition, unwind one call frame and
2489            restore the scope chain, code block instruction pointer and
2490            register base to those of the calling function.
2491         */
2492            
2493         int result = (++vPC)->u.operand;
2494
2495         Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2496         if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
2497             ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
2498             ASSERT(activation->isActivationObject());
2499             activation->copyRegisters();
2500         }
2501
2502         if (*enabledProfilerReference)
2503             (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
2504
2505         if (codeBlock->needsFullScopeChain)
2506             scopeChain->deref();
2507
2508         JSValue* returnValue = r[result].jsValue(exec);
2509         if (callFrame[RegisterFile::CalledAsConstructor].i() && !returnValue->isObject()) {
2510             JSValue* thisObject = callFrame[RegisterFile::CallFrameHeaderSize].jsValue(exec);
2511             returnValue = thisObject;
2512         }
2513
2514         codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
2515         if (!codeBlock)
2516             return returnValue;
2517
2518         vPC = callFrame[RegisterFile::ReturnVPC].vPC();
2519         setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
2520         r = callFrame[RegisterFile::CallerRegisters].r();
2521         exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2522         int dst = callFrame[RegisterFile::ReturnValueRegister].i();
2523         r[dst] = returnValue;
2524
2525         NEXT_OPCODE;
2526     }
2527     BEGIN_OPCODE(op_construct) {
2528         /* construct dst(r) constr(r) firstArg(r) argCount(n)
2529
2530            Invoke register "constr" as a constructor. For JS
2531            functions, the calling convention is exactly as for the
2532            "call" opcode, except that the "this" value is a newly
2533            created Object. For native constructors, a null "this"
2534            value is passed. In either case, the firstArg and argCount
2535            registers are interpreted as for the "call" opcode.
2536         */
2537
2538         int dst = (++vPC)->u.operand;
2539         int constr = (++vPC)->u.operand;
2540         int firstArg = (++vPC)->u.operand;
2541         int argCount = (++vPC)->u.operand;
2542
2543         JSValue* constrVal = r[constr].jsValue(exec);
2544
2545         ConstructData constructData;
2546         ConstructType constructType = constrVal->getConstructData(constructData);
2547
2548         // Removing this line of code causes a measurable regression on squirrelfish.
2549         JSObject* constructor = static_cast<JSObject*>(constrVal);
2550
2551         if (constructType == ConstructTypeJS) {
2552             if (*enabledProfilerReference)
2553                 (*enabledProfilerReference)->willExecute(exec, constructor);
2554
2555             JSObject* prototype;
2556             JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
2557             if (p->isObject())
2558                 prototype = static_cast<JSObject*>(p);
2559             else
2560                 prototype = scopeChain->globalObject()->objectPrototype();
2561             JSObject* newObject = new (exec) JSObject(prototype);
2562
2563             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
2564             FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
2565             CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
2566
2567             r[firstArg] = newObject; // "this" value
2568
2569             Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
2570             initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 1, constructor);
2571             exec->m_callFrame = callFrame;
2572
2573             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
2574             if (exceptionValue)
2575                 goto vm_throw;
2576
2577             codeBlock = newCodeBlock;
2578             setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
2579             vPC = codeBlock->instructions.begin();
2580
2581             NEXT_OPCODE;
2582         }
2583
2584         if (constructType == ConstructTypeHost) {
2585             if (*enabledProfilerReference)
2586                 (*enabledProfilerReference)->willExecute(exec, constructor);
2587
2588             ArgList args(r + firstArg + 1, argCount - 1);
2589
2590             MACHINE_SAMPLING_callingHostFunction();
2591
2592             JSValue* returnValue = constructData.native.function(exec, constructor, args);
2593
2594             VM_CHECK_EXCEPTION();
2595             r[dst] = returnValue;
2596
2597             if (*enabledProfilerReference)
2598                 (*enabledProfilerReference)->didExecute(exec, constructor);
2599
2600             ++vPC;
2601             NEXT_OPCODE;
2602         }
2603
2604         ASSERT(constructType == ConstructTypeNone);
2605
2606         exceptionValue = createNotAConstructorError(exec, constrVal, vPC, codeBlock);
2607         goto vm_throw;
2608     }
2609     BEGIN_OPCODE(op_push_scope) {
2610         /* push_scope scope(r)
2611
2612            Converts register scope to object, and pushes it onto the top
2613            of the current scope chain.
2614         */
2615         int scope = (++vPC)->u.operand;
2616         JSValue* v = r[scope].jsValue(exec);
2617         JSObject* o = v->toObject(exec);
2618         VM_CHECK_EXCEPTION();
2619
2620         setScopeChain(exec, scopeChain, scopeChain->push(o));
2621
2622         ++vPC;
2623         NEXT_OPCODE;
2624     }
2625     BEGIN_OPCODE(op_pop_scope) {
2626         /* pop_scope
2627
2628            Removes the top item from the current scope chain.
2629         */
2630         setScopeChain(exec, scopeChain, scopeChain->pop());
2631
2632         ++vPC;
2633         NEXT_OPCODE;
2634     }
2635     BEGIN_OPCODE(op_get_pnames) {
2636         /* get_pnames dst(r) base(r)
2637
2638            Creates a property name list for register base and puts it
2639            in register dst. This is not a true JavaScript value, just
2640            a synthetic value used to keep the iteration state in a
2641            register.
2642         */
2643         int dst = (++vPC)->u.operand;
2644         int base = (++vPC)->u.operand;
2645
2646         r[dst] = JSPropertyNameIterator::create(exec, r[base].jsValue(exec));
2647         ++vPC;
2648         NEXT_OPCODE;
2649     }
2650     BEGIN_OPCODE(op_next_pname) {
2651         /* next_pname dst(r) iter(r) target(offset)
2652
2653            Tries to copies the next name from property name list in
2654            register iter. If there are names left, then copies one to
2655            register dst, and jumps to offset target. If there are none
2656            left, invalidates the iterator and continues to the next
2657            instruction.
2658         */
2659         int dst = (++vPC)->u.operand;
2660         int iter = (++vPC)->u.operand;
2661         int target = (++vPC)->u.operand;
2662
2663         JSPropertyNameIterator* it = r[iter].jsPropertyNameIterator();
2664         if (JSValue* temp = it->next(exec)) {
2665             CHECK_FOR_TIMEOUT();
2666             r[dst] = temp;
2667             vPC += target;
2668             NEXT_OPCODE;
2669         }
2670         it->invalidate();
2671
2672         ++vPC;
2673         NEXT_OPCODE;
2674     }
2675     BEGIN_OPCODE(op_jmp_scopes) {
2676         /* jmp_scopes count(n) target(offset)
2677
2678            Removes the a number of items from the current scope chain
2679            specified by immediate number count, then jumps to offset
2680            target.
2681         */
2682         int count = (++vPC)->u.operand;
2683         int target = (++vPC)->u.operand;
2684
2685         ScopeChainNode* tmp = scopeChain;
2686         while (count--)
2687             tmp = tmp->pop();
2688         setScopeChain(exec, scopeChain, tmp);
2689
2690         vPC += target;
2691         NEXT_OPCODE;
2692     }
2693 #if HAVE(COMPUTED_GOTO)
2694     // Appease GCC
2695     goto *(&&skip_new_scope);
2696 #endif
2697     BEGIN_OPCODE(op_push_new_scope) {
2698         /* new_scope dst(r) property(id) value(r)
2699          
2700            Constructs a new StaticScopeObject with property set to value.  That scope
2701            object is then pushed onto the ScopeChain.  The scope object is then stored
2702            in dst for GC.
2703          */
2704         setScopeChain(exec, scopeChain, createExceptionScope(exec, codeBlock, vPC, r, scopeChain));
2705         vPC += 4;
2706         NEXT_OPCODE;
2707     }
2708 #if HAVE(COMPUTED_GOTO)
2709     skip_new_scope:
2710 #endif
2711     BEGIN_OPCODE(op_catch) {
2712         /* catch ex(r)
2713
2714            Retrieves the VMs current exception and puts it in register
2715            ex. This is only valid after an exception has been raised,
2716            and usually forms the beginning of an exception handler.
2717         */
2718         ASSERT(exceptionValue);
2719         ASSERT(!exec->hadException());
2720         int ex = (++vPC)->u.operand;
2721         r[ex] = exceptionValue;
2722         exceptionValue = 0;
2723
2724         ++vPC;
2725         NEXT_OPCODE;
2726     }
2727     BEGIN_OPCODE(op_throw) {
2728         /* throw ex(r)
2729
2730            Throws register ex as an exception. This involves three
2731            steps: first, it is set as the current exception in the
2732            VM's internal state, then the stack is unwound until an
2733            exception handler or a native code boundary is found, and
2734            then control resumes at the exception handler if any or
2735            else the script returns control to the nearest native caller.
2736         */
2737
2738         int ex = (++vPC)->u.operand;
2739         exceptionValue = r[ex].jsValue(exec);
2740
2741         handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, scopeChain, r, true);
2742         if (!handlerVPC) {
2743             *exception = exceptionValue;
2744             return jsNull();
2745         }
2746
2747 #if HAVE(COMPUTED_GOTO)
2748         // Hack around gcc performance quirk by performing an indirect goto
2749         // in order to set the vPC -- attempting to do so directly results in a
2750         // significant regression.
2751         goto *op_throw_end_indirect; // indirect goto -> op_throw_end
2752     }
2753     op_throw_end: {
2754 #endif
2755
2756         vPC = handlerVPC;
2757         NEXT_OPCODE;
2758     }
2759     BEGIN_OPCODE(op_unexpected_load) {
2760         /* unexpected_load load dst(r) src(k)
2761
2762            Copies constant src to register dst.
2763         */
2764         int dst = (++vPC)->u.operand;
2765         int src = (++vPC)->u.operand;
2766         r[dst] = codeBlock->unexpectedConstants[src];
2767
2768         ++vPC;
2769         NEXT_OPCODE;
2770     }
2771     BEGIN_OPCODE(op_new_error) {
2772         /* new_error dst(r) type(n) message(k)
2773
2774            Constructs a new Error instance using the original
2775            constructor, using immediate number n as the type and
2776            constant message as the message string. The result is
2777            written to register dst.
2778         */
2779         int dst = (++vPC)->u.operand;
2780         int type = (++vPC)->u.operand;
2781         int message = (++vPC)->u.operand;
2782
2783         r[dst] = Error::create(exec, (ErrorType)type, codeBlock->unexpectedConstants[message]->toString(exec), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
2784
2785         ++vPC;
2786         NEXT_OPCODE;
2787     }
2788     BEGIN_OPCODE(op_end) {
2789         /* end result(r)
2790            
2791            Return register result as the value of a global or eval
2792            program. Return control to the calling native code.
2793         */
2794
2795         if (codeBlock->needsFullScopeChain) {
2796             ASSERT(scopeChain->refCount > 1);
2797             scopeChain->deref();
2798         }
2799         int result = (++vPC)->u.operand;
2800         return r[result].jsValue(exec);
2801     }
2802     BEGIN_OPCODE(op_put_getter) {
2803         /* put_getter base(r) property(id) function(r)
2804
2805            Sets register function on register base as the getter named
2806            by identifier property. Base and function are assumed to be
2807            objects as this op should only be used for getters defined
2808            in object literal form.
2809
2810            Unlike many opcodes, this one does not write any output to
2811            the register file.
2812         */
2813         int base = (++vPC)->u.operand;
2814         int property = (++vPC)->u.operand;
2815         int function = (++vPC)->u.operand;
2816
2817         ASSERT(r[base].jsValue(exec)->isObject());
2818         JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
2819         Identifier& ident = codeBlock->identifiers[property];
2820         ASSERT(r[function].jsValue(exec)->isObject());
2821         baseObj->defineGetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
2822
2823         ++vPC;
2824         NEXT_OPCODE;
2825     }
2826     BEGIN_OPCODE(op_put_setter) {
2827         /* put_setter base(r) property(id) function(r)
2828
2829            Sets register function on register base as the setter named
2830            by identifier property. Base and function are assumed to be
2831            objects as this op should only be used for setters defined
2832            in object literal form.
2833
2834            Unlike many opcodes, this one does not write any output to
2835            the register file.
2836         */
2837         int base = (++vPC)->u.operand;
2838         int property = (++vPC)->u.operand;
2839         int function = (++vPC)->u.operand;
2840
2841         ASSERT(r[base].jsValue(exec)->isObject());
2842         JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
2843         Identifier& ident = codeBlock->identifiers[property];
2844         ASSERT(r[function].jsValue(exec)->isObject());
2845         baseObj->defineSetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
2846
2847         ++vPC;
2848         NEXT_OPCODE;
2849     }
2850     BEGIN_OPCODE(op_jsr) {
2851         /* jsr retAddrDst(r) target(offset)
2852
2853            Places the address of the next instruction into the retAddrDst
2854            register and jumps to offset target from the current instruction.
2855         */
2856         int retAddrDst = (++vPC)->u.operand;
2857         int target = (++vPC)->u.operand;
2858         r[retAddrDst] = vPC + 1;
2859
2860         vPC += target;
2861         NEXT_OPCODE;
2862     }
2863     BEGIN_OPCODE(op_sret) {
2864         /* sret retAddrSrc(r)
2865
2866          Jumps to the address stored in the retAddrSrc register. This
2867          differs from op_jmp because the target address is stored in a
2868          register, not as an immediate.
2869         */
2870         int retAddrSrc = (++vPC)->u.operand;
2871         vPC = r[retAddrSrc].vPC();
2872         NEXT_OPCODE;
2873     }
2874     BEGIN_OPCODE(op_debug) {
2875         /* debug debugHookID(n) firstLine(n) lastLine(n)
2876
2877          Notifies the debugger of the current state of execution. This opcode
2878          is only generated while the debugger is attached.
2879         */
2880
2881         debug(exec, vPC, codeBlock, scopeChain, r);
2882
2883         vPC += 4;
2884         NEXT_OPCODE;
2885     }
2886     vm_throw: {
2887         exec->clearException();
2888         if (!tickCount) {
2889             // The exceptionValue is a lie! (GCC produces bad code for reasons I 
2890             // cannot fathom if we don't assign to the exceptionValue before branching)
2891             exceptionValue = createInterruptedExecutionException(exec);
2892         }
2893         handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, scopeChain, r, false);
2894         if (!handlerVPC) {
2895             *exception = exceptionValue;
2896             return jsNull();
2897         }
2898         vPC = handlerVPC;
2899         NEXT_OPCODE;
2900     }
2901     }
2902     #undef NEXT_OPCODE
2903     #undef BEGIN_OPCODE
2904     #undef VM_CHECK_EXCEPTION
2905 }
2906
2907 JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
2908 {
2909     Register* callFrame = this->callFrame(exec, function);
2910     if (!callFrame)
2911         return jsNull();
2912
2913     JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec));
2914     if (!activation) {
2915         CodeBlock* codeBlock = &function->m_body->generatedByteCode();
2916         activation = new (exec) JSActivation(function->m_body, callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals);
2917         callFrame[RegisterFile::OptionalCalleeActivation] = activation;
2918     }
2919
2920     return activation->get(exec, exec->propertyNames().arguments);
2921 }
2922
2923 JSValue* Machine::retrieveCaller(ExecState* exec, JSFunction* function) const
2924 {
2925     Register* callFrame = this->callFrame(exec, function);
2926     if (!callFrame)
2927         return jsNull();
2928
2929     CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
2930     if (!callerCodeBlock)
2931         return jsNull();
2932
2933     Register* callerCallFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2934     if (JSValue* caller = callerCallFrame[RegisterFile::Callee].jsValue(exec))
2935         return caller;
2936
2937     return jsNull();
2938 }
2939
2940 Register* Machine::callFrame(ExecState* exec, JSFunction* function) const
2941 {
2942     Register* callFrame = exec->m_callFrame;
2943
2944     while (1) {
2945         while (!callFrame) {
2946             exec = exec->m_prev;
2947             if (!exec)
2948                 return 0;
2949             callFrame = exec->m_callFrame;
2950         }
2951
2952         if (callFrame[RegisterFile::Callee].jsValue(exec) == function)
2953             return callFrame;
2954
2955         CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
2956         if (!callerCodeBlock) {
2957             callFrame = 0;
2958             continue;
2959         }
2960         
2961         callFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2962     }
2963 }
2964
2965 void Machine::getArgumentsData(Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
2966 {
2967     function = static_cast<JSFunction*>(callFrame[RegisterFile::Callee].getJSValue());
2968     ASSERT(function->inherits(&JSFunction::info));
2969
2970     argv = callFrame[RegisterFile::CallerRegisters].r() + callFrame[RegisterFile::ArgumentStartRegister].i() + 1; //  + 1 to skip "this"
2971     argc = callFrame[RegisterFile::ArgumentCount].i() - 1; // - 1 to skip "this"
2972 }
2973
2974 } // namespace KJS