<rdar://problem/5951561> Turn on JavaScript Profiler
[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 "JSActivation.h"
38 #include "JSLock.h"
39 #include "JSPropertyNameIterator.h"
40 #include "Parser.h"
41 #include "Profiler.h"
42 #include "Register.h"
43 #include "array_object.h"
44 #include "debugger.h"
45 #include "function.h"
46 #include "internal.h"
47 #include "object_object.h"
48 #include "operations.h"
49 #include "operations.h"
50 #include "regexp_object.h"
51
52 #if COMPILER(GCC)
53 #define UNLIKELY(x) \
54   __builtin_expect ((x), 0)
55 #else
56 #define UNLIKELY(x) x
57 #endif
58
59 namespace KJS {
60
61 #if HAVE(COMPUTED_GOTO)
62 static void* op_throw_end_indirect;
63 static void* op_call_indirect;
64 #endif
65
66 // Retrieves the offset of a calling function within the current register file.
67 bool getCallerFunctionOffset(Register** registerBase, int callOffset, int& callerOffset)
68 {
69     Register* callFrame = (*registerBase) + callOffset;
70
71     CodeBlock* callerCodeBlock = callFrame[Machine::CallerCodeBlock].u.codeBlock;
72     if (!callerCodeBlock) // test for top frame of re-entrant function call
73         return false;
74
75     callerOffset = callFrame[Machine::CallerRegisterOffset].u.i - callerCodeBlock->numLocals - Machine::CallFrameHeaderSize;
76     if (callerOffset < 0) // test for global frame
77         return false;
78
79     Register* callerCallFrame = (*registerBase) + callerOffset;
80     if (!callerCallFrame[Machine::CallerCodeBlock].u.codeBlock) // test for eval frame
81         return false;
82
83     return true;
84 }
85
86 // Returns the depth of the scope chain within a given call frame.
87 static int depth(ScopeChain& sc)
88 {
89     int scopeDepth = 0;
90     ScopeChainIterator iter = sc.begin(); 
91     ScopeChainIterator end = sc.end(); 
92     while (!(*iter)->isVariableObject()) {
93         ++iter;
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 StringImp*>(p1)->value() < static_cast<const StringImp*>(p2)->value();
115 }
116
117 static inline bool jsLessEq(ExecState* exec, JSValue* v1, JSValue* v2)
118 {
119     double n1;
120     double n2;
121     JSValue* p1;
122     JSValue* p2;
123     bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
124     bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
125
126     if (wasNotString1 | wasNotString2)
127         return n1 <= n2;
128
129     return !(static_cast<const StringImp*>(p2)->value() < static_cast<const StringImp*>(p1)->value());
130 }
131
132 static JSValue* jsAddSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
133 {
134     // exception for the Date exception in defaultValue()
135     JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
136     JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
137
138     if (p1->isString() || p2->isString()) {
139         UString value = p1->toString(exec) + p2->toString(exec);
140         if (value.isNull())
141             return throwOutOfMemoryError(exec);
142         return jsString(value);
143     }
144
145     return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
146 }
147
148 // Fast-path choices here are based on frequency data from SunSpider:
149 //    <times> Add case: <t1> <t2>
150 //    ---------------------------
151 //    5627160 Add case: 1 1
152 //    247427  Add case: 5 5
153 //    20901   Add case: 5 6
154 //    13978   Add case: 5 1
155 //    4000    Add case: 1 5
156 //    1       Add case: 3 5
157
158 static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
159 {
160     JSType t1 = v1->type();
161     JSType t2 = v2->type();
162     const unsigned bothTypes = (t1 << 3) | t2;
163
164     if (bothTypes == ((NumberType << 3) | NumberType))
165         return jsNumber(v1->uncheckedGetNumber() + v2->uncheckedGetNumber());
166     if (bothTypes == ((StringType << 3) | StringType)) {
167         UString value = static_cast<StringImp*>(v1)->value() + static_cast<StringImp*>(v2)->value();
168         if (value.isNull())
169             return throwOutOfMemoryError(exec);
170         return jsString(value);
171     }
172
173     // All other cases are pretty uncommon
174     return jsAddSlowCase(exec, v1, v2);
175 }
176
177 static JSValue* jsTypeStringForValue(JSValue* v)
178 {
179     switch (v->type()) {
180         case UndefinedType:
181             return jsString("undefined");
182         case NullType:
183             return jsString("object");
184         case BooleanType:
185             return jsString("boolean");
186         case NumberType:
187             return jsString("number");
188         case StringType:
189             return jsString("string");
190         default:
191             if (v->isObject()) {
192                 // Return "undefined" for objects that should be treated
193                 // as null when doing comparisons.
194                 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
195                     return jsString("undefined");
196                 else if (static_cast<JSObject*>(v)->implementsCall())
197                     return jsString("function");
198             }
199
200             return jsString("object");
201     }
202 }
203
204 static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
205 {
206     int dst = (vPC + 1)->u.operand;
207     int property = (vPC + 2)->u.operand;
208
209     ScopeChainIterator iter = scopeChain->begin();
210     ScopeChainIterator end = scopeChain->end();
211     ASSERT(iter != end);
212
213     PropertySlot slot;
214     Identifier& ident = codeBlock->identifiers[property];
215     do {
216         JSObject* o = *iter;
217         if (o->getPropertySlot(exec, ident, slot)) {
218             JSValue* result = slot.getValue(exec, o, ident);
219             exceptionValue = exec->exception();
220             if (exceptionValue)
221                 return false;
222             r[dst].u.jsValue = result;
223             return true;
224         }
225     } while (++iter != end);
226     exceptionValue = createUndefinedVariableError(exec, ident);
227     return false;
228 }
229     
230 static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
231 {
232     int dst = (vPC + 1)->u.operand;
233     int property = (vPC + 2)->u.operand;
234     int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain;
235     
236     ScopeChainIterator iter = scopeChain->begin();
237     ScopeChainIterator end = scopeChain->end();
238     ASSERT(iter != end);
239     while (skip--) {
240         ++iter;
241         ASSERT(iter != end);
242     }
243     PropertySlot slot;
244     Identifier& ident = codeBlock->identifiers[property];
245     do {
246         JSObject* o = *iter;
247         if (o->getPropertySlot(exec, ident, slot)) {
248             JSValue* result = slot.getValue(exec, o, ident);
249             exceptionValue = exec->exception();
250             if (exceptionValue)
251                 return false;
252             r[dst].u.jsValue = result;
253             return true;
254         }
255     } while (++iter != end);
256     exceptionValue = createUndefinedVariableError(exec, ident);
257     return false;
258 }
259
260 static void NEVER_INLINE resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
261 {
262     int dst = (vPC + 1)->u.operand;
263     int property = (vPC + 2)->u.operand;
264
265     ScopeChainIterator iter = scopeChain->begin();
266     ScopeChainIterator next = iter;
267     ++next;
268     ScopeChainIterator end = scopeChain->end();
269     ASSERT(iter != end);
270
271     PropertySlot slot;
272     Identifier& ident = codeBlock->identifiers[property];
273     JSObject* base;
274     while (true) {
275         base = *iter;
276         if (next == end || base->getPropertySlot(exec, ident, slot)) {
277             r[dst].u.jsValue = base;
278             return;
279         }
280         iter = next;
281         ++next;
282     }
283 }
284
285 static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
286 {
287     int baseDst = (vPC + 1)->u.operand;
288     int propDst = (vPC + 2)->u.operand;
289     int property = (vPC + 3)->u.operand;
290     
291     ScopeChainIterator iter = scopeChain->begin();
292     ScopeChainIterator end = scopeChain->end();
293     
294     // FIXME: add scopeDepthIsZero optimization
295     
296     ASSERT(iter != end);
297     
298     PropertySlot slot;
299     Identifier& ident = codeBlock->identifiers[property];
300     JSObject* base;
301     do {
302         base = *iter;
303         if (base->getPropertySlot(exec, ident, slot)) {
304             JSValue* result = slot.getValue(exec, base, ident);  
305             exceptionValue = exec->exception();
306             if (exceptionValue)
307                 return false;
308             r[propDst].u.jsValue = result;   
309             r[baseDst].u.jsValue = base;
310             return true;
311         }
312         ++iter;
313     } while (iter != end);
314     
315     exceptionValue = createUndefinedVariableError(exec, ident);
316     return false;
317 }
318
319 static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
320 {
321     int baseDst = (vPC + 1)->u.operand;
322     int funcDst = (vPC + 2)->u.operand;
323     int property = (vPC + 3)->u.operand;
324
325     ScopeChainIterator iter = scopeChain->begin();
326     ScopeChainIterator end = scopeChain->end();
327     
328     // FIXME: add scopeDepthIsZero optimization
329     
330     ASSERT(iter != end);
331     
332     PropertySlot slot;
333     Identifier& ident = codeBlock->identifiers[property];
334     JSObject* base;
335     do {
336         base = *iter;
337         if (base->getPropertySlot(exec, ident, slot)) {            
338             // ECMA 11.2.3 says that if we hit an activation the this value should be null.
339             // However, section 10.2.3 says that in the case where the value provided
340             // by the caller is null, the global object should be used. It also says
341             // that the section does not apply to internal functions, but for simplicity
342             // of implementation we use the global object anyway here. This guarantees
343             // that in host objects you always get a valid object for this.
344             // We also handle wrapper substitution for the global object at the same time.
345             JSObject* thisObj = base->toThisObject(exec);
346             JSValue* result = slot.getValue(exec, base, ident);
347             exceptionValue = exec->exception();
348             if (exceptionValue)
349                 return false;
350             
351             r[baseDst].u.jsValue = thisObj;
352             r[funcDst].u.jsValue = result;
353             return true;
354         }
355         ++iter;
356     } while (iter != end);
357
358     exceptionValue = createUndefinedVariableError(exec, ident);
359     return false;
360 }
361
362 ALWAYS_INLINE void initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, int registerOffset, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function)
363 {
364     callFrame[Machine::CallerCodeBlock].u.codeBlock = codeBlock;
365     callFrame[Machine::ReturnVPC].u.vPC = vPC + 1;
366     callFrame[Machine::CallerScopeChain].u.scopeChain = scopeChain;
367     callFrame[Machine::CallerRegisterOffset].u.i = registerOffset;
368     callFrame[Machine::ReturnValueRegister].u.i = returnValueRegister;
369     callFrame[Machine::ArgumentStartRegister].u.i = argv; // original argument vector (for the sake of the "arguments" object)
370     callFrame[Machine::ArgumentCount].u.i = argc; // original argument count (for the sake of the "arguments" object)
371     callFrame[Machine::CalledAsConstructor].u.i = calledAsConstructor;
372     callFrame[Machine::Callee].u.jsValue = function;
373     callFrame[Machine::OptionalCalleeActivation].u.jsValue = 0;
374 }
375
376 ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register** registerBase, int registerOffset, int argv, int argc, JSValue*& exceptionValue)
377 {
378     Register* r = 0;
379     int oldOffset = registerOffset;
380     registerOffset += argv + newCodeBlock->numLocals;
381     size_t size = registerOffset + newCodeBlock->numTemporaries;
382
383     if (argc == newCodeBlock->numParameters) { // correct number of arguments
384         if (!registerFile->grow(size)) {
385             exceptionValue = createStackOverflowError(exec);
386             return *registerBase + oldOffset;
387         }
388         r = (*registerBase) + registerOffset;
389     } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
390         if (!registerFile->grow(size)) {
391             exceptionValue = createStackOverflowError(exec);
392             return *registerBase + oldOffset;
393         }
394         r = (*registerBase) + registerOffset;
395         
396         int omittedArgCount = newCodeBlock->numParameters - argc;
397         Register* endOfParams = r - newCodeBlock->numVars;
398         for (Register* it = endOfParams - omittedArgCount; it != endOfParams; ++it)
399             (*it).u.jsValue = jsUndefined();
400     } else { // too many arguments -- copy return info and expected arguments, leaving the extra arguments behind
401         int shift = argc + Machine::CallFrameHeaderSize;
402         registerOffset += shift;
403         size += shift;
404
405         if (!registerFile->grow(size)) {
406             exceptionValue = createStackOverflowError(exec);
407             return *registerBase + oldOffset;
408         }
409         r = (*registerBase) + registerOffset;
410         
411         Register* it = r - newCodeBlock->numLocals - Machine::CallFrameHeaderSize - shift;
412         Register* end = it + Machine::CallFrameHeaderSize + newCodeBlock->numParameters;
413         for ( ; it != end; ++it)
414             *(it + shift) = *it;
415     }
416
417     return r;
418 }
419
420 ALWAYS_INLINE ScopeChainNode* scopeChainForCall(FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register** registerBase, Register* r)
421 {
422     if (newCodeBlock->needsFullScopeChain) {
423         JSActivation* activation = new JSActivation(functionBodyNode, registerBase, r - (*registerBase));
424         r[Machine::OptionalCalleeActivation - Machine::CallFrameHeaderSize - newCodeBlock->numLocals].u.jsValue = activation;
425
426         return callDataScopeChain->copy()->push(activation);
427     }
428
429     return callDataScopeChain;
430 }
431
432 static NEVER_INLINE bool isNotObject(ExecState* exec, const Instruction*, CodeBlock*, JSValue* value, JSValue*& exceptionData)
433 {
434     if (value->isObject())
435         return false;
436     exceptionData = createNotAnObjectError(exec, value, 0);
437     return true;
438 }
439
440 static NEVER_INLINE JSValue* callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
441 {
442 #if JAVASCRIPT_PROFILING
443     Profiler** profiler = Profiler::enabledProfilerReference();
444     JSObject* evalFunction = scopeChain->globalObject()->evalFunction();
445     if (*profiler)
446         (*profiler)->willExecute(exec, evalFunction);
447 #endif
448
449     JSValue* x = argc >= 2 ? r[argv + 1].u.jsValue : jsUndefined();
450     
451     if (!x->isString())
452         return x;
453     
454     UString s = x->toString(exec);
455     if (exec->hadException()) {
456         exceptionValue = exec->exception();
457         exec->clearException();
458         return 0;
459     }
460
461     int sourceId;
462     int errLine;
463     UString errMsg;
464     RefPtr<EvalNode> evalNode = parser().parse<EvalNode>(exec, UString(), 0, UStringSourceProvider::create(s), &sourceId, &errLine, &errMsg);
465     
466     if (!evalNode) {
467         exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
468         return 0;
469     }
470
471 #if JAVASCRIPT_PROFILING
472     JSValue* result = machine().execute(evalNode.get(), exec, thisObj, registerFile, r - (*registerFile->basePointer()) + argv + argc, scopeChain, &exceptionValue);
473
474     if ((*profiler))
475         (*profiler)->didExecute(exec, evalFunction);
476
477     return result;
478 #else
479     return machine().execute(evalNode.get(), exec, thisObj, registerFile, r - (*registerFile->basePointer()) + argv + argc, scopeChain, &exceptionValue);
480 #endif
481 }
482
483 Machine& machine()
484 {
485     ASSERT(JSLock::currentThreadIsHoldingLock());
486     static Machine machine;
487     return machine;
488 }
489
490 Machine::Machine()
491     : m_reentryDepth(0)
492 {
493     privateExecute(InitializeAndReturn);
494 }
495
496 void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
497 {
498     ScopeChain sc(scopeChain);
499     JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(sc.bottom());
500     codeBlock->dump(globalObject->globalExec());
501     dumpRegisters(codeBlock, registerFile, r);
502 }
503
504 void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFile, const Register* r)
505 {
506     printf("Register frame: \n\n");
507     printf("----------------------------------------\n");
508     printf("     use      |   address  |    value   \n");
509     printf("----------------------------------------\n");
510     
511     const Register* it;
512     const Register* end;
513     
514     if (isGlobalCallFrame(registerFile->basePointer(), r)) {
515         it = r - registerFile->numGlobalSlots();
516         end = r;
517         if (it != end) {
518             do {
519                 printf("[global var]  | %10p | %10p \n", it, (*it).u.jsValue);
520                 ++it;
521             } while (it != end);
522             printf("----------------------------------------\n");
523         }
524     } else {
525         it = r - codeBlock->numLocals - CallFrameHeaderSize;
526         end = it + CallFrameHeaderSize;
527         if (it != end) {
528             do {
529                 printf("[call frame]  | %10p | %10p \n", it, (*it).u.jsValue);
530                 ++it;
531             } while (it != end);
532             printf("----------------------------------------\n");
533         }
534         
535         end = it + codeBlock->numParameters;
536         if (it != end) {
537             do {
538                 printf("[param]       | %10p | %10p \n", it, (*it).u.jsValue);
539                 ++it;
540             } while (it != end);
541             printf("----------------------------------------\n");
542         }
543
544         end = it + codeBlock->numVars;
545         if (it != end) {
546             do {
547                 printf("[var]         | %10p | %10p \n", it, (*it).u.jsValue);
548                 ++it;
549             } while (it != end);
550             printf("----------------------------------------\n");
551         }
552     }
553
554     end = it + codeBlock->numTemporaries;
555     if (it != end) {
556         do {
557             printf("[temp]        | %10p | %10p \n", it, (*it).u.jsValue);
558             ++it;
559         } while (it != end);
560     }
561 }
562
563 bool Machine::isOpcode(Opcode opcode)
564 {
565 #if HAVE(COMPUTED_GOTO)
566     return opcode != HashTraits<Opcode>::emptyValue()
567         && !HashTraits<Opcode>::isDeletedValue(opcode)
568         && m_opcodeIDTable.contains(opcode);
569 #else
570     return opcode >= 0 && opcode <= op_end;
571 #endif
572 }
573
574 NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, Register** registerBase, const Instruction*& vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
575 {
576     CodeBlock* oldCodeBlock = codeBlock;
577
578     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
579         if (!isGlobalCallFrame(registerBase, r)) {
580             DebuggerCallFrame debuggerCallFrame(this, exec->dynamicGlobalObject(), codeBlock, scopeChain, exceptionValue, registerBase, r - *registerBase);
581             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
582         }
583     }
584
585     if (oldCodeBlock->needsFullScopeChain)
586         scopeChain->deref();
587     
588     if (isGlobalCallFrame(registerBase, r))
589         return false;
590
591     Register* callFrame = r - oldCodeBlock->numLocals - CallFrameHeaderSize;
592     
593     codeBlock = callFrame[CallerCodeBlock].u.codeBlock;
594     if (!codeBlock)
595         return false;
596
597     // If this call frame created an activation, tear it off.
598     if (JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue)) {
599         ASSERT(activation->isActivationObject());
600         activation->copyRegisters();
601     }
602
603     k = codeBlock->jsValues.data();
604     scopeChain = callFrame[CallerScopeChain].u.scopeChain;
605     int callerRegisterOffset = callFrame[CallerRegisterOffset].u.i;
606     r = (*registerBase) + callerRegisterOffset;
607     exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - CallFrameHeaderSize;
608     vPC = callFrame[ReturnVPC].u.vPC;
609
610 #if JAVASCRIPT_PROFILING
611     if (Profiler* profiler = *Profiler::enabledProfilerReference())
612         profiler->didExecute(exec, callFrame[Callee].u.jsObject);
613 #endif
614     return true;
615 }
616
617 NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue* exceptionValue, Register** registerBase, const Instruction* vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
618 {
619     // Set up the exception object
620
621     if (exceptionValue->isObject()) {
622         JSObject* exception = static_cast<JSObject*>(exceptionValue);
623         if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
624             exception->put(exec, "line", jsNumber(codeBlock->lineNumberForVPC(vPC)));
625             exception->put(exec, "sourceURL", jsOwnedString(codeBlock->ownerNode->sourceURL()));
626         }
627     }
628
629     if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
630         DebuggerCallFrame debuggerCallFrame(this, exec->dynamicGlobalObject(), codeBlock, scopeChain, exceptionValue, registerBase, r - *registerBase);
631         debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
632     }
633
634     // Calculate an exception handler vPC, unwinding call frames as necessary.
635
636     int scopeDepth;        
637     Instruction* handlerVPC;
638
639     while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth))
640         if (!unwindCallFrame(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r))
641             return 0;
642
643     // Now unwind the scope chain within the exception handler's call frame.
644     
645     ScopeChain sc(scopeChain);
646     int scopeDelta = depth(sc) - scopeDepth;
647     ASSERT(scopeDelta >= 0);
648     while (scopeDelta--)
649         sc.pop();
650     setScopeChain(exec, scopeChain, sc.node());
651
652     return handlerVPC;
653 }
654
655 JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, RegisterFileStack* registerFileStack, JSValue** exception)
656 {
657     if (m_reentryDepth >= MaxReentryDepth) {
658         *exception = createStackOverflowError(exec);
659         return 0;
660     }
661
662     RegisterFile* registerFile = registerFileStack->pushGlobalRegisterFile();
663     ASSERT(registerFile->numGlobalSlots());
664     CodeBlock* codeBlock = &programNode->code(scopeChain, !registerFileStack->inImplicitCall());
665     registerFile->addGlobalSlots(codeBlock->numVars);
666
667     registerFile->uncheckedGrow(codeBlock->numTemporaries);
668     Register* r = (*registerFile->basePointer());
669
670     r[ProgramCodeThisRegister].u.jsValue = thisObj;
671     
672     if (codeBlock->needsFullScopeChain)
673         scopeChain = scopeChain->copy();
674
675 #if JAVASCRIPT_PROFILING
676     Profiler** profiler = Profiler::enabledProfilerReference();
677     if (*profiler)
678         (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
679 #endif
680
681     ExecState newExec(exec, this, registerFile, scopeChain, -1);
682
683     m_reentryDepth++;
684     JSValue* result = privateExecute(Normal, &newExec, registerFile, r, scopeChain, codeBlock, exception);
685     m_reentryDepth--;
686
687     registerFileStack->popGlobalRegisterFile();
688
689 #if JAVASCRIPT_PROFILING
690     if (*profiler)
691         (*profiler)->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
692 #endif
693
694     return result;
695 }
696
697 JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, FunctionImp* function, JSObject* thisObj, const List& args, RegisterFileStack* registerFileStack, ScopeChainNode* scopeChain, JSValue** exception)
698 {
699     if (m_reentryDepth >= MaxReentryDepth) {
700         *exception = createStackOverflowError(exec);
701         return 0;
702     }
703
704     RegisterFile* registerFile = registerFileStack->current();
705
706     int argv = CallFrameHeaderSize;
707     int argc = args.size() + 1; // implicit "this" parameter
708     
709     size_t oldSize = registerFile->size();
710     if (!registerFile->grow(oldSize + CallFrameHeaderSize + argc)) {
711         *exception = createStackOverflowError(exec);
712         return 0;
713     }
714         
715     Register** registerBase = registerFile->basePointer();
716     int registerOffset = oldSize;
717     int callFrameOffset = registerOffset;
718     Register* callFrame = (*registerBase) + callFrameOffset;
719     
720     // put args in place, including "this"
721     Register* dst = callFrame + CallFrameHeaderSize;
722     (*dst).u.jsValue = thisObj;
723     
724     List::const_iterator end = args.end();
725     for (List::const_iterator it = args.begin(); it != end; ++it)
726         (*++dst).u.jsValue = *it;
727
728     // put call frame in place, using a 0 codeBlock to indicate a built-in caller
729     initializeCallFrame(callFrame, 0, 0, 0, registerOffset, 0, argv, argc, 0, function);
730
731     CodeBlock* newCodeBlock = &functionBodyNode->code(scopeChain);
732     Register* r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, argv, argc, *exception);
733     if (*exception) {
734         registerFile->shrink(oldSize);
735         return 0;
736     }
737
738     scopeChain = scopeChainForCall(functionBodyNode, newCodeBlock, scopeChain, registerBase, r);            
739
740     ExecState newExec(exec, this, registerFile, scopeChain, callFrameOffset);
741     
742 #if JAVASCRIPT_PROFILING
743     Profiler** profiler = Profiler::enabledProfilerReference();
744     if (*profiler)
745         (*profiler)->willExecute(exec, function);
746 #endif
747
748     m_reentryDepth++;
749     JSValue* result = privateExecute(Normal, &newExec, registerFile, r, scopeChain, newCodeBlock, exception);
750     m_reentryDepth--;
751
752 #if JAVASCRIPT_PROFILING
753     if (*profiler)
754         (*profiler)->didExecute(exec, function);
755 #endif
756     registerFile->shrink(oldSize);
757     return result;
758 }
759
760 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, RegisterFile* registerFile, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
761 {
762     if (m_reentryDepth >= MaxReentryDepth) {
763         *exception = createStackOverflowError(exec);
764         return 0;
765     }
766
767     EvalCodeBlock* codeBlock = &evalNode->code(scopeChain);
768     
769     JSVariableObject* variableObject;
770     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
771         ASSERT(node);
772         if (node->object->isVariableObject()) {
773             variableObject = static_cast<JSVariableObject*>(node->object);
774             break;
775         }
776     }
777     
778     for (Vector<Identifier>::const_iterator iter = codeBlock->declaredVariableNames.begin(); iter != codeBlock->declaredVariableNames.end(); ++iter) {
779         Identifier ident = *iter;
780         
781         if (!variableObject->hasProperty(exec, ident))
782             variableObject->put(exec, ident, jsUndefined());
783     }
784     
785     ASSERT(codeBlock->functions.size() == codeBlock->declaredFunctionNames.size());
786     for (size_t i = 0; i < codeBlock->functions.size(); ++i)
787         variableObject->put(exec, codeBlock->declaredFunctionNames[i], codeBlock->functions[i]->makeFunction(exec, scopeChain));
788     
789     size_t oldSize = registerFile->size();
790     size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numTemporaries + CallFrameHeaderSize;
791     if (!registerFile->grow(newSize)) {
792         *exception = createStackOverflowError(exec);
793         return 0;
794     }
795
796     Register* callFrame = *registerFile->basePointer() + registerOffset;
797     
798     // put call frame in place, using a 0 codeBlock to indicate a built-in caller
799     initializeCallFrame(callFrame, 0, 0, 0, registerOffset, 0, 0, 0, 0, 0);
800
801     Register* r = callFrame + CallFrameHeaderSize + codeBlock->numVars;
802     r[ProgramCodeThisRegister].u.jsValue = thisObj;
803
804     if (codeBlock->needsFullScopeChain)
805         scopeChain = scopeChain->copy();
806
807 #if JAVASCRIPT_PROFILING
808     Profiler** profiler = Profiler::enabledProfilerReference();
809     if (*profiler)
810         (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
811 #endif
812
813     ExecState newExec(exec, this, registerFile, scopeChain, -1);
814
815     m_reentryDepth++;
816     JSValue* result = privateExecute(Normal, &newExec, registerFile, r, scopeChain, codeBlock, exception);
817     m_reentryDepth--;
818
819     registerFile->shrink(oldSize);
820
821 #if JAVASCRIPT_PROFILING
822     if (*profiler)
823         (*profiler)->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
824 #endif
825
826     return result;
827 }
828
829 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, RegisterFileStack* registerFileStack, ScopeChainNode* scopeChain, JSValue** exception)
830 {
831     RegisterFile* registerFile = registerFileStack->current();
832     if (registerFile->safeForReentry())
833         return Machine::execute(evalNode, exec, thisObj, registerFile, registerFile->size(), scopeChain, exception);
834     registerFile = registerFileStack->pushFunctionRegisterFile();
835     JSValue* result = Machine::execute(evalNode, exec, thisObj, registerFile, registerFile->size(), scopeChain, exception);
836     registerFileStack->popFunctionRegisterFile();
837     return result;
838 }
839
840 ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scopeChain, ScopeChainNode* newScopeChain)
841 {
842     scopeChain = newScopeChain;
843     exec->m_scopeChain = newScopeChain;
844 }
845
846 NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register** registerBase, Register* r)
847 {
848     int debugHookID = (++vPC)->u.operand;
849     int firstLine = (++vPC)->u.operand;
850     int lastLine = (++vPC)->u.operand;
851
852     Debugger* debugger = exec->dynamicGlobalObject()->debugger();
853     if (!debugger)
854         return;
855
856     DebuggerCallFrame debuggerCallFrame(this, exec->dynamicGlobalObject(), codeBlock, scopeChain, 0, registerBase, r - *registerBase);
857
858     switch((DebugHookID)debugHookID) {
859     case DidEnterCallFrame: {
860         debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
861         return;
862     }
863     case WillLeaveCallFrame: {
864         debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
865         return;
866     }
867     case WillExecuteStatement: {
868         debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
869         return;
870     }
871     }
872 }
873
874 JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
875 {
876     // One-time initialization of our address tables. We have to put this code
877     // here because our labels are only in scope inside this function.
878     if (flag == InitializeAndReturn) {
879         #if HAVE(COMPUTED_GOTO)
880             #define ADD_OPCODE(id) m_opcodeTable[id] = &&id;
881                 FOR_EACH_OPCODE_ID(ADD_OPCODE);
882             #undef ADD_OPCODE
883
884             #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id);
885                 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
886             #undef ADD_OPCODE
887             ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
888             op_throw_end_indirect = &&op_throw_end;
889             op_call_indirect = &&op_call;
890         #endif // HAVE(COMPUTED_GOTO)
891         return 0;
892     }
893
894     JSValue* exceptionValue = 0;
895     Instruction* handlerVPC = 0;
896
897     Register** registerBase = registerFile->basePointer();
898     Instruction* vPC = codeBlock->instructions.begin();
899     JSValue** k = codeBlock->jsValues.data();
900 #if JAVASCRIPT_PROFILING
901     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
902     
903 #if HAVE(COMPUTED_GOTO)
904     // Yet another hack around GCC's various foibles, in this case fetching the
905     // profiler reference results in a regression.  Removing this indirection
906     // results in a 0.8% regression.
907     goto *(&&profilerFetchHack);
908     profilerFetchHack:
909 #endif
910     
911 #endif
912     
913     registerFile->setSafeForReentry(false);
914 #define VM_CHECK_EXCEPTION() \
915      do { \
916         if (UNLIKELY(exec->hadException())) { \
917             exceptionValue = exec->exception(); \
918             goto vm_throw; \
919         } \
920     } while (0)
921
922 #if HAVE(COMPUTED_GOTO)
923     #define NEXT_OPCODE goto *vPC->u.opcode
924     #define BEGIN_OPCODE(opcode) opcode:
925     NEXT_OPCODE;
926 #else
927     #define NEXT_OPCODE continue
928     #define BEGIN_OPCODE(opcode) case opcode:
929     while(1) // iterator loop begins
930     switch (vPC->u.opcode)
931 #endif
932     {
933     BEGIN_OPCODE(op_load) {
934         /* load dst(r) src(k)
935
936            Copies constant src to register dst.
937         */
938         int dst = (++vPC)->u.operand;
939         int src = (++vPC)->u.operand;
940         r[dst].u.jsValue = k[src];
941         
942         ++vPC;
943         NEXT_OPCODE;
944     }
945     BEGIN_OPCODE(op_new_object) {
946         /* new_object dst(r)
947
948            Constructs a new empty Object instance using the original
949            constructor, and puts the result in register dst.
950         */
951         int dst = (++vPC)->u.operand;
952         r[dst].u.jsValue = scopeChain->globalObject()->objectConstructor()->construct(exec, exec->emptyList());
953         
954         ++vPC;
955         NEXT_OPCODE;
956     }
957     BEGIN_OPCODE(op_new_array) {
958         /* new_array dst(r)
959
960            Constructs a new empty Array instance using the original
961            constructor, and puts the result in register dst.
962         */
963         int dst = (++vPC)->u.operand;
964         r[dst].u.jsValue = scopeChain->globalObject()->arrayConstructor()->construct(exec, exec->emptyList());
965         
966         ++vPC;
967         NEXT_OPCODE;
968     }
969     BEGIN_OPCODE(op_new_regexp) {
970         /* new_regexp dst(r) regExp(re)
971
972            Constructs a new RegExp instance using the original
973            constructor from regexp regExp, and puts the result in
974            register dst.
975         */
976         int dst = (++vPC)->u.operand;
977         int regExp = (++vPC)->u.operand;
978         r[dst].u.jsValue = new RegExpImp(scopeChain->globalObject()->regExpPrototype(), codeBlock->regexps[regExp]);
979
980         ++vPC;
981         NEXT_OPCODE;
982     }
983     BEGIN_OPCODE(op_mov) {
984         /* mov dst(r) src(r)
985
986            Copies register src to register dst.
987         */
988         int dst = (++vPC)->u.operand;
989         int src = (++vPC)->u.operand;
990         r[dst] = r[src];
991
992         ++vPC;
993         NEXT_OPCODE;
994     }
995     BEGIN_OPCODE(op_eq) {
996         /* eq dst(r) src1(r) src2(r)
997
998            Checks whether register src1 and register src2 are equal,
999            as with the ECMAScript '==' operator, and puts the result
1000            as a boolean in register dst.
1001         */
1002         int dst = (++vPC)->u.operand;
1003         int src1 = (++vPC)->u.operand;
1004         int src2 = (++vPC)->u.operand;
1005         JSValue* result = jsBoolean(equal(exec, r[src1].u.jsValue, r[src2].u.jsValue));
1006         VM_CHECK_EXCEPTION();
1007         r[dst].u.jsValue = result;
1008
1009         ++vPC;
1010         NEXT_OPCODE;
1011     }
1012     BEGIN_OPCODE(op_neq) {
1013         /* neq dst(r) src1(r) src2(r)
1014
1015            Checks whether register src1 and register src2 are not
1016            equal, as with the ECMAScript '!=' operator, and puts the
1017            result as a boolean in register dst.
1018         */
1019         int dst = (++vPC)->u.operand;
1020         int src1 = (++vPC)->u.operand;
1021         int src2 = (++vPC)->u.operand;
1022         JSValue* result = jsBoolean(!equal(exec, r[src1].u.jsValue, r[src2].u.jsValue));
1023         VM_CHECK_EXCEPTION();
1024         r[dst].u.jsValue = result;
1025
1026         ++vPC;
1027         NEXT_OPCODE;
1028     }
1029     BEGIN_OPCODE(op_stricteq) {
1030         /* stricteq dst(r) src1(r) src2(r)
1031
1032            Checks whether register src1 and register src2 are strictly
1033            equal, as with the ECMAScript '===' operator, and puts the
1034            result as a boolean in register dst.
1035         */
1036         int dst = (++vPC)->u.operand;
1037         int src1 = (++vPC)->u.operand;
1038         int src2 = (++vPC)->u.operand;
1039         r[dst].u.jsValue = jsBoolean(strictEqual(r[src1].u.jsValue, r[src2].u.jsValue));
1040         
1041         ++vPC;
1042         NEXT_OPCODE;
1043     }
1044     BEGIN_OPCODE(op_nstricteq) {
1045         /* nstricteq dst(r) src1(r) src2(r)
1046
1047            Checks whether register src1 and register src2 are not
1048            strictly equal, as with the ECMAScript '!==' operator, and
1049            puts the result as a boolean in register dst.
1050         */
1051         int dst = (++vPC)->u.operand;
1052         int src1 = (++vPC)->u.operand;
1053         int src2 = (++vPC)->u.operand;
1054         r[dst].u.jsValue = jsBoolean(!strictEqual(r[src1].u.jsValue, r[src2].u.jsValue));
1055
1056         ++vPC;
1057         NEXT_OPCODE;
1058     }
1059     BEGIN_OPCODE(op_less) {
1060         /* less dst(r) src1(r) src2(r)
1061
1062            Checks whether register src1 is less than register src2, as
1063            with the ECMAScript '<' operator, and puts the result as
1064            a boolean in register dst.
1065         */
1066         int dst = (++vPC)->u.operand;
1067         int src1 = (++vPC)->u.operand;
1068         int src2 = (++vPC)->u.operand;
1069         JSValue* result = jsBoolean(jsLess(exec, r[src1].u.jsValue, r[src2].u.jsValue));
1070         VM_CHECK_EXCEPTION();
1071         r[dst].u.jsValue = result;
1072
1073         ++vPC;
1074         NEXT_OPCODE;
1075     }
1076     BEGIN_OPCODE(op_lesseq) {
1077         /* lesseq dst(r) src1(r) src2(r)
1078
1079            Checks whether register src1 is less than or equal to
1080            register src2, as with the ECMAScript '<=' operator, and
1081            puts the result as a boolean in register dst.
1082         */
1083         int dst = (++vPC)->u.operand;
1084         int src1 = (++vPC)->u.operand;
1085         int src2 = (++vPC)->u.operand;
1086         JSValue* result = jsBoolean(jsLessEq(exec, r[src1].u.jsValue, r[src2].u.jsValue));
1087         VM_CHECK_EXCEPTION();
1088         r[dst].u.jsValue = result;
1089
1090         ++vPC;
1091         NEXT_OPCODE;
1092     }
1093     BEGIN_OPCODE(op_pre_inc) {
1094         /* pre_inc srcDst(r)
1095
1096            Converts register srcDst to number, adds one, and puts the result
1097            back in register srcDst.
1098         */
1099         int srcDst = (++vPC)->u.operand;
1100         JSValue* result = jsNumber(r[srcDst].u.jsValue->toNumber(exec) + 1);
1101         VM_CHECK_EXCEPTION();
1102         r[srcDst].u.jsValue = result;
1103         
1104         ++vPC;
1105         NEXT_OPCODE;
1106     }
1107     BEGIN_OPCODE(op_pre_dec) {
1108         /* pre_dec srcDst(r)
1109
1110            Converts register srcDst to number, subtracts one, and puts the result
1111            back in register srcDst.
1112         */
1113         int srcDst = (++vPC)->u.operand;
1114         JSValue* result = jsNumber(r[srcDst].u.jsValue->toNumber(exec) - 1);
1115         VM_CHECK_EXCEPTION();
1116         r[srcDst].u.jsValue = result;
1117
1118         ++vPC;
1119         NEXT_OPCODE;
1120     }
1121     BEGIN_OPCODE(op_post_inc) {
1122         /* post_inc dst(r) srcDst(r)
1123
1124            Converts register srcDst to number. The number itself is
1125            written to register dst, and the number plus one is written
1126            back to register srcDst.
1127         */
1128         int dst = (++vPC)->u.operand;
1129         int srcDst = (++vPC)->u.operand;
1130         JSValue* number = r[srcDst].u.jsValue->toJSNumber(exec);
1131         VM_CHECK_EXCEPTION();
1132
1133         r[dst].u.jsValue = number;
1134         r[srcDst].u.jsValue = jsNumber(number->uncheckedGetNumber() + 1);
1135
1136         ++vPC;
1137         NEXT_OPCODE;
1138     }
1139     BEGIN_OPCODE(op_post_dec) {
1140         /* post_dec dst(r) srcDst(r)
1141
1142            Converts register srcDst to number. The number itself is
1143            written to register dst, and the number minus one is written
1144            back to register srcDst.
1145         */
1146         int dst = (++vPC)->u.operand;
1147         int srcDst = (++vPC)->u.operand;
1148         JSValue* number = r[srcDst].u.jsValue->toJSNumber(exec);
1149         VM_CHECK_EXCEPTION();
1150
1151         r[dst].u.jsValue = number;
1152         r[srcDst].u.jsValue = jsNumber(number->uncheckedGetNumber() - 1);
1153
1154         ++vPC;
1155         NEXT_OPCODE;
1156     }
1157     BEGIN_OPCODE(op_to_jsnumber) {
1158         /* to_jsnumber dst(r) src(r)
1159
1160            Converts register src to number, and puts the result
1161            in register dst.
1162         */
1163         int dst = (++vPC)->u.operand;
1164         int src = (++vPC)->u.operand;
1165         JSValue* result = r[src].u.jsValue->toJSNumber(exec);
1166         VM_CHECK_EXCEPTION();
1167
1168         r[dst].u.jsValue = result;
1169
1170         ++vPC;
1171         NEXT_OPCODE;
1172     }
1173     BEGIN_OPCODE(op_negate) {
1174         /* negate dst(r) src(r)
1175
1176            Converts register src to number, negates it, and puts the
1177            result in register dst.
1178         */
1179         int dst = (++vPC)->u.operand;
1180         int src = (++vPC)->u.operand;
1181         JSValue* result = jsNumber(-r[src].u.jsValue->toNumber(exec));
1182         VM_CHECK_EXCEPTION();
1183         r[dst].u.jsValue = result;
1184
1185         ++vPC;
1186         NEXT_OPCODE;
1187     }
1188     BEGIN_OPCODE(op_add) {
1189         /* add dst(r) src1(r) src2(r)
1190
1191            Adds register src1 and register src2, and puts the result
1192            in register dst. (JS add may be string concatenation or
1193            numeric add, depending on the types of the operands.)
1194         */
1195         int dst = (++vPC)->u.operand;
1196         int src1 = (++vPC)->u.operand;
1197         int src2 = (++vPC)->u.operand;
1198         JSValue* result = jsAdd(exec, r[src1].u.jsValue, r[src2].u.jsValue);
1199         VM_CHECK_EXCEPTION();
1200         r[dst].u.jsValue = result;
1201         ++vPC;
1202         NEXT_OPCODE;
1203     }
1204     BEGIN_OPCODE(op_mul) {
1205         /* mul dst(r) src1(r) src2(r)
1206
1207            Multiplies register src1 and register src2 (converted to
1208            numbers), and puts the product in register dst.
1209         */
1210         int dst = (++vPC)->u.operand;
1211         int src1 = (++vPC)->u.operand;
1212         int src2 = (++vPC)->u.operand;
1213         JSValue* result = jsNumber(r[src1].u.jsValue->toNumber(exec) * r[src2].u.jsValue->toNumber(exec));
1214         VM_CHECK_EXCEPTION();
1215         r[dst].u.jsValue = result;
1216
1217         ++vPC;
1218         NEXT_OPCODE;
1219     }
1220     BEGIN_OPCODE(op_div) {
1221         /* div dst(r) dividend(r) divisor(r)
1222
1223            Divides register dividend (converted to number) by the
1224            register divisor (converted to number), and puts the
1225            quotient in register dst.
1226         */
1227         int dst = (++vPC)->u.operand;
1228         int dividend = (++vPC)->u.operand;
1229         int divisor = (++vPC)->u.operand;
1230         JSValue* result = jsNumber(r[dividend].u.jsValue->toNumber(exec) / r[divisor].u.jsValue->toNumber(exec));
1231         VM_CHECK_EXCEPTION();
1232         r[dst].u.jsValue = result;
1233         ++vPC;
1234         NEXT_OPCODE;
1235     }
1236     BEGIN_OPCODE(op_mod) {
1237         /* mod dst(r) dividend(r) divisor(r)
1238
1239            Divides register dividend (converted to number) by 
1240            register divisor (converted to number), and puts the
1241            remainder in register dst.
1242         */
1243         int dst = (++vPC)->u.operand;
1244         int dividend = (++vPC)->u.operand;
1245         int divisor = (++vPC)->u.operand;
1246         double d = r[dividend].u.jsValue->toNumber(exec);
1247         JSValue* result = jsNumber(fmod(d, r[divisor].u.jsValue->toNumber(exec)));
1248         VM_CHECK_EXCEPTION();
1249         r[dst].u.jsValue = result;
1250         ++vPC;
1251         NEXT_OPCODE;
1252     }
1253     BEGIN_OPCODE(op_sub) {
1254         /* sub dst(r) src1(r) src2(r)
1255
1256            Subtracts register src2 (converted to number) from register
1257            src1 (converted to number), and puts the difference in
1258            register dst.
1259         */
1260         int dst = (++vPC)->u.operand;
1261         int src1 = (++vPC)->u.operand;
1262         int src2 = (++vPC)->u.operand;
1263         JSValue* result = jsNumber(r[src1].u.jsValue->toNumber(exec) - r[src2].u.jsValue->toNumber(exec));
1264         VM_CHECK_EXCEPTION();
1265         r[dst].u.jsValue = result;
1266         ++vPC;
1267         NEXT_OPCODE;
1268     }
1269     BEGIN_OPCODE(op_lshift) {
1270         /* lshift dst(r) val(r) shift(r)
1271
1272            Performs left shift of register val (converted to int32) by
1273            register shift (converted to uint32), and puts the result
1274            in register dst.
1275         */
1276         int dst = (++vPC)->u.operand;
1277         int val = (++vPC)->u.operand;
1278         int shift = (++vPC)->u.operand;
1279         JSValue* result = jsNumber((r[val].u.jsValue->toInt32(exec)) << (r[shift].u.jsValue->toUInt32(exec)));
1280         VM_CHECK_EXCEPTION();
1281         r[dst].u.jsValue = result;
1282         
1283         ++vPC;
1284         NEXT_OPCODE;
1285     }
1286     BEGIN_OPCODE(op_rshift) {
1287         /* rshift dst(r) val(r) shift(r)
1288
1289            Performs arithmetic right shift of register val (converted
1290            to int32) by register shift (converted to
1291            uint32), and puts the result in register dst.
1292         */
1293         int dst = (++vPC)->u.operand;
1294         int val = (++vPC)->u.operand;
1295         int shift = (++vPC)->u.operand;
1296         JSValue* result = jsNumber((r[val].u.jsValue->toInt32(exec)) >> (r[shift].u.jsValue->toUInt32(exec)));
1297         VM_CHECK_EXCEPTION();
1298         r[dst].u.jsValue = result;
1299         
1300         ++vPC;
1301         NEXT_OPCODE;
1302     }
1303     BEGIN_OPCODE(op_urshift) {
1304         /* rshift dst(r) val(r) shift(r)
1305
1306            Performs logical right shift of register val (converted
1307            to uint32) by register shift (converted to
1308            uint32), and puts the result in register dst.
1309         */
1310         int dst = (++vPC)->u.operand;
1311         int val = (++vPC)->u.operand;
1312         int shift = (++vPC)->u.operand;
1313         JSValue* result = jsNumber((r[val].u.jsValue->toUInt32(exec)) >> (r[shift].u.jsValue->toUInt32(exec)));
1314         VM_CHECK_EXCEPTION();
1315         r[dst].u.jsValue = result;
1316         
1317         ++vPC;
1318         NEXT_OPCODE;
1319     }
1320     BEGIN_OPCODE(op_bitand) {
1321         /* bitand dst(r) src1(r) src2(r)
1322
1323            Computes bitwise AND of register src1 (converted to int32)
1324            and register src2 (converted to int32), and puts the result
1325            in register dst.
1326         */
1327         int dst = (++vPC)->u.operand;
1328         int src1 = (++vPC)->u.operand;
1329         int src2 = (++vPC)->u.operand;
1330         JSValue* result = jsNumber((r[src1].u.jsValue->toInt32(exec)) & (r[src2].u.jsValue->toInt32(exec)));
1331         VM_CHECK_EXCEPTION();
1332         r[dst].u.jsValue = result;
1333         
1334         ++vPC;
1335         NEXT_OPCODE;
1336     }
1337     BEGIN_OPCODE(op_bitxor) {
1338         /* bitxor dst(r) src1(r) src2(r)
1339
1340            Computes bitwise XOR of register src1 (converted to int32)
1341            and register src2 (converted to int32), and puts the result
1342            in register dst.
1343         */
1344         int dst = (++vPC)->u.operand;
1345         int src1 = (++vPC)->u.operand;
1346         int src2 = (++vPC)->u.operand;
1347         JSValue* result = jsNumber((r[src1].u.jsValue->toInt32(exec)) ^ (r[src2].u.jsValue->toInt32(exec)));
1348         VM_CHECK_EXCEPTION();
1349         r[dst].u.jsValue = result;
1350         
1351         ++vPC;
1352         NEXT_OPCODE;
1353     }
1354     BEGIN_OPCODE(op_bitor) {
1355         /* bitor dst(r) src1(r) src2(r)
1356
1357            Computes bitwise OR of register src1 (converted to int32)
1358            and register src2 (converted to int32), and puts the
1359            result in register dst.
1360         */
1361         int dst = (++vPC)->u.operand;
1362         int src1 = (++vPC)->u.operand;
1363         int src2 = (++vPC)->u.operand;
1364         JSValue* result = jsNumber((r[src1].u.jsValue->toInt32(exec)) | (r[src2].u.jsValue->toInt32(exec)));
1365         VM_CHECK_EXCEPTION();
1366         r[dst].u.jsValue = result;
1367         
1368         ++vPC;
1369         NEXT_OPCODE;
1370     }
1371     BEGIN_OPCODE(op_bitnot) {
1372         /* bitnot dst(r) src(r)
1373
1374            Computes bitwise NOT of register src1 (converted to int32),
1375            and puts the result in register dst.
1376         */
1377         int dst = (++vPC)->u.operand;
1378         int src = (++vPC)->u.operand;
1379         JSValue* result = jsNumber(~r[src].u.jsValue->toInt32(exec));
1380         VM_CHECK_EXCEPTION();
1381         r[dst].u.jsValue = result;
1382
1383         ++vPC;
1384         NEXT_OPCODE;
1385     }
1386     BEGIN_OPCODE(op_not) {
1387         /* not dst(r) src1(r) src2(r)
1388
1389            Computes logical NOT of register src1 (converted to
1390            boolean), and puts the result in register dst.
1391         */
1392         int dst = (++vPC)->u.operand;
1393         int src = (++vPC)->u.operand;
1394         JSValue* result = jsBoolean(!r[src].u.jsValue->toBoolean(exec));
1395         VM_CHECK_EXCEPTION();
1396         r[dst].u.jsValue = result;
1397
1398         ++vPC;
1399         NEXT_OPCODE;
1400     }
1401     BEGIN_OPCODE(op_instanceof) {
1402         /* instanceof dst(r) value(r) constructor(r)
1403
1404            Tests whether register value is an instance of register
1405            constructor, and puts the boolean result in register dst.
1406           
1407            Raises an exception if register constructor is not an
1408            object.
1409         */
1410         int dst = (++vPC)->u.operand;
1411         int value = (++vPC)->u.operand;
1412         int base = (++vPC)->u.operand;
1413
1414         JSValue* baseVal = r[base].u.jsValue;
1415
1416         if (isNotObject(exec, vPC, codeBlock, baseVal, exceptionValue))
1417             goto vm_throw;
1418
1419         JSObject* baseObj = static_cast<JSObject*>(baseVal);
1420         r[dst].u.jsValue = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].u.jsValue) : false);
1421
1422         ++vPC;
1423         NEXT_OPCODE;
1424     }
1425     BEGIN_OPCODE(op_typeof) {
1426         /* typeof dst(r) src(r)
1427
1428            Determines the type string for src according to ECMAScript
1429            rules, and puts the result in register dst.
1430         */
1431         int dst = (++vPC)->u.operand;
1432         int src = (++vPC)->u.operand;
1433         r[dst].u.jsValue = jsTypeStringForValue(r[src].u.jsValue);
1434
1435         ++vPC;
1436         NEXT_OPCODE;
1437     }
1438     BEGIN_OPCODE(op_in) {
1439         /* in dst(r) property(r) base(r)
1440
1441            Tests whether register base has a property named register
1442            property, and puts the boolean result in register dst.
1443           
1444            Raises an exception if register constructor is not an
1445            object.
1446         */
1447         int dst = (++vPC)->u.operand;
1448         int property = (++vPC)->u.operand;
1449         int base = (++vPC)->u.operand;
1450
1451         JSValue* baseVal = r[base].u.jsValue;
1452         if (isNotObject(exec, vPC, codeBlock, baseVal, exceptionValue))
1453             goto vm_throw;
1454
1455         JSObject* baseObj = static_cast<JSObject*>(baseVal);
1456
1457         JSValue* propName = r[property].u.jsValue;
1458
1459         uint32_t i;
1460         if (propName->getUInt32(i))
1461             r[dst].u.jsValue = jsBoolean(baseObj->hasProperty(exec, i));
1462         else {
1463             Identifier property(propName->toString(exec));
1464             VM_CHECK_EXCEPTION();
1465             r[dst].u.jsValue = jsBoolean(baseObj->hasProperty(exec, property));
1466         }
1467
1468         ++vPC;
1469         NEXT_OPCODE;
1470     }
1471     BEGIN_OPCODE(op_resolve) {
1472         /* resolve dst(r) property(id)
1473
1474            Looks up the property named by identifier property in the
1475            scope chain, and writes the resulting value to register
1476            dst. If the property is not found, raises an exception.
1477         */
1478         if (UNLIKELY(!resolve(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1479             goto vm_throw;
1480
1481         vPC += 3;
1482         NEXT_OPCODE;
1483     }
1484     BEGIN_OPCODE(op_resolve_skip) {
1485         /* resolve_skip dst(r) property(id) skip(n)
1486          
1487          Looks up the property named by identifier property in the
1488          scope chain skipping the top 'skip' levels, and writes the resulting
1489          value to register dst. If the property is not found, raises an exception.
1490          */
1491         if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1492             goto vm_throw;
1493         
1494         vPC += 4;
1495         
1496         NEXT_OPCODE;
1497     }
1498     BEGIN_OPCODE(op_get_scoped_var) {
1499         /* get_scoped_var dst(r) index(n) skip(n)
1500          
1501          Loads the contents of the index-th local from the scope skip nodes from
1502          the top of the scope chain, and places it in register dst
1503          */
1504         int dst = (++vPC)->u.operand;
1505         int index = (++vPC)->u.operand;
1506         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1507         
1508         ScopeChainIterator iter = scopeChain->begin();
1509         ScopeChainIterator end = scopeChain->end();
1510         ASSERT(iter != end);
1511         while (skip--) {
1512             ++iter;
1513             ASSERT(iter != end);
1514         }
1515         
1516         ASSERT((*iter)->isVariableObject());
1517         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1518         r[dst].u.jsValue = scope->valueAt(index);
1519         ++vPC;
1520         NEXT_OPCODE;
1521     }
1522     BEGIN_OPCODE(op_put_scoped_var) {
1523         /* put_scoped_var index(n) skip(n) value(r)
1524
1525          */
1526         int index = (++vPC)->u.operand;
1527         int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1528         int value = (++vPC)->u.operand;
1529         
1530         ScopeChainIterator iter = scopeChain->begin();
1531         ScopeChainIterator end = scopeChain->end();
1532         ASSERT(iter != end);
1533         while (skip--) {
1534             ++iter;
1535             ASSERT(iter != end);
1536         }
1537         
1538         ASSERT((*iter)->isVariableObject());
1539         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1540         scope->valueAt(index) = r[value].u.jsValue;
1541         ++vPC;
1542         NEXT_OPCODE;
1543     }
1544     BEGIN_OPCODE(op_resolve_base) {
1545         /* resolve_base dst(r) property(id)
1546
1547            Searches the scope chain for an object containing
1548            identifier property, and if one is found, writes it to
1549            register dst. If none is found, the outermost scope (which
1550            will be the global object) is stored in register dst.
1551         */
1552         resolveBase(exec, vPC, r, scopeChain, codeBlock);
1553
1554         vPC += 3;
1555         NEXT_OPCODE;
1556     }
1557     BEGIN_OPCODE(op_resolve_with_base) {
1558         /* resolve_with_base baseDst(r) propDst(r) property(id)
1559
1560            Searches the scope chain for an object containing
1561            identifier property, and if one is found, writes it to
1562            register srcDst, and the retrieved property value to register
1563            propDst. If the property is not found, raises an exception.
1564
1565            This is more efficient than doing resolve_base followed by
1566            resolve, or resolve_base followed by get_by_id, as it
1567            avoids duplicate hash lookups.
1568         */
1569         if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1570             goto vm_throw;
1571
1572         vPC += 4;
1573         NEXT_OPCODE;
1574     }
1575     BEGIN_OPCODE(op_resolve_func) {
1576         /* resolve_func baseDst(r) funcDst(r) property(id)
1577
1578            Searches the scope chain for an object containing
1579            identifier property, and if one is found, writes the
1580            appropriate object to use as "this" when calling its
1581            properties to register baseDst; and the retrieved property
1582            value to register propDst. If the property is not found,
1583            raises an exception.
1584
1585            This differs from resolve_with_base, because the
1586            global this value will be substituted for activations or
1587            the global object, which is the right behavior for function
1588            calls but not for other property lookup.
1589         */
1590         if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1591             goto vm_throw;
1592
1593         vPC += 4;
1594         NEXT_OPCODE;
1595     }
1596     BEGIN_OPCODE(op_get_by_id) {
1597         /* get_by_id dst(r) base(r) property(id)
1598
1599            Converts register base to Object, gets the property
1600            named by identifier property from the object, and puts the
1601            result in register dst.
1602         */
1603         int dst = (++vPC)->u.operand;
1604         int base = (++vPC)->u.operand;
1605         int property = (++vPC)->u.operand;
1606 #ifndef NDEBUG
1607         int registerOffset = r - (*registerBase);
1608 #endif
1609         JSObject* baseObj = r[base].u.jsValue->toObject(exec);
1610
1611         Identifier& ident = codeBlock->identifiers[property];
1612         JSValue *result = baseObj->get(exec, ident);
1613         ASSERT(registerOffset == (r - (*registerBase)));
1614         VM_CHECK_EXCEPTION();
1615         r[dst].u.jsValue = result;
1616         ++vPC;
1617         NEXT_OPCODE;
1618     }
1619     BEGIN_OPCODE(op_put_by_id) {
1620         /* put_by_id base(r) property(id) value(r)
1621
1622            Sets register value on register base as the property named
1623            by identifier property. Base is converted to object first.
1624  
1625            Unlike many opcodes, this one does not write any output to
1626            the register file.
1627         */
1628         int base = (++vPC)->u.operand;
1629         int property = (++vPC)->u.operand;
1630         int value = (++vPC)->u.operand;
1631 #ifndef NDEBUG
1632         int registerOffset = r - (*registerBase);
1633 #endif
1634
1635         JSObject* baseObj = r[base].u.jsValue->toObject(exec);
1636         
1637         Identifier& ident = codeBlock->identifiers[property];
1638         baseObj->put(exec, ident, r[value].u.jsValue);
1639         ASSERT(registerOffset == (r - (*registerBase)));
1640         
1641         VM_CHECK_EXCEPTION();
1642         ++vPC;
1643         NEXT_OPCODE;
1644     }
1645     BEGIN_OPCODE(op_del_by_id) {
1646         /* del_by_id dst(r) base(r) property(id)
1647
1648            Converts register base to Object, deletes the property
1649            named by identifier property from the object, and writes a
1650            boolean indicating success (if true) or failure (if false)
1651            to register dst.
1652         */
1653         int dst = (++vPC)->u.operand;
1654         int base = (++vPC)->u.operand;
1655         int property = (++vPC)->u.operand;
1656
1657         JSObject* baseObj = r[base].u.jsValue->toObject(exec);
1658         
1659         Identifier& ident = codeBlock->identifiers[property];
1660         JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
1661         VM_CHECK_EXCEPTION();
1662         r[dst].u.jsValue = result;
1663         ++vPC;
1664         NEXT_OPCODE;
1665     }
1666     BEGIN_OPCODE(op_get_by_val) {
1667         /* get_by_val dst(r) base(r) property(r)
1668
1669            Converts register base to Object, gets the property named
1670            by register property from the object, and puts the result
1671            in register dst. property is nominally converted to string
1672            but numbers are treated more efficiently.
1673         */
1674         int dst = (++vPC)->u.operand;
1675         int base = (++vPC)->u.operand;
1676         int property = (++vPC)->u.operand;
1677
1678         JSObject* baseObj = r[base].u.jsValue->toObject(exec); // may throw
1679         
1680         JSValue* subscript = r[property].u.jsValue;
1681         JSValue* result;
1682         uint32_t i;
1683         if (subscript->getUInt32(i))
1684             result = baseObj->get(exec, i);
1685         else {
1686             Identifier property;
1687             if (subscript->isObject()) {
1688                 VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
1689                 property = Identifier(subscript->toString(exec));
1690             } else
1691                 property = Identifier(subscript->toString(exec));
1692
1693             VM_CHECK_EXCEPTION(); // This check is needed to prevent us from incorrectly calling a getter after an exception is thrown
1694             result = baseObj->get(exec, property);
1695         }
1696         
1697         VM_CHECK_EXCEPTION();
1698         r[dst].u.jsValue = result;
1699         ++vPC;
1700         NEXT_OPCODE;
1701     }
1702     BEGIN_OPCODE(op_put_by_val) {
1703         /* put_by_val base(r) property(r) value(r)
1704
1705            Sets register value on register base as the property named
1706            by register property. Base is converted to object
1707            first. register property is nominally converted to string
1708            but numbers are treated more efficiently.
1709  
1710            Unlike many opcodes, this one does not write any output to
1711            the register file.
1712         */
1713         int base = (++vPC)->u.operand;
1714         int property = (++vPC)->u.operand;
1715         int value = (++vPC)->u.operand;
1716
1717         JSObject* baseObj = r[base].u.jsValue->toObject(exec);
1718         
1719         JSValue* subscript = r[property].u.jsValue;
1720
1721         uint32_t i;
1722         if (subscript->getUInt32(i))
1723             baseObj->put(exec, i, r[value].u.jsValue);
1724         else {
1725             Identifier property;
1726             if (subscript->isObject()) {
1727                 VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
1728                 property = Identifier(subscript->toString(exec));
1729             } else
1730                 property = Identifier(subscript->toString(exec));
1731
1732             VM_CHECK_EXCEPTION(); // This check is needed to prevent us from incorrectly calling a setter after an exception is thrown
1733             baseObj->put(exec, property, r[value].u.jsValue);
1734         }
1735         
1736         VM_CHECK_EXCEPTION();
1737         ++vPC;
1738         NEXT_OPCODE;
1739     }
1740     BEGIN_OPCODE(op_del_by_val) {
1741         /* del_by_val dst(r) base(r) property(r)
1742
1743            Converts register base to Object, deletes the property
1744            named by register property from the object, and writes a
1745            boolean indicating success (if true) or failure (if false)
1746            to register dst.
1747         */
1748         int dst = (++vPC)->u.operand;
1749         int base = (++vPC)->u.operand;
1750         int property = (++vPC)->u.operand;
1751
1752         JSObject* baseObj = r[base].u.jsValue->toObject(exec); // may throw
1753
1754         JSValue* subscript = r[property].u.jsValue;
1755         JSValue* result;
1756         uint32_t i;
1757         if (subscript->getUInt32(i))
1758             result = jsBoolean(baseObj->deleteProperty(exec, i));
1759         else {
1760             VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
1761             Identifier property(subscript->toString(exec));
1762             VM_CHECK_EXCEPTION();
1763             result = jsBoolean(baseObj->deleteProperty(exec, property));
1764         }
1765         
1766         VM_CHECK_EXCEPTION();
1767         r[dst].u.jsValue = result;
1768         ++vPC;
1769         NEXT_OPCODE;
1770     }
1771     BEGIN_OPCODE(op_put_by_index) {
1772         /* put_by_index base(r) property(n) value(r)
1773
1774            Sets register value on register base as the property named
1775            by the immediate number property. Base is converted to
1776            object first. register property is nominally converted to
1777            string but numbers are treated more efficiently.
1778  
1779            Unlike many opcodes, this one does not write any output to
1780            the register file.
1781
1782            This opcode is mainly used to initialize array literals.
1783         */
1784         int base = (++vPC)->u.operand;
1785         unsigned property = (++vPC)->u.operand;
1786         int value = (++vPC)->u.operand;
1787
1788         r[base].u.jsObject->put(exec, property, r[value].u.jsValue);
1789
1790         ++vPC;
1791         NEXT_OPCODE;
1792     }
1793     BEGIN_OPCODE(op_jmp) {
1794         /* jmp target(offset)
1795          
1796            Jumps unconditionally to offset target from the current
1797            instruction.
1798         */
1799         int target = (++vPC)->u.operand;
1800
1801         vPC += target;
1802         NEXT_OPCODE;
1803     }
1804     BEGIN_OPCODE(op_jtrue) {
1805         /* jtrue cond(r) target(offset)
1806          
1807            Jumps to offset target from the current instruction, if and
1808            only if register cond converts to boolean as true.
1809         */
1810         int cond = (++vPC)->u.operand;
1811         int target = (++vPC)->u.operand;
1812         if (r[cond].u.jsValue->toBoolean(exec)) {
1813             vPC += target;
1814             NEXT_OPCODE;
1815         }
1816
1817         ++vPC;
1818         NEXT_OPCODE;
1819     }
1820     BEGIN_OPCODE(op_jfalse) {
1821         /* jfalse cond(r) target(offset)
1822          
1823            Jumps to offset target from the current instruction, if and
1824            only if register cond converts to boolean as false.
1825         */
1826         int cond = (++vPC)->u.operand;
1827         int target = (++vPC)->u.operand;
1828         if (!r[cond].u.jsValue->toBoolean(exec)) {
1829             vPC += target;
1830             NEXT_OPCODE;
1831         }
1832
1833         ++vPC;
1834         NEXT_OPCODE;
1835     }
1836     BEGIN_OPCODE(op_new_func) {
1837         /* new_func dst(r) func(f)
1838
1839            Constructs a new Function instance from function func and
1840            the current scope chain using the original Function
1841            constructor, using the rules for function declarations, and
1842            puts the result in register dst.
1843         */
1844         int dst = (++vPC)->u.operand;
1845         int func = (++vPC)->u.operand;
1846
1847         r[dst].u.jsValue = codeBlock->functions[func]->makeFunction(exec, scopeChain);
1848
1849         ++vPC;
1850         NEXT_OPCODE;
1851     }
1852     BEGIN_OPCODE(op_new_func_exp) {
1853         /* new_func_exp dst(r) func(f)
1854
1855            Constructs a new Function instance from function func and
1856            the current scope chain using the original Function
1857            constructor, using the rules for function expressions, and
1858            puts the result in register dst.
1859         */
1860         int dst = (++vPC)->u.operand;
1861         int func = (++vPC)->u.operand;
1862
1863         r[dst].u.jsValue = codeBlock->functionExpressions[func]->makeFunction(exec, scopeChain);
1864
1865         ++vPC;
1866         NEXT_OPCODE;
1867     }
1868     BEGIN_OPCODE(op_call_eval) {
1869         int dst = (++vPC)->u.operand;
1870         int func = (++vPC)->u.operand;
1871         int base = (++vPC)->u.operand;
1872         int argv = (++vPC)->u.operand;
1873         int argc = (++vPC)->u.operand;
1874
1875         JSValue* funcVal = r[func].u.jsValue;
1876         JSValue* baseVal = r[base].u.jsValue;
1877         
1878         if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
1879             int registerOffset = r - (*registerBase);
1880
1881             JSObject* thisObject = r[codeBlock->thisRegister].u.jsObject;
1882
1883             registerFile->setSafeForReentry(true);
1884
1885             JSValue* result = callEval(exec, thisObject, scopeChain, registerFile, r, argv, argc, exceptionValue);
1886
1887             registerFile->setSafeForReentry(false);
1888             r = (*registerBase) + registerOffset;
1889
1890             if (exceptionValue)
1891                 goto vm_throw;
1892
1893             r[dst].u.jsValue = result;
1894             
1895             ++vPC;
1896             NEXT_OPCODE;
1897         }
1898         
1899         // We didn't find the blessed version of eval, so reset vPC and process
1900         // this instruction as a normal function call, supplying the proper 'this'
1901         // value.
1902         vPC -= 5;
1903         r[base].u.jsValue = baseVal->toObject(exec)->toThisObject(exec);
1904
1905 #if HAVE(COMPUTED_GOTO)
1906         // Hack around gcc performance quirk by performing an indirect goto
1907         // in order to set the vPC -- attempting to do so directly results in a
1908         // significant regression.
1909         goto *op_call_indirect; // indirect goto -> op_call
1910 #endif
1911         // fall through to op_call
1912     }
1913     BEGIN_OPCODE(op_call) {
1914         int dst = (++vPC)->u.operand;
1915         int func = (++vPC)->u.operand;
1916         int base = (++vPC)->u.operand;
1917         int argv = (++vPC)->u.operand;
1918         int argc = (++vPC)->u.operand;
1919         
1920         JSValue* v = r[func].u.jsValue;
1921         
1922         CallData callData;
1923         CallType callType = v->getCallData(callData);
1924         
1925         if (callType == CallTypeJS) {
1926 #if JAVASCRIPT_PROFILING
1927             if (*enabledProfilerReference)
1928                 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
1929 #endif
1930             int registerOffset = r - (*registerBase);
1931             Register* callFrame = r + argv - CallFrameHeaderSize;
1932             int callFrameOffset = registerOffset + argv - CallFrameHeaderSize;
1933
1934             r[argv].u.jsValue = base == missingThisObjectMarker() ? exec->globalThisValue() : r[base].u.jsValue; // "this" value
1935             initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, dst, argv, argc, 0, v);
1936
1937             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
1938             FunctionBodyNode* functionBodyNode = callData.js.functionBody;
1939
1940             CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
1941             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, argv, argc, exceptionValue);
1942             if (UNLIKELY(exceptionValue != 0))
1943                 goto vm_throw;
1944
1945             codeBlock = newCodeBlock;
1946             exec->m_callFrameOffset = callFrameOffset;
1947             setScopeChain(exec, scopeChain, scopeChainForCall(functionBodyNode, codeBlock, callDataScopeChain, registerBase, r));
1948             k = codeBlock->jsValues.data();
1949             vPC = codeBlock->instructions.begin();
1950
1951             NEXT_OPCODE;
1952         }
1953
1954         if (callType == CallTypeNative) {
1955 #if JAVASCRIPT_PROFILING
1956             if (*enabledProfilerReference)
1957                 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
1958 #endif
1959             int registerOffset = r - (*registerBase);
1960
1961             r[argv].u.jsValue = base == missingThisObjectMarker() ? exec->globalThisValue() : (r[base].u.jsValue)->toObject(exec); // "this" value
1962             JSObject* thisObj = static_cast<JSObject*>(r[argv].u.jsValue);
1963
1964             List args(&r[argv + 1].u.jsValue, argc - 1);
1965
1966             registerFile->setSafeForReentry(true);
1967             JSValue* returnValue = static_cast<JSObject*>(v)->callAsFunction(exec, thisObj, args);
1968             registerFile->setSafeForReentry(false);
1969
1970             r = (*registerBase) + registerOffset;
1971             r[dst].u.jsValue = returnValue;
1972
1973 #if JAVASCRIPT_PROFILING
1974             if (*enabledProfilerReference)
1975                 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
1976 #endif
1977             VM_CHECK_EXCEPTION();
1978
1979             ++vPC;
1980             NEXT_OPCODE;
1981         }
1982
1983         ASSERT(callType == CallTypeNone);
1984
1985         exceptionValue = createNotAFunctionError(exec, v, 0);
1986         goto vm_throw;
1987     }
1988     BEGIN_OPCODE(op_ret) {
1989         int r1 = (++vPC)->u.operand;
1990
1991         CodeBlock* oldCodeBlock = codeBlock;
1992
1993         Register* callFrame = r - oldCodeBlock->numLocals - CallFrameHeaderSize;
1994         JSValue* returnValue = r[r1].u.jsValue;
1995
1996         if (JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue)) {
1997             ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
1998             ASSERT(activation->isActivationObject());
1999             activation->copyRegisters();
2000         }
2001
2002         if (codeBlock->needsFullScopeChain)
2003             scopeChain->deref();
2004
2005         if (callFrame[CalledAsConstructor].u.i && !returnValue->isObject()) {
2006             JSValue* thisObject = callFrame[CallFrameHeaderSize].u.jsValue;
2007             returnValue = thisObject;
2008         }
2009          
2010         codeBlock = callFrame[CallerCodeBlock].u.codeBlock;
2011         if (!codeBlock)
2012             return returnValue;
2013         
2014         k = codeBlock->jsValues.data();
2015         vPC = callFrame[ReturnVPC].u.vPC;
2016         setScopeChain(exec, scopeChain, callFrame[CallerScopeChain].u.scopeChain);
2017         int callerRegisterOffset = callFrame[CallerRegisterOffset].u.i;
2018         r = (*registerBase) + callerRegisterOffset;
2019         exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - CallFrameHeaderSize;
2020         int r0 = callFrame[ReturnValueRegister].u.i;
2021         r[r0].u.jsValue = returnValue;
2022         
2023 #if JAVASCRIPT_PROFILING
2024         if (*enabledProfilerReference)
2025             (*enabledProfilerReference)->didExecute(exec, callFrame[Callee].u.jsObject);
2026 #endif
2027         NEXT_OPCODE;
2028     }
2029     BEGIN_OPCODE(op_construct) {
2030         int dst = (++vPC)->u.operand;
2031         int func = (++vPC)->u.operand;
2032         int argv = (++vPC)->u.operand;
2033         int argc = (++vPC)->u.operand;
2034
2035         JSValue* funcVal = r[func].u.jsValue;
2036
2037         ConstructData constructData;
2038         ConstructType constructType = funcVal->getConstructData(constructData);
2039
2040         // Removing this line of code causes a measurable regression on squirrelfish.
2041         JSObject* constructor = static_cast<JSObject*>(funcVal);
2042
2043         if (constructType == ConstructTypeJS) {
2044 #if JAVASCRIPT_PROFILING
2045             if (*enabledProfilerReference)
2046                 (*enabledProfilerReference)->willExecute(exec, constructor);
2047 #endif
2048             int registerOffset = r - (*registerBase);
2049             Register* callFrame = r + argv - CallFrameHeaderSize;
2050             int callFrameOffset = registerOffset + argv - CallFrameHeaderSize;
2051
2052             JSObject* prototype;
2053             JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
2054             if (p->isObject())
2055                 prototype = static_cast<JSObject*>(p);
2056             else
2057                 prototype = scopeChain->globalObject()->objectPrototype();
2058             JSObject* newObject = new JSObject(prototype);
2059             r[argv].u.jsValue = newObject; // "this" value
2060
2061             initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, dst, argv, argc, 1, constructor);
2062
2063             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
2064             FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
2065
2066             CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
2067             r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, argv, argc, exceptionValue);
2068             if (exceptionValue)
2069                 goto vm_throw;
2070
2071             codeBlock = newCodeBlock;
2072             exec->m_callFrameOffset = callFrameOffset;
2073             setScopeChain(exec, scopeChain, scopeChainForCall(functionBodyNode, codeBlock, callDataScopeChain, registerBase, r));
2074             k = codeBlock->jsValues.data();
2075             vPC = codeBlock->instructions.begin();
2076
2077             NEXT_OPCODE;
2078         }
2079
2080         if (constructType == ConstructTypeNative) {
2081 #if JAVASCRIPT_PROFILING
2082             if (*enabledProfilerReference)
2083                 (*enabledProfilerReference)->willExecute(exec, constructor);
2084 #endif
2085             int registerOffset = r - (*registerBase);
2086
2087             List args(&r[argv + 1].u.jsValue, argc - 1);
2088             registerFile->setSafeForReentry(true);
2089             JSValue* returnValue = constructor->construct(exec, args);
2090             registerFile->setSafeForReentry(false);
2091
2092             r = (*registerBase) + registerOffset;
2093             VM_CHECK_EXCEPTION();
2094             r[dst].u.jsValue = returnValue;
2095
2096 #if JAVASCRIPT_PROFILING
2097             if (*enabledProfilerReference)
2098                 (*enabledProfilerReference)->didExecute(exec, constructor);
2099 #endif
2100             ++vPC;
2101             NEXT_OPCODE;
2102         }
2103
2104         ASSERT(constructType == ConstructTypeNone);
2105
2106         exceptionValue = createNotAConstructorError(exec, funcVal, 0);
2107         goto vm_throw;
2108     }
2109     BEGIN_OPCODE(op_push_scope) {
2110         /* push_scope scope(r)
2111
2112            Converts register scope to object, and pushes it onto the top
2113            of the current scope chain.
2114         */
2115         int scope = (++vPC)->u.operand;
2116         JSValue* v = r[scope].u.jsValue;
2117         JSObject* o = v->toObject(exec);
2118         VM_CHECK_EXCEPTION();
2119         
2120         setScopeChain(exec, scopeChain, scopeChain->push(o));
2121
2122         ++vPC;
2123         NEXT_OPCODE;
2124     }
2125     BEGIN_OPCODE(op_pop_scope) {
2126         /* pop_scope
2127
2128            Removes the top item from the current scope chain.
2129         */
2130         setScopeChain(exec, scopeChain, scopeChain->pop());
2131
2132         ++vPC;
2133         NEXT_OPCODE;
2134     }
2135     BEGIN_OPCODE(op_get_pnames) {
2136         /* get_pnames dst(r) base(r)
2137
2138            Creates a property name list for register base and puts it
2139            in register dst. This is not a true JavaScript value, just
2140            a synthetic value used to keep the iteration state in a
2141            register.
2142         */
2143         int dst = (++vPC)->u.operand;
2144         int base = (++vPC)->u.operand;
2145
2146         r[dst].u.jsPropertyNameIterator = JSPropertyNameIterator::create(exec, r[base].u.jsValue);
2147         ++vPC;
2148         NEXT_OPCODE;
2149     }
2150     BEGIN_OPCODE(op_next_pname) {
2151         /* next_pname dst(r) iter(r) target(offset)
2152
2153            Tries to copies the next name from property name list in
2154            register iter. If there are names left, then copies one to
2155            register dst, and jumps to offset target. If there are none
2156            left, invalidates the iterator and continues to the next
2157            instruction.
2158         */
2159         int dst = (++vPC)->u.operand;
2160         int iter = (++vPC)->u.operand;
2161         int target = (++vPC)->u.operand;
2162
2163         JSPropertyNameIterator* it = r[iter].u.jsPropertyNameIterator;
2164         if (JSValue* temp = it->next(exec)) {
2165             r[dst].u.jsValue = temp;
2166             vPC += target;
2167             NEXT_OPCODE;
2168         }
2169         it->invalidate();
2170
2171         ++vPC;
2172         NEXT_OPCODE;
2173     }
2174     BEGIN_OPCODE(op_jmp_scopes) {
2175         /* jmp_scopes count(n) target(offset)
2176
2177            Removes the a number of items from the current scope chain
2178            specified by immediate number count, then jumps to offset
2179            target.
2180         */
2181         int count = (++vPC)->u.operand;
2182         int target = (++vPC)->u.operand;
2183         
2184         ScopeChainNode* tmp = scopeChain;
2185         while (count--)
2186             tmp = tmp->pop();
2187         setScopeChain(exec, scopeChain, tmp);
2188             
2189         vPC += target;
2190         NEXT_OPCODE;
2191     }
2192     BEGIN_OPCODE(op_catch) {
2193         ASSERT(exceptionValue);
2194         ASSERT(!exec->hadException());
2195         int r0 = (++vPC)->u.operand;
2196         r[r0].u.jsValue = exceptionValue;
2197         exceptionValue = 0;
2198         ++vPC;
2199         NEXT_OPCODE;
2200     }
2201     BEGIN_OPCODE(op_throw) {
2202         int e = (++vPC)->u.operand;
2203         exceptionValue = r[e].u.jsValue;
2204         handlerVPC = throwException(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r);
2205         if (!handlerVPC) {
2206             *exception = exceptionValue;
2207             return jsNull();
2208         }
2209
2210 #if HAVE(COMPUTED_GOTO)
2211         // Hack around gcc performance quirk by performing an indirect goto
2212         // in order to set the vPC -- attempting to do so directly results in a
2213         // significant regression.
2214         goto *op_throw_end_indirect; // indirect goto -> op_throw_end
2215     }
2216     op_throw_end: {
2217 #endif
2218
2219         vPC = handlerVPC;
2220         NEXT_OPCODE;
2221     }
2222     BEGIN_OPCODE(op_new_error) {
2223         /* new_error dst(r) type(n) message(k)
2224
2225            Constructs a new Error instance using the original
2226            constructor, using immediate number n as the type and
2227            constant message as the message string. The result is
2228            written to register dst.
2229         */
2230         int dst = (++vPC)->u.operand;
2231         int type = (++vPC)->u.operand;
2232         int message = (++vPC)->u.operand;
2233         
2234         r[dst].u.jsValue = Error::create(exec, (ErrorType)type, k[message]->toString(exec), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
2235         
2236         ++vPC;
2237         NEXT_OPCODE;
2238     }
2239     BEGIN_OPCODE(op_end) {
2240         if (codeBlock->needsFullScopeChain) {
2241             ASSERT(scopeChain->refCount > 1);
2242             scopeChain->deref();
2243         }
2244         int r0 = (++vPC)->u.operand;
2245         return r[r0].u.jsValue;
2246     }
2247     BEGIN_OPCODE(op_put_getter) {
2248         /* put_getter base(r) property(id) function(r)
2249          
2250            Sets register function on register base as the getter named
2251            by identifier property. Base and function are assumed to be
2252            objects as this op should only be used for getters defined
2253            in object literal form.
2254          
2255            Unlike many opcodes, this one does not write any output to
2256            the register file.
2257         */
2258         int base = (++vPC)->u.operand;
2259         int property = (++vPC)->u.operand;
2260         int function = (++vPC)->u.operand;
2261         
2262         ASSERT(r[base].u.jsValue->isObject());
2263         JSObject* baseObj = static_cast<JSObject*>(r[base].u.jsValue);
2264         Identifier& ident = codeBlock->identifiers[property];
2265         ASSERT(r[function].u.jsValue->isObject());
2266         baseObj->defineGetter(exec, ident, static_cast<JSObject* >(r[function].u.jsValue));
2267
2268         ++vPC;
2269         NEXT_OPCODE;
2270     }
2271     BEGIN_OPCODE(op_put_setter) {
2272         /* put_setter base(r) property(id) function(r)
2273          
2274            Sets register function on register base as the setter named
2275            by identifier property. Base and function are assumed to be
2276            objects as this op should only be used for setters defined
2277            in object literal form.
2278          
2279            Unlike many opcodes, this one does not write any output to
2280            the register file.
2281         */
2282         int base = (++vPC)->u.operand;
2283         int property = (++vPC)->u.operand;
2284         int function = (++vPC)->u.operand;
2285         
2286         ASSERT(r[base].u.jsValue->isObject());
2287         JSObject* baseObj = static_cast<JSObject*>(r[base].u.jsValue);
2288         Identifier& ident = codeBlock->identifiers[property];
2289         ASSERT(r[function].u.jsValue->isObject());
2290         baseObj->defineSetter(exec, ident, static_cast<JSObject* >(r[function].u.jsValue));
2291         
2292         ++vPC;
2293         NEXT_OPCODE;
2294     }
2295     BEGIN_OPCODE(op_jsr) {
2296         /* jsr retAddrDst(r) target(offset)
2297          
2298            Places the address of the next instruction into the retAddrDst
2299            register and jumps to offset target from the current instruction.
2300         */
2301         int retAddrDst = (++vPC)->u.operand;
2302         int target = (++vPC)->u.operand;
2303         r[retAddrDst].u.vPC = vPC + 1;
2304
2305         vPC += target;
2306         NEXT_OPCODE;
2307     }
2308     BEGIN_OPCODE(op_sret) {
2309         /* sret retAddrSrc(r)
2310          
2311          Jumps to the address stored in the retAddrSrc register. This
2312          differs from op_jmp because the target address is stored in a
2313          register, not as an immediate.
2314         */
2315         int retAddrSrc = (++vPC)->u.operand;
2316         vPC = r[retAddrSrc].u.vPC;
2317         NEXT_OPCODE;
2318     }
2319     BEGIN_OPCODE(op_debug) {
2320         /* debug debugHookID(n) firstLine(n) lastLine(n)
2321          
2322          Notifies the debugger of the current state of execution:
2323          didEnterCallFrame; willLeaveCallFrame; or willExecuteStatement.
2324          
2325          This opcode is only generated while the debugger is attached.
2326         */
2327
2328         int registerOffset = r - (*registerBase);
2329         registerFile->setSafeForReentry(true);
2330         debug(exec, vPC, codeBlock, scopeChain, registerBase, r);
2331         registerFile->setSafeForReentry(false);
2332         r = (*registerBase) + registerOffset;
2333
2334         vPC += 4;
2335         NEXT_OPCODE;
2336     }
2337     vm_throw: {
2338         exec->clearException();
2339         handlerVPC = throwException(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r);
2340         if (!handlerVPC) {
2341             *exception = exceptionValue;
2342             return jsNull();
2343         }
2344         vPC = handlerVPC;
2345         NEXT_OPCODE;
2346     }          
2347     }
2348     #undef NEXT_OPCODE
2349     #undef BEGIN_OPCODE
2350     #undef VM_CHECK_EXCEPTION
2351 }
2352
2353 JSValue* Machine::retrieveArguments(ExecState* exec, FunctionImp* function) const
2354 {
2355     Register** registerBase;
2356     int callFrameOffset;
2357
2358     if (!getCallFrame(exec, function, registerBase, callFrameOffset))
2359         return jsNull();
2360
2361     Register* callFrame = (*registerBase) + callFrameOffset;
2362     JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue);
2363     if (!activation) {
2364         CodeBlock* codeBlock = &function->body->generatedCode();
2365         activation = new JSActivation(function->body, registerBase, callFrameOffset + CallFrameHeaderSize + codeBlock->numLocals);
2366         callFrame[OptionalCalleeActivation].u.jsValue = activation;
2367     }
2368
2369     return activation->get(exec, exec->propertyNames().arguments);
2370 }
2371
2372 JSValue* Machine::retrieveCaller(ExecState* exec, FunctionImp* function) const
2373 {
2374     Register** registerBase;
2375     int callFrameOffset;
2376
2377     if (!getCallFrame(exec, function, registerBase, callFrameOffset))
2378         return jsNull();
2379
2380     int callerFrameOffset;
2381     if (!getCallerFunctionOffset(registerBase, callFrameOffset, callerFrameOffset))
2382         return jsNull();
2383
2384     Register* callerFrame = (*registerBase) + callerFrameOffset;
2385     ASSERT(callerFrame[Callee].u.jsValue);
2386     return callerFrame[Callee].u.jsValue;
2387 }
2388
2389 bool Machine::getCallFrame(ExecState* exec, FunctionImp* function, Register**& registerBase, int& callFrameOffset) const
2390 {
2391     callFrameOffset = exec->m_callFrameOffset;
2392
2393     while (1) {
2394         while (callFrameOffset < 0) {
2395             exec = exec->m_prev;
2396             if (!exec)
2397                 return false;
2398             callFrameOffset = exec->m_callFrameOffset;
2399         }
2400
2401         registerBase = exec->m_registerFile->basePointer();
2402         Register* callFrame = (*registerBase) + callFrameOffset;
2403         if (callFrame[Callee].u.jsValue == function)
2404             return true;
2405
2406         if (!getCallerFunctionOffset(registerBase, callFrameOffset, callFrameOffset))
2407             callFrameOffset = -1;
2408     }
2409 }
2410
2411 void Machine::getFunctionAndArguments(Register** registerBase, Register* callFrame, FunctionImp*& function, Register*& argv, int& argc)
2412 {
2413     function = static_cast<FunctionImp*>(callFrame[Callee].u.jsValue);
2414     ASSERT(function->inherits(&FunctionImp::info));
2415
2416     argv = (*registerBase) + callFrame[CallerRegisterOffset].u.i + callFrame[ArgumentStartRegister].u.i + 1; // skip "this"
2417     argc = callFrame[ArgumentCount].u.i - 1; // skip "this"
2418 }
2419
2420 } // namespace KJS