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