OSDN Git Service

remove unused JSC::MasqueradesAsUndefined enum
[kde/Katie.git] / src / 3rdparty / javascriptcore / interpreter / Interpreter.cpp
1 /*
2  * Copyright (C) 2008, 2009 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 "Platform.h"
31 #include "Interpreter.h"
32
33 #include "Arguments.h"
34 #include "BatchedTransitionOptimizer.h"
35 #include "CallFrame.h"
36 #include "CallFrameClosure.h"
37 #include "CodeBlock.h"
38 #include "Collector.h"
39 #include "Debugger.h"
40 #include "DebuggerCallFrame.h"
41 #include "EvalCodeCache.h"
42 #include "ExceptionHelpers.h"
43 #include "GlobalEvalFunction.h"
44 #include "JSActivation.h"
45 #include "JSArray.h"
46 #include "JSByteArray.h"
47 #include "JSFunction.h"
48 #include "JSNotAnObject.h"
49 #include "JSPropertyNameIterator.h"
50 #include "LiteralParser.h"
51 #include "JSStaticScopeObject.h"
52 #include "JSString.h"
53 #include "ObjectPrototype.h"
54 #include "Operations.h"
55 #include "Parser.h"
56 #include "RegExpObject.h"
57 #include "RegExpPrototype.h"
58 #include "Register.h"
59 #include "SamplingTool.h"
60 #include <wtf/Threading.h>
61
62 #include "qscriptobject_p.h"
63
64 #include <limits.h>
65 #include <stdio.h>
66
67 using namespace std;
68
69 namespace JSC {
70
71 static ALWAYS_INLINE unsigned bytecodeOffsetForPC(CodeBlock* codeBlock, void* pc)
72 {
73     return static_cast<Instruction*>(pc) - codeBlock->instructions().begin();
74 }
75
76 // Returns the depth of the scope chain within a given call frame.
77 static int depth(CodeBlock* codeBlock, ScopeChain& sc)
78 {
79     if (!codeBlock->needsFullScopeChain())
80         return 0;
81     return sc.localDepth();
82 }
83
84 NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
85 {
86     int dst = vPC[1].u.operand;
87     int property = vPC[2].u.operand;
88
89     ScopeChainNode* scopeChain = callFrame->scopeChain();
90     ScopeChainIterator iter = scopeChain->begin();
91     ScopeChainIterator end = scopeChain->end();
92     Q_ASSERT(iter != end);
93
94     CodeBlock* codeBlock = callFrame->codeBlock();
95     Identifier& ident = codeBlock->identifier(property);
96     do {
97         JSObject* o = *iter;
98         PropertySlot slot(o);
99         if (o->getPropertySlot(callFrame, ident, slot)) {
100             JSValue result = slot.getValue(callFrame, ident);
101             exceptionValue = callFrame->globalData().exception;
102             if (exceptionValue)
103                 return false;
104             callFrame->r(dst) = JSValue(result);
105             return true;
106         }
107     } while (++iter != end);
108     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
109     return false;
110 }
111
112 NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
113 {
114     CodeBlock* codeBlock = callFrame->codeBlock();
115
116     int dst = vPC[1].u.operand;
117     int property = vPC[2].u.operand;
118     int skip = vPC[3].u.operand + codeBlock->needsFullScopeChain();
119
120     ScopeChainNode* scopeChain = callFrame->scopeChain();
121     ScopeChainIterator iter = scopeChain->begin();
122     ScopeChainIterator end = scopeChain->end();
123     Q_ASSERT(iter != end);
124     while (skip--) {
125         ++iter;
126         Q_ASSERT(iter != end);
127     }
128     Identifier& ident = codeBlock->identifier(property);
129     do {
130         JSObject* o = *iter;
131         PropertySlot slot(o);
132         if (o->getPropertySlot(callFrame, ident, slot)) {
133             JSValue result = slot.getValue(callFrame, ident);
134             exceptionValue = callFrame->globalData().exception;
135             if (exceptionValue)
136                 return false;
137             callFrame->r(dst) = JSValue(result);
138             return true;
139         }
140     } while (++iter != end);
141     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
142     return false;
143 }
144
145 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
146 {
147     int dst = vPC[1].u.operand;
148     JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(vPC[2].u.jsCell);
149     Q_ASSERT(globalObject->isGlobalObject());
150     int property = vPC[3].u.operand;
151     Structure* structure = vPC[4].u.structure;
152     int offset = vPC[5].u.operand;
153
154     if (structure == globalObject->structure()) {
155         callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
156         return true;
157     }
158
159     CodeBlock* codeBlock = callFrame->codeBlock();
160     Identifier& ident = codeBlock->identifier(property);
161     PropertySlot slot(globalObject);
162     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
163         JSValue result = slot.getValue(callFrame, ident);
164         if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
165             if (vPC[4].u.structure)
166                 vPC[4].u.structure->deref();
167             globalObject->structure()->ref();
168             vPC[4] = globalObject->structure();
169             vPC[5] = slot.cachedOffset();
170             callFrame->r(dst) = JSValue(result);
171             return true;
172         }
173
174         exceptionValue = callFrame->globalData().exception;
175         if (exceptionValue)
176             return false;
177         callFrame->r(dst) = JSValue(result);
178         return true;
179     }
180
181     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
182     return false;
183 }
184
185 NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
186 {
187     int dst = vPC[1].u.operand;
188     int property = vPC[2].u.operand;
189     callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
190 }
191
192 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
193 {
194     int baseDst = vPC[1].u.operand;
195     int propDst = vPC[2].u.operand;
196     int property = vPC[3].u.operand;
197
198     ScopeChainNode* scopeChain = callFrame->scopeChain();
199     ScopeChainIterator iter = scopeChain->begin();
200     ScopeChainIterator end = scopeChain->end();
201
202     // FIXME: add scopeDepthIsZero optimization
203
204     Q_ASSERT(iter != end);
205
206     CodeBlock* codeBlock = callFrame->codeBlock();
207     Identifier& ident = codeBlock->identifier(property);
208     JSObject* base;
209     do {
210         base = *iter;
211         PropertySlot slot(base);
212         if (base->getPropertySlot(callFrame, ident, slot)) {
213             JSValue result = slot.getValue(callFrame, ident);
214             exceptionValue = callFrame->globalData().exception;
215             if (exceptionValue)
216                 return false;
217             callFrame->r(propDst) = JSValue(result);
218             callFrame->r(baseDst) = JSValue(base);
219             return true;
220         }
221         ++iter;
222     } while (iter != end);
223
224     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
225     return false;
226 }
227
228 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
229 {
230     Register* r = callFrame->registers();
231     Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters;
232
233     if (Q_LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments
234         if (Q_UNLIKELY(!registerFile->grow(newEnd)))
235             return 0;
236         r += registerOffset;
237     } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks
238         size_t omittedArgCount = newCodeBlock->m_numParameters - argc;
239         registerOffset += omittedArgCount;
240         newEnd += omittedArgCount;
241         if (!registerFile->grow(newEnd))
242             return 0;
243         r += registerOffset;
244
245         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
246         for (size_t i = 0; i < omittedArgCount; ++i)
247             argv[i] = jsUndefined();
248     } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
249         size_t numParameters = newCodeBlock->m_numParameters;
250         registerOffset += numParameters;
251         newEnd += numParameters;
252
253         if (!registerFile->grow(newEnd))
254             return 0;
255         r += registerOffset;
256
257         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
258         for (size_t i = 0; i < numParameters; ++i)
259             argv[i + argc] = argv[i];
260     }
261
262     return CallFrame::create(r);
263 }
264
265 static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
266 {
267     if (value.isObject())
268         return false;
269     exceptionData = createInvalidParamError(callFrame, "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
270     return true;
271 }
272
273 static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
274 {
275     if (value.isObject() && asObject(value)->structure()->typeInfo().implementsHasInstance())
276         return false;
277     exceptionData = createInvalidParamError(callFrame, "instanceof" , value, vPC - codeBlock->instructions().begin(), codeBlock);
278     return true;
279 }
280
281 NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue& exceptionValue)
282 {
283     if (argc < 2)
284         return jsUndefined();
285
286     JSValue program = argv[1].jsValue();
287
288     if (!program.isString())
289         return program;
290
291     UString programSource = asString(program)->value(callFrame);
292
293     LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
294     if (JSValue parsedObject = preparser.tryLiteralParse())
295         return parsedObject;
296
297     ScopeChainNode* scopeChain = callFrame->scopeChain();
298     CodeBlock* codeBlock = callFrame->codeBlock();
299     RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
300
301     JSValue result = jsUndefined();
302     if (eval)
303         result = callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
304
305     return result;
306 }
307
308 Interpreter::Interpreter()
309     : m_sampleEntryDepth(0)
310     , m_reentryDepth(0)
311 {
312 #if ENABLE(OPCODE_SAMPLING)
313     enableSampler();
314 #endif
315 }
316
317 #ifndef QT_NO_DEBUG
318
319 void Interpreter::dumpCallFrame(CallFrame* callFrame)
320 {
321     callFrame->codeBlock()->dump(callFrame);
322     dumpRegisters(callFrame);
323 }
324
325 void Interpreter::dumpRegisters(CallFrame* callFrame)
326 {
327     printf("Register frame: \n\n");
328     printf("-----------------------------------------------------------------------------\n");
329     printf("            use            |   address  |                value               \n");
330     printf("-----------------------------------------------------------------------------\n");
331
332     CodeBlock* codeBlock = callFrame->codeBlock();
333     RegisterFile* registerFile = &callFrame->scopeChain()->globalObject->globalData()->interpreter->registerFile();
334     const Register* it;
335     const Register* end;
336     JSValue v;
337
338     if (codeBlock->codeType() == GlobalCode) {
339         it = registerFile->lastGlobal();
340         end = it + registerFile->numGlobals();
341         while (it != end) {
342             v = (*it).jsValue();
343 #if USE(JSVALUE32_64)
344             printf("[global var]               | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
345 #else
346             printf("[global var]               | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
347 #endif
348             ++it;
349         }
350         printf("-----------------------------------------------------------------------------\n");
351     }
352     
353     it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
354     v = (*it).jsValue();
355 #if USE(JSVALUE32_64)
356     printf("[this]                     | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it;
357 #else
358     printf("[this]                     | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it;
359 #endif
360     end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"
361     if (it != end) {
362         do {
363             v = (*it).jsValue();
364 #if USE(JSVALUE32_64)
365             printf("[param]                    | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
366 #else
367             printf("[param]                    | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
368 #endif
369             ++it;
370         } while (it != end);
371     }
372     printf("-----------------------------------------------------------------------------\n");
373     printf("[CodeBlock]                | %10p | %p \n", it, (*it).codeBlock()); ++it;
374     printf("[ScopeChain]               | %10p | %p \n", it, (*it).scopeChain()); ++it;
375     printf("[CallerRegisters]          | %10p | %d \n", it, (*it).i()); ++it;
376     printf("[ReturnPC]                 | %10p | %p \n", it, (*it).vPC()); ++it;
377     printf("[ReturnValueRegister]      | %10p | %d \n", it, (*it).i()); ++it;
378     printf("[ArgumentCount]            | %10p | %d \n", it, (*it).i()); ++it;
379     printf("[Callee]                   | %10p | %p \n", it, (*it).object()); ++it;
380     printf("[OptionalCalleeArguments]  | %10p | %p \n", it, (*it).arguments()); ++it;
381     printf("-----------------------------------------------------------------------------\n");
382
383     int registerCount = 0;
384
385     end = it + codeBlock->m_numVars;
386     if (it != end) {
387         do {
388             v = (*it).jsValue();
389 #if USE(JSVALUE32_64)
390             printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
391 #else
392             printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
393 #endif
394             ++it;
395             ++registerCount;
396         } while (it != end);
397     }
398     printf("-----------------------------------------------------------------------------\n");
399
400     end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
401     if (it != end) {
402         do {
403             v = (*it).jsValue();
404 #if USE(JSVALUE32_64)
405             printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
406 #else
407             printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
408 #endif
409             ++it;
410             ++registerCount;
411         } while (it != end);
412     }
413     printf("-----------------------------------------------------------------------------\n");
414 }
415
416 #endif
417
418 NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
419 {
420     CodeBlock* oldCodeBlock = codeBlock;
421     ScopeChainNode* scopeChain = callFrame->scopeChain();
422
423     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
424         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
425         if (callFrame->callee()) {
426             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
427             debugger->functionExit(exceptionValue, codeBlock->ownerExecutable()->sourceID());
428         } else
429             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
430     }
431
432     // If this call frame created an activation or an 'arguments' object, tear it off.
433     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
434         while (!scopeChain->object->inherits(&JSActivation::info))
435             scopeChain = scopeChain->pop();
436         static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments());
437     } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) {
438         if (!arguments->isTornOff())
439             arguments->copyRegisters();
440     }
441
442     if (oldCodeBlock->needsFullScopeChain())
443         scopeChain->deref();
444
445     void* returnPC = callFrame->returnPC();
446     callFrame = callFrame->callerFrame();
447     if (callFrame->hasHostCallFrameFlag())
448         return false;
449
450     codeBlock = callFrame->codeBlock();
451     bytecodeOffset = bytecodeOffsetForPC(codeBlock, returnPC);
452     return true;
453 }
454
455 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
456 {
457     // Set up the exception object
458
459     CodeBlock* codeBlock = callFrame->codeBlock();
460     if (exceptionValue.isObject()) {
461         JSObject* exception = asObject(exceptionValue);
462         if (exception->isNotAnObjectErrorStub()) {
463             exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock);
464             exceptionValue = exception;
465         } else {
466             if (!exception->hasProperty(callFrame, Identifier(callFrame, JSC_ERROR_LINENUMBER_PROPERTYNAME)) && 
467                 !exception->hasProperty(callFrame, Identifier(callFrame, "sourceId")) && 
468                 !exception->hasProperty(callFrame, Identifier(callFrame, JSC_ERROR_FILENAME_PROPERTYNAME)) && 
469                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName)) && 
470                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionCaretOffsetPropertyName)) && 
471                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName))) {
472                 if (explicitThrow) {
473                     int startOffset = 0;
474                     int endOffset = 0;
475                     int divotPoint = 0;
476                     int line = codeBlock->expressionRangeForBytecodeOffset(callFrame, bytecodeOffset, divotPoint, startOffset, endOffset);
477                     exception->putWithAttributes(callFrame, Identifier(callFrame, JSC_ERROR_LINENUMBER_PROPERTYNAME), jsNumber(callFrame, line), ReadOnly | DontDelete);
478                     
479                     // We only hit this path for error messages and throw statements, which don't have a specific failure position
480                     // So we just give the full range of the error/throw statement.
481                     exception->putWithAttributes(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName), jsNumber(callFrame, divotPoint - startOffset), ReadOnly | DontDelete);
482                     exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete);
483                 } else
484                     exception->putWithAttributes(callFrame, Identifier(callFrame, JSC_ERROR_LINENUMBER_PROPERTYNAME), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete);
485                 exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerExecutable()->sourceID()), ReadOnly | DontDelete);
486                 exception->putWithAttributes(callFrame, Identifier(callFrame, JSC_ERROR_FILENAME_PROPERTYNAME), jsOwnedString(callFrame, codeBlock->ownerExecutable()->sourceURL()), ReadOnly | DontDelete);
487             }
488             
489             if (exception->isWatchdogException()) {
490                 while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
491                     // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
492                 }
493                 return 0;
494             }
495         }
496     }
497
498     Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
499     if (debugger) {
500         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
501         bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
502         debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset), hasHandler);
503     }
504
505     // Calculate an exception handler vPC, unwinding call frames as necessary.
506
507     HandlerInfo* handler = 0;
508
509     //try to find handler
510     bool hasHandler = true;
511     CallFrame *callFrameTemp = callFrame;
512     unsigned bytecodeOffsetTemp = bytecodeOffset;
513     CodeBlock *codeBlockTemp = codeBlock;
514     while (!(handler = codeBlockTemp->handlerForBytecodeOffset(bytecodeOffsetTemp))) {
515         void* returnPC = callFrameTemp->returnPC();
516         callFrameTemp = callFrameTemp->callerFrame();
517         if (callFrameTemp->hasHostCallFrameFlag()) {
518             hasHandler = false;
519             break;
520         } else {
521             codeBlockTemp = callFrameTemp->codeBlock();
522             bytecodeOffsetTemp = bytecodeOffsetForPC(codeBlockTemp, returnPC);
523         }
524     }
525     if (debugger)
526         debugger->exceptionThrow(DebuggerCallFrame(callFrame, exceptionValue), codeBlock->ownerExecutable()->sourceID(), hasHandler);
527
528     while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
529         if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
530             return 0;
531         }
532     }
533     // Now unwind the scope chain within the exception handler's call frame.
534
535     ScopeChainNode* scopeChain = callFrame->scopeChain();
536     ScopeChain sc(scopeChain);
537     int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
538     Q_ASSERT(scopeDelta >= 0);
539     while (scopeDelta--)
540         scopeChain = scopeChain->pop();
541     callFrame->setScopeChain(scopeChain);
542
543     return handler;
544 }
545
546 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
547 {
548     Q_ASSERT(!scopeChain->globalData->exception);
549
550     if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
551         if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
552             *exception = createStackOverflowError(callFrame);
553             return jsNull();
554         }
555     }
556
557     CodeBlock* codeBlock = &program->bytecode(callFrame, scopeChain);
558
559     Register* oldEnd = m_registerFile.end();
560     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
561     if (!m_registerFile.grow(newEnd)) {
562         *exception = createStackOverflowError(callFrame);
563         return jsNull();
564     }
565
566     DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
567
568     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
569     JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
570     globalObject->copyGlobalsTo(m_registerFile);
571
572     CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
573     newCallFrame->r(codeBlock->thisRegister()) = JSValue(thisObj);
574     newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0);
575
576     if (codeBlock->needsFullScopeChain())
577         scopeChain->ref();
578
579     JSValue result;
580     {
581         SamplingTool::CallRecord callRecord(m_sampler.get());
582
583         m_reentryDepth++;
584         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
585         m_reentryDepth--;
586     }
587
588     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
589         lastGlobalObject->copyGlobalsTo(m_registerFile);
590
591     m_registerFile.shrink(oldEnd);
592
593     return result;
594 }
595
596 JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception)
597 {
598     Q_ASSERT(!scopeChain->globalData->exception);
599
600     if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
601         if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
602             *exception = createStackOverflowError(callFrame);
603             return jsNull();
604         }
605     }
606
607     Register* oldEnd = m_registerFile.end();
608     int argc = 1 + args.size(); // implicit "this" parameter
609
610     if (!m_registerFile.grow(oldEnd + argc)) {
611         *exception = createStackOverflowError(callFrame);
612         return jsNull();
613     }
614
615     DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
616
617     CallFrame* newCallFrame = CallFrame::create(oldEnd);
618     size_t dst = 0;
619     newCallFrame->r(0) = JSValue(thisObj);
620     ArgList::const_iterator end = args.end();
621     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
622         newCallFrame->r(++dst) = *it;
623
624     CodeBlock* codeBlock = &functionExecutable->bytecode(callFrame, scopeChain);
625     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
626     if (Q_UNLIKELY(!newCallFrame)) {
627         *exception = createStackOverflowError(callFrame);
628         m_registerFile.shrink(oldEnd);
629         return jsNull();
630     }
631     // a 0 codeBlock indicates a built-in caller
632     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
633
634     JSValue result;
635     {
636         SamplingTool::CallRecord callRecord(m_sampler.get());
637
638         m_reentryDepth++;
639         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
640         m_reentryDepth--;
641     }
642
643     m_registerFile.shrink(oldEnd);
644     return result;
645 }
646
647 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception)
648 {
649     Q_ASSERT(!scopeChain->globalData->exception);
650     
651     if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
652         if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
653             *exception = createStackOverflowError(callFrame);
654             return CallFrameClosure();
655         }
656     }
657     
658     Register* oldEnd = m_registerFile.end();
659     int argc = 1 + argCount; // implicit "this" parameter
660     
661     if (!m_registerFile.grow(oldEnd + argc)) {
662         *exception = createStackOverflowError(callFrame);
663         return CallFrameClosure();
664     }
665
666     CallFrame* newCallFrame = CallFrame::create(oldEnd);
667     size_t dst = 0;
668     for (int i = 0; i < argc; ++i)
669         newCallFrame->r(++dst) = jsUndefined();
670     
671     CodeBlock* codeBlock = &FunctionExecutable->bytecode(callFrame, scopeChain);
672     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
673     if (Q_UNLIKELY(!newCallFrame)) {
674         *exception = createStackOverflowError(callFrame);
675         m_registerFile.shrink(oldEnd);
676         return CallFrameClosure();
677     }
678     // a 0 codeBlock indicates a built-in caller
679     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
680
681     CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
682     return result;
683 }
684
685 JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception) 
686 {
687     closure.resetCallFrame();
688
689     JSValue result;
690     {
691         SamplingTool::CallRecord callRecord(m_sampler.get());
692
693         m_reentryDepth++;
694         result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
695         m_reentryDepth--;
696     }
697
698     return result;
699 }
700
701 void Interpreter::endRepeatCall(CallFrameClosure& closure)
702 {
703     m_registerFile.shrink(closure.oldEnd);
704 }
705
706 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
707 {
708     return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->bytecode(callFrame, scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
709 }
710
711 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
712 {
713     Q_ASSERT(!scopeChain->globalData->exception);
714
715     if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
716         if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
717             *exception = createStackOverflowError(callFrame);
718             return jsNull();
719         }
720     }
721
722     DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
723
724     EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain);
725
726     JSVariableObject* variableObject;
727     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
728         Q_ASSERT(node);
729         if (node->object->isVariableObject()) {
730             variableObject = static_cast<JSVariableObject*>(node->object);
731             break;
732         }
733     }
734
735     { // Scope for BatchedTransitionOptimizer
736
737         BatchedTransitionOptimizer optimizer(variableObject);
738
739         unsigned numVariables = codeBlock->numVariables();
740         for (unsigned i = 0; i < numVariables; ++i) {
741             const Identifier& ident = codeBlock->variable(i);
742             if (!variableObject->hasProperty(callFrame, ident)) {
743                 PutPropertySlot slot;
744                 variableObject->put(callFrame, ident, jsUndefined(), slot);
745             }
746         }
747
748         int numFunctions = codeBlock->numberOfFunctionDecls();
749         for (int i = 0; i < numFunctions; ++i) {
750             FunctionExecutable* function = codeBlock->functionDecl(i);
751             PutPropertySlot slot;
752             variableObject->put(callFrame, function->name(), function->make(callFrame, scopeChain), slot);
753         }
754
755     }
756
757     Register* oldEnd = m_registerFile.end();
758     // with QtScript, we do not necesserly start from scratch
759     Register* newEnd = oldEnd + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
760     if (!m_registerFile.grow(newEnd)) {
761         *exception = createStackOverflowError(callFrame);
762         return jsNull();
763     }
764
765     // with QtScript, we do not necesserly start from scratch
766     CallFrame* newCallFrame = CallFrame::create(oldEnd + globalRegisterOffset);
767
768     // a 0 codeBlock indicates a built-in caller
769     newCallFrame->r(codeBlock->thisRegister()) = JSValue(thisObj);
770     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0);
771
772     if (codeBlock->needsFullScopeChain())
773         scopeChain->ref();
774
775     JSValue result;
776     {
777         SamplingTool::CallRecord callRecord(m_sampler.get());
778
779         m_reentryDepth++;
780         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
781         m_reentryDepth--;
782     }
783
784     m_registerFile.shrink(oldEnd);
785     return result;
786 }
787
788 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
789 {
790     Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
791     if (!debugger)
792         return;
793
794     switch (debugHookID) {
795         case DidEnterCallFrame:
796             debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
797             return;
798         case WillLeaveCallFrame:
799             debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
800             return;
801         case WillExecuteStatement:
802             debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
803             return;
804         case WillExecuteProgram:
805             debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
806             return;
807         case DidExecuteProgram:
808             debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
809             return;
810         case DidReachBreakpoint:
811             debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
812             return;
813     }
814 }
815
816 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
817 {
818     int dst = vPC[1].u.operand;
819     CodeBlock* codeBlock = callFrame->codeBlock();
820     Identifier& property = codeBlock->identifier(vPC[2].u.operand);
821     JSValue value = callFrame->r(vPC[3].u.operand).jsValue();
822     JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
823     callFrame->r(dst) = JSValue(scope);
824
825     return callFrame->scopeChain()->push(scope);
826 }
827
828 NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const PutPropertySlot& slot)
829 {
830     // Recursive invocation may already have specialized this instruction.
831     if (vPC[0].u.opcode != op_put_by_id)
832         return;
833
834     if (!baseValue.isCell())
835         return;
836
837     // Uncacheable: give up.
838     if (!slot.isCacheable()) {
839         vPC[0] = op_put_by_id_generic;
840         return;
841     }
842     
843     JSCell* baseCell = baseValue.asCell();
844     Structure* structure = baseCell->structure();
845
846     if (structure->isUncacheableDictionary()) {
847         vPC[0] = op_put_by_id_generic;
848         return;
849     }
850
851     // Cache miss: record Structure to compare against next time.
852     Structure* lastStructure = vPC[4].u.structure;
853     if (structure != lastStructure) {
854         // First miss: record Structure to compare against next time.
855         if (!lastStructure) {
856             vPC[4] = structure;
857             return;
858         }
859
860         // Second miss: give up.
861         vPC[0] = op_put_by_id_generic;
862         return;
863     }
864
865     // Cache hit: Specialize instruction and ref Structures.
866
867     // If baseCell != slot.base(), then baseCell must be a proxy for another object.
868     if (baseCell != slot.base()) {
869         vPC[0] = op_put_by_id_generic;
870         return;
871     }
872
873     // Structure transition, cache transition info
874     if (slot.type() == PutPropertySlot::NewProperty) {
875         if (structure->isDictionary()) {
876             vPC[0] = op_put_by_id_generic;
877             return;
878         }
879
880         // put_by_id_transition checks the prototype chain for setters.
881         normalizePrototypeChain(callFrame, baseCell);
882
883         vPC[0] = op_put_by_id_transition;
884         vPC[4] = structure->previousID();
885         vPC[5] = structure;
886         vPC[6] = structure->prototypeChain(callFrame);
887         vPC[7] = slot.cachedOffset();
888         codeBlock->refStructures(vPC);
889         return;
890     }
891
892     vPC[0] = op_put_by_id_replace;
893     vPC[5] = slot.cachedOffset();
894     codeBlock->refStructures(vPC);
895 }
896
897 NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC)
898 {
899     codeBlock->derefStructures(vPC);
900     vPC[0] = op_put_by_id;
901     vPC[4] = 0;
902 }
903
904 NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot)
905 {
906     // Recursive invocation may already have specialized this instruction.
907     if (vPC[0].u.opcode != op_get_by_id)
908         return;
909
910     // FIXME: Cache property access for immediates.
911     if (!baseValue.isCell()) {
912         vPC[0] = op_get_by_id_generic;
913         return;
914     }
915
916     JSGlobalData* globalData = &callFrame->globalData();
917     if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
918         vPC[0] = op_get_array_length;
919         return;
920     }
921
922     if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
923         vPC[0] = op_get_string_length;
924         return;
925     }
926
927     // Uncacheable: give up.
928     if (!slot.isCacheable()) {
929         vPC[0] = op_get_by_id_generic;
930         return;
931     }
932
933     Structure* structure = baseValue.asCell()->structure();
934
935     if (structure->isUncacheableDictionary()) {
936         vPC[0] = op_get_by_id_generic;
937         return;
938     }
939
940     // Cache miss
941     Structure* lastStructure = vPC[4].u.structure;
942     if (structure != lastStructure) {
943         // First miss: record Structure to compare against next time.
944         if (!lastStructure) {
945             vPC[4] = structure;
946             return;
947         }
948
949         // Second miss: give up.
950         vPC[0] = op_get_by_id_generic;
951         return;
952     }
953
954     // Cache hit: Specialize instruction and ref Structures.
955
956     if (slot.slotBase() == baseValue) {
957         vPC[0] = op_get_by_id_self;
958         vPC[5] = slot.cachedOffset();
959
960         codeBlock->refStructures(vPC);
961         return;
962     }
963
964     if (structure->isDictionary()) {
965         vPC[0] = op_get_by_id_generic;
966         return;
967     }
968
969     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
970         Q_ASSERT(slot.slotBase().isObject());
971
972         JSObject* baseObject = asObject(slot.slotBase());
973         size_t offset = slot.cachedOffset();
974
975         // Since we're accessing a prototype in a loop, it's a good bet that it
976         // should not be treated as a dictionary.
977         if (baseObject->structure()->isDictionary()) {
978             baseObject->flattenDictionaryObject();
979             offset = baseObject->structure()->get(propertyName);
980         }
981
982         Q_ASSERT(!baseObject->structure()->isUncacheableDictionary());
983
984         vPC[0] = op_get_by_id_proto;
985         vPC[5] = baseObject->structure();
986         vPC[6] = offset;
987
988         codeBlock->refStructures(vPC);
989         return;
990     }
991
992     size_t offset = slot.cachedOffset();
993     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
994     if (!count) {
995         vPC[0] = op_get_by_id_generic;
996         return;
997     }
998
999     vPC[0] = op_get_by_id_chain;
1000     vPC[4] = structure;
1001     vPC[5] = structure->prototypeChain(callFrame);
1002     vPC[6] = count;
1003     vPC[7] = offset;
1004     codeBlock->refStructures(vPC);
1005 }
1006
1007 NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC)
1008 {
1009     codeBlock->derefStructures(vPC);
1010     vPC[0] = op_get_by_id;
1011     vPC[4] = 0;
1012 }
1013
1014 JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue* exception)
1015 {
1016     // One-time initialization of our address tables. We have to put this code
1017     // here because our labels are only in scope inside this function.
1018     if (Q_UNLIKELY(flag == InitializeAndReturn)) {
1019         return JSValue();
1020     }
1021
1022     JSGlobalData* globalData = &callFrame->globalData();
1023     JSValue exceptionValue;
1024     HandlerInfo* handler = 0;
1025
1026     Instruction* vPC = callFrame->codeBlock()->instructions().begin();
1027     unsigned tickCount = globalData->timeoutChecker->ticksUntilNextCheck();
1028
1029 #define CHECK_FOR_EXCEPTION() \
1030     do { \
1031         if (Q_UNLIKELY(globalData->exception != JSValue())) { \
1032             exceptionValue = globalData->exception; \
1033             goto vm_throw; \
1034         } \
1035     } while (0)
1036
1037 #if ENABLE(OPCODE_STATS)
1038     OpcodeStats::resetLastInstruction();
1039 #endif
1040
1041 #define CHECK_FOR_TIMEOUT() \
1042     if (!--tickCount) { \
1043         if (globalData->timeoutChecker->didTimeOut(callFrame)) { \
1044             exceptionValue = jsNull(); \
1045             goto vm_throw; \
1046         } \
1047         tickCount = globalData->timeoutChecker->ticksUntilNextCheck(); \
1048         CHECK_FOR_EXCEPTION(); \
1049     }
1050     
1051 #if ENABLE(OPCODE_SAMPLING)
1052     #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)
1053 #else
1054     #define SAMPLE(codeBlock, vPC)
1055 #endif
1056
1057 #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto interpreterLoopStart
1058 #if ENABLE(OPCODE_STATS)
1059     #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1060 #else
1061     #define DEFINE_OPCODE(opcode) case opcode:
1062 #endif
1063     while (1) { // iterator loop begins
1064     interpreterLoopStart:;
1065     switch (vPC->u.opcode)
1066     {
1067     DEFINE_OPCODE(op_new_object) {
1068         /* new_object dst(r)
1069
1070            Constructs a new empty Object instance using the original
1071            constructor, and puts the result in register dst.
1072         */
1073         int dst = vPC[1].u.operand;
1074         callFrame->r(dst) = JSValue(constructEmptyObject(callFrame));
1075
1076         vPC += OPCODE_LENGTH(op_new_object);
1077         NEXT_INSTRUCTION();
1078     }
1079     DEFINE_OPCODE(op_new_array) {
1080         /* new_array dst(r) firstArg(r) argCount(n)
1081
1082            Constructs a new Array instance using the original
1083            constructor, and puts the result in register dst.
1084            The array will contain argCount elements with values
1085            taken from registers starting at register firstArg.
1086         */
1087         int dst = vPC[1].u.operand;
1088         int firstArg = vPC[2].u.operand;
1089         int argCount = vPC[3].u.operand;
1090         ArgList args(callFrame->registers() + firstArg, argCount);
1091         callFrame->r(dst) = JSValue(constructArray(callFrame, args));
1092
1093         vPC += OPCODE_LENGTH(op_new_array);
1094         NEXT_INSTRUCTION();
1095     }
1096     DEFINE_OPCODE(op_new_regexp) {
1097         /* new_regexp dst(r) regExp(re)
1098
1099            Constructs a new RegExp instance using the original
1100            constructor from regexp regExp, and puts the result in
1101            register dst.
1102         */
1103         int dst = vPC[1].u.operand;
1104         int regExp = vPC[2].u.operand;
1105         callFrame->r(dst) = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
1106
1107         vPC += OPCODE_LENGTH(op_new_regexp);
1108         NEXT_INSTRUCTION();
1109     }
1110     DEFINE_OPCODE(op_mov) {
1111         /* mov dst(r) src(r)
1112
1113            Copies register src to register dst.
1114         */
1115         int dst = vPC[1].u.operand;
1116         int src = vPC[2].u.operand;
1117         callFrame->r(dst) = callFrame->r(src);
1118
1119         vPC += OPCODE_LENGTH(op_mov);
1120         NEXT_INSTRUCTION();
1121     }
1122     DEFINE_OPCODE(op_eq) {
1123         /* eq dst(r) src1(r) src2(r)
1124
1125            Checks whether register src1 and register src2 are equal,
1126            as with the ECMAScript '==' operator, and puts the result
1127            as a boolean in register dst.
1128         */
1129         int dst = vPC[1].u.operand;
1130         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1131         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1132         if (src1.isInt32() && src2.isInt32())
1133             callFrame->r(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
1134         else {
1135             JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2));
1136             CHECK_FOR_EXCEPTION();
1137             callFrame->r(dst) = result;
1138         }
1139
1140         vPC += OPCODE_LENGTH(op_eq);
1141         NEXT_INSTRUCTION();
1142     }
1143     DEFINE_OPCODE(op_eq_null) {
1144         /* eq_null dst(r) src(r)
1145
1146            Checks whether register src is null, as with the ECMAScript '!='
1147            operator, and puts the result as a boolean in register dst.
1148         */
1149         int dst = vPC[1].u.operand;
1150         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
1151
1152         if (src.isUndefinedOrNull()) {
1153             callFrame->r(dst) = jsBoolean(true);
1154             vPC += OPCODE_LENGTH(op_eq_null);
1155             NEXT_INSTRUCTION();
1156         }
1157         
1158         callFrame->r(dst) = jsBoolean(false);
1159         vPC += OPCODE_LENGTH(op_eq_null);
1160         NEXT_INSTRUCTION();
1161     }
1162     DEFINE_OPCODE(op_neq) {
1163         /* neq dst(r) src1(r) src2(r)
1164
1165            Checks whether register src1 and register src2 are not
1166            equal, as with the ECMAScript '!=' operator, and puts the
1167            result as a boolean in register dst.
1168         */
1169         int dst = vPC[1].u.operand;
1170         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1171         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1172         if (src1.isInt32() && src2.isInt32())
1173             callFrame->r(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
1174         else {
1175             JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2));
1176             CHECK_FOR_EXCEPTION();
1177             callFrame->r(dst) = result;
1178         }
1179
1180         vPC += OPCODE_LENGTH(op_neq);
1181         NEXT_INSTRUCTION();
1182     }
1183     DEFINE_OPCODE(op_neq_null) {
1184         /* neq_null dst(r) src(r)
1185
1186            Checks whether register src is not null, as with the ECMAScript '!='
1187            operator, and puts the result as a boolean in register dst.
1188         */
1189         int dst = vPC[1].u.operand;
1190         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
1191
1192         if (src.isUndefinedOrNull()) {
1193             callFrame->r(dst) = jsBoolean(false);
1194             vPC += OPCODE_LENGTH(op_neq_null);
1195             NEXT_INSTRUCTION();
1196         }
1197         
1198         callFrame->r(dst) = jsBoolean(!src.isCell());
1199         vPC += OPCODE_LENGTH(op_neq_null);
1200         NEXT_INSTRUCTION();
1201     }
1202     DEFINE_OPCODE(op_stricteq) {
1203         /* stricteq dst(r) src1(r) src2(r)
1204
1205            Checks whether register src1 and register src2 are strictly
1206            equal, as with the ECMAScript '===' operator, and puts the
1207            result as a boolean in register dst.
1208         */
1209         int dst = vPC[1].u.operand;
1210         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1211         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1212         callFrame->r(dst) = jsBoolean(JSValue::strictEqual(callFrame, src1, src2));
1213
1214         vPC += OPCODE_LENGTH(op_stricteq);
1215         NEXT_INSTRUCTION();
1216     }
1217     DEFINE_OPCODE(op_nstricteq) {
1218         /* nstricteq dst(r) src1(r) src2(r)
1219
1220            Checks whether register src1 and register src2 are not
1221            strictly equal, as with the ECMAScript '!==' operator, and
1222            puts the result as a boolean in register dst.
1223         */
1224         int dst = vPC[1].u.operand;
1225         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1226         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1227         callFrame->r(dst) = jsBoolean(!JSValue::strictEqual(callFrame, src1, src2));
1228
1229         vPC += OPCODE_LENGTH(op_nstricteq);
1230         NEXT_INSTRUCTION();
1231     }
1232     DEFINE_OPCODE(op_less) {
1233         /* less dst(r) src1(r) src2(r)
1234
1235            Checks whether register src1 is less than register src2, as
1236            with the ECMAScript '<' operator, and puts the result as
1237            a boolean in register dst.
1238         */
1239         int dst = vPC[1].u.operand;
1240         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1241         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1242         JSValue result = jsBoolean(jsLess(callFrame, src1, src2));
1243         CHECK_FOR_EXCEPTION();
1244         callFrame->r(dst) = result;
1245
1246         vPC += OPCODE_LENGTH(op_less);
1247         NEXT_INSTRUCTION();
1248     }
1249     DEFINE_OPCODE(op_lesseq) {
1250         /* lesseq dst(r) src1(r) src2(r)
1251
1252            Checks whether register src1 is less than or equal to
1253            register src2, as with the ECMAScript '<=' operator, and
1254            puts the result as a boolean in register dst.
1255         */
1256         int dst = vPC[1].u.operand;
1257         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1258         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1259         JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2));
1260         CHECK_FOR_EXCEPTION();
1261         callFrame->r(dst) = result;
1262
1263         vPC += OPCODE_LENGTH(op_lesseq);
1264         NEXT_INSTRUCTION();
1265     }
1266     DEFINE_OPCODE(op_pre_inc) {
1267         /* pre_inc srcDst(r)
1268
1269            Converts register srcDst to number, adds one, and puts the result
1270            back in register srcDst.
1271         */
1272         int srcDst = vPC[1].u.operand;
1273         JSValue v = callFrame->r(srcDst).jsValue();
1274         if (v.isInt32() && v.asInt32() < INT_MAX)
1275             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
1276         else {
1277             JSValue result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
1278             CHECK_FOR_EXCEPTION();
1279             callFrame->r(srcDst) = result;
1280         }
1281
1282         vPC += OPCODE_LENGTH(op_pre_inc);
1283         NEXT_INSTRUCTION();
1284     }
1285     DEFINE_OPCODE(op_pre_dec) {
1286         /* pre_dec srcDst(r)
1287
1288            Converts register srcDst to number, subtracts one, and puts the result
1289            back in register srcDst.
1290         */
1291         int srcDst = vPC[1].u.operand;
1292         JSValue v = callFrame->r(srcDst).jsValue();
1293         if (v.isInt32() && v.asInt32() > INT_MIN)
1294             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
1295         else {
1296             JSValue result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
1297             CHECK_FOR_EXCEPTION();
1298             callFrame->r(srcDst) = result;
1299         }
1300
1301         vPC += OPCODE_LENGTH(op_pre_dec);
1302         NEXT_INSTRUCTION();
1303     }
1304     DEFINE_OPCODE(op_post_inc) {
1305         /* post_inc dst(r) srcDst(r)
1306
1307            Converts register srcDst to number. The number itself is
1308            written to register dst, and the number plus one is written
1309            back to register srcDst.
1310         */
1311         int dst = vPC[1].u.operand;
1312         int srcDst = vPC[2].u.operand;
1313         JSValue v = callFrame->r(srcDst).jsValue();
1314         if (v.isInt32() && v.asInt32() < INT_MAX) {
1315             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
1316             callFrame->r(dst) = v;
1317         } else {
1318             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
1319             CHECK_FOR_EXCEPTION();
1320             callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() + 1);
1321             callFrame->r(dst) = number;
1322         }
1323
1324         vPC += OPCODE_LENGTH(op_post_inc);
1325         NEXT_INSTRUCTION();
1326     }
1327     DEFINE_OPCODE(op_post_dec) {
1328         /* post_dec dst(r) srcDst(r)
1329
1330            Converts register srcDst to number. The number itself is
1331            written to register dst, and the number minus one is written
1332            back to register srcDst.
1333         */
1334         int dst = vPC[1].u.operand;
1335         int srcDst = vPC[2].u.operand;
1336         JSValue v = callFrame->r(srcDst).jsValue();
1337         if (v.isInt32() && v.asInt32() > INT_MIN) {
1338             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
1339             callFrame->r(dst) = v;
1340         } else {
1341             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
1342             CHECK_FOR_EXCEPTION();
1343             callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() - 1);
1344             callFrame->r(dst) = number;
1345         }
1346
1347         vPC += OPCODE_LENGTH(op_post_dec);
1348         NEXT_INSTRUCTION();
1349     }
1350     DEFINE_OPCODE(op_to_jsnumber) {
1351         /* to_jsnumber dst(r) src(r)
1352
1353            Converts register src to number, and puts the result
1354            in register dst.
1355         */
1356         int dst = vPC[1].u.operand;
1357         int src = vPC[2].u.operand;
1358
1359         JSValue srcVal = callFrame->r(src).jsValue();
1360
1361         if (Q_LIKELY(srcVal.isNumber()))
1362             callFrame->r(dst) = callFrame->r(src);
1363         else {
1364             JSValue result = srcVal.toJSNumber(callFrame);
1365             CHECK_FOR_EXCEPTION();
1366             callFrame->r(dst) = result;
1367         }
1368
1369         vPC += OPCODE_LENGTH(op_to_jsnumber);
1370         NEXT_INSTRUCTION();
1371     }
1372     DEFINE_OPCODE(op_negate) {
1373         /* negate dst(r) src(r)
1374
1375            Converts register src to number, negates it, and puts the
1376            result in register dst.
1377         */
1378         int dst = vPC[1].u.operand;
1379         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
1380         if (src.isInt32() && src.asInt32())
1381             callFrame->r(dst) = jsNumber(callFrame, -src.asInt32());
1382         else {
1383             JSValue result = jsNumber(callFrame, -src.toNumber(callFrame));
1384             CHECK_FOR_EXCEPTION();
1385             callFrame->r(dst) = result;
1386         }
1387
1388         vPC += OPCODE_LENGTH(op_negate);
1389         NEXT_INSTRUCTION();
1390     }
1391     DEFINE_OPCODE(op_add) {
1392         /* add dst(r) src1(r) src2(r)
1393
1394            Adds register src1 and register src2, and puts the result
1395            in register dst. (JS add may be string concatenation or
1396            numeric add, depending on the types of the operands.)
1397         */
1398         int dst = vPC[1].u.operand;
1399         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1400         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1401         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
1402             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() + src2.asInt32());
1403         else {
1404             JSValue result = jsAdd(callFrame, src1, src2);
1405             CHECK_FOR_EXCEPTION();
1406             callFrame->r(dst) = result;
1407         }
1408         vPC += OPCODE_LENGTH(op_add);
1409         NEXT_INSTRUCTION();
1410     }
1411     DEFINE_OPCODE(op_mul) {
1412         /* mul dst(r) src1(r) src2(r)
1413
1414            Multiplies register src1 and register src2 (converted to
1415            numbers), and puts the product in register dst.
1416         */
1417         int dst = vPC[1].u.operand;
1418         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1419         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1420         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow
1421                 callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() * src2.asInt32());
1422         else {
1423             JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
1424             CHECK_FOR_EXCEPTION();
1425             callFrame->r(dst) = result;
1426         }
1427
1428         vPC += OPCODE_LENGTH(op_mul);
1429         NEXT_INSTRUCTION();
1430     }
1431     DEFINE_OPCODE(op_div) {
1432         /* div dst(r) dividend(r) divisor(r)
1433
1434            Divides register dividend (converted to number) by the
1435            register divisor (converted to number), and puts the
1436            quotient in register dst.
1437         */
1438         int dst = vPC[1].u.operand;
1439         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
1440         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
1441
1442         JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
1443         CHECK_FOR_EXCEPTION();
1444         callFrame->r(dst) = result;
1445
1446         vPC += OPCODE_LENGTH(op_div);
1447         NEXT_INSTRUCTION();
1448     }
1449     DEFINE_OPCODE(op_mod) {
1450         /* mod dst(r) dividend(r) divisor(r)
1451
1452            Divides register dividend (converted to number) by
1453            register divisor (converted to number), and puts the
1454            remainder in register dst.
1455         */
1456         int dst = vPC[1].u.operand;
1457         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
1458         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
1459
1460         if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) {
1461             JSValue result = jsNumber(callFrame, dividend.asInt32() % divisor.asInt32());
1462             Q_ASSERT(result);
1463             callFrame->r(dst) = result;
1464             vPC += OPCODE_LENGTH(op_mod);
1465             NEXT_INSTRUCTION();
1466         }
1467
1468         // Conversion to double must happen outside the call to fmod since the
1469         // order of argument evaluation is not guaranteed.
1470         double d1 = dividend.toNumber(callFrame);
1471         double d2 = divisor.toNumber(callFrame);
1472         JSValue result = jsNumber(callFrame, fmod(d1, d2));
1473         CHECK_FOR_EXCEPTION();
1474         callFrame->r(dst) = result;
1475         vPC += OPCODE_LENGTH(op_mod);
1476         NEXT_INSTRUCTION();
1477     }
1478     DEFINE_OPCODE(op_sub) {
1479         /* sub dst(r) src1(r) src2(r)
1480
1481            Subtracts register src2 (converted to number) from register
1482            src1 (converted to number), and puts the difference in
1483            register dst.
1484         */
1485         int dst = vPC[1].u.operand;
1486         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1487         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1488         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
1489             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() - src2.asInt32());
1490         else {
1491             JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
1492             CHECK_FOR_EXCEPTION();
1493             callFrame->r(dst) = result;
1494         }
1495         vPC += OPCODE_LENGTH(op_sub);
1496         NEXT_INSTRUCTION();
1497     }
1498     DEFINE_OPCODE(op_lshift) {
1499         /* lshift dst(r) val(r) shift(r)
1500
1501            Performs left shift of register val (converted to int32) by
1502            register shift (converted to uint32), and puts the result
1503            in register dst.
1504         */
1505         int dst = vPC[1].u.operand;
1506         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
1507         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
1508
1509         if (val.isInt32() && shift.isInt32())
1510             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() << (shift.asInt32() & 0x1f));
1511         else {
1512             JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
1513             CHECK_FOR_EXCEPTION();
1514             callFrame->r(dst) = result;
1515         }
1516
1517         vPC += OPCODE_LENGTH(op_lshift);
1518         NEXT_INSTRUCTION();
1519     }
1520     DEFINE_OPCODE(op_rshift) {
1521         /* rshift dst(r) val(r) shift(r)
1522
1523            Performs arithmetic right shift of register val (converted
1524            to int32) by register shift (converted to
1525            uint32), and puts the result in register dst.
1526         */
1527         int dst = vPC[1].u.operand;
1528         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
1529         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
1530
1531         if (val.isInt32() && shift.isInt32())
1532             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
1533         else {
1534             JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
1535             CHECK_FOR_EXCEPTION();
1536             callFrame->r(dst) = result;
1537         }
1538
1539         vPC += OPCODE_LENGTH(op_rshift);
1540         NEXT_INSTRUCTION();
1541     }
1542     DEFINE_OPCODE(op_urshift) {
1543         /* rshift dst(r) val(r) shift(r)
1544
1545            Performs logical right shift of register val (converted
1546            to uint32) by register shift (converted to
1547            uint32), and puts the result in register dst.
1548         */
1549         int dst = vPC[1].u.operand;
1550         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
1551         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
1552         if (val.isUInt32() && shift.isInt32())
1553             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
1554         else {
1555             JSValue result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
1556             CHECK_FOR_EXCEPTION();
1557             callFrame->r(dst) = result;
1558         }
1559
1560         vPC += OPCODE_LENGTH(op_urshift);
1561         NEXT_INSTRUCTION();
1562     }
1563     DEFINE_OPCODE(op_bitand) {
1564         /* bitand dst(r) src1(r) src2(r)
1565
1566            Computes bitwise AND of register src1 (converted to int32)
1567            and register src2 (converted to int32), and puts the result
1568            in register dst.
1569         */
1570         int dst = vPC[1].u.operand;
1571         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1572         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1573         if (src1.isInt32() && src2.isInt32())
1574             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() & src2.asInt32());
1575         else {
1576             JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
1577             CHECK_FOR_EXCEPTION();
1578             callFrame->r(dst) = result;
1579         }
1580
1581         vPC += OPCODE_LENGTH(op_bitand);
1582         NEXT_INSTRUCTION();
1583     }
1584     DEFINE_OPCODE(op_bitxor) {
1585         /* bitxor dst(r) src1(r) src2(r)
1586
1587            Computes bitwise XOR of register src1 (converted to int32)
1588            and register src2 (converted to int32), and puts the result
1589            in register dst.
1590         */
1591         int dst = vPC[1].u.operand;
1592         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1593         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1594         if (src1.isInt32() && src2.isInt32())
1595             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() ^ src2.asInt32());
1596         else {
1597             JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
1598             CHECK_FOR_EXCEPTION();
1599             callFrame->r(dst) = result;
1600         }
1601
1602         vPC += OPCODE_LENGTH(op_bitxor);
1603         NEXT_INSTRUCTION();
1604     }
1605     DEFINE_OPCODE(op_bitor) {
1606         /* bitor dst(r) src1(r) src2(r)
1607
1608            Computes bitwise OR of register src1 (converted to int32)
1609            and register src2 (converted to int32), and puts the
1610            result in register dst.
1611         */
1612         int dst = vPC[1].u.operand;
1613         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
1614         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
1615         if (src1.isInt32() && src2.isInt32())
1616             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() | src2.asInt32());
1617         else {
1618             JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
1619             CHECK_FOR_EXCEPTION();
1620             callFrame->r(dst) = result;
1621         }
1622
1623         vPC += OPCODE_LENGTH(op_bitor);
1624         NEXT_INSTRUCTION();
1625     }
1626     DEFINE_OPCODE(op_bitnot) {
1627         /* bitnot dst(r) src(r)
1628
1629            Computes bitwise NOT of register src1 (converted to int32),
1630            and puts the result in register dst.
1631         */
1632         int dst = vPC[1].u.operand;
1633         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
1634         if (src.isInt32())
1635             callFrame->r(dst) = jsNumber(callFrame, ~src.asInt32());
1636         else {
1637             JSValue result = jsNumber(callFrame, ~src.toInt32(callFrame));
1638             CHECK_FOR_EXCEPTION();
1639             callFrame->r(dst) = result;
1640         }
1641         vPC += OPCODE_LENGTH(op_bitnot);
1642         NEXT_INSTRUCTION();
1643     }
1644     DEFINE_OPCODE(op_not) {
1645         /* not dst(r) src(r)
1646
1647            Computes logical NOT of register src (converted to
1648            boolean), and puts the result in register dst.
1649         */
1650         int dst = vPC[1].u.operand;
1651         int src = vPC[2].u.operand;
1652         JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame));
1653         CHECK_FOR_EXCEPTION();
1654         callFrame->r(dst) = result;
1655
1656         vPC += OPCODE_LENGTH(op_not);
1657         NEXT_INSTRUCTION();
1658     }
1659     DEFINE_OPCODE(op_instanceof) {
1660         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
1661
1662            Tests whether register value is an instance of register
1663            constructor, and puts the boolean result in register
1664            dst. Register constructorProto must contain the "prototype"
1665            property (not the actual prototype) of the object in
1666            register constructor. This lookup is separated so that
1667            polymorphic inline caching can apply.
1668
1669            Raises an exception if register constructor is not an
1670            object.
1671         */
1672         int dst = vPC[1].u.operand;
1673         int value = vPC[2].u.operand;
1674         int base = vPC[3].u.operand;
1675         int baseProto = vPC[4].u.operand;
1676
1677         JSValue baseVal = callFrame->r(base).jsValue();
1678
1679         if (isInvalidParamForInstanceOf(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
1680             goto vm_throw;
1681
1682         bool result = asObject(baseVal)->hasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
1683         CHECK_FOR_EXCEPTION();
1684         callFrame->r(dst) = jsBoolean(result);
1685
1686         vPC += OPCODE_LENGTH(op_instanceof);
1687         NEXT_INSTRUCTION();
1688     }
1689     DEFINE_OPCODE(op_typeof) {
1690         /* typeof dst(r) src(r)
1691
1692            Determines the type string for src according to ECMAScript
1693            rules, and puts the result in register dst.
1694         */
1695         int dst = vPC[1].u.operand;
1696         int src = vPC[2].u.operand;
1697         callFrame->r(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
1698
1699         vPC += OPCODE_LENGTH(op_typeof);
1700         NEXT_INSTRUCTION();
1701     }
1702     DEFINE_OPCODE(op_is_undefined) {
1703         /* is_undefined dst(r) src(r)
1704
1705            Determines whether the type string for src according to
1706            the ECMAScript rules is "undefined", and puts the result
1707            in register dst.
1708         */
1709         int dst = vPC[1].u.operand;
1710         int src = vPC[2].u.operand;
1711         JSValue v = callFrame->r(src).jsValue();
1712         callFrame->r(dst) = jsBoolean(v.isUndefined());
1713
1714         vPC += OPCODE_LENGTH(op_is_undefined);
1715         NEXT_INSTRUCTION();
1716     }
1717     DEFINE_OPCODE(op_is_boolean) {
1718         /* is_boolean dst(r) src(r)
1719
1720            Determines whether the type string for src according to
1721            the ECMAScript rules is "boolean", and puts the result
1722            in register dst.
1723         */
1724         int dst = vPC[1].u.operand;
1725         int src = vPC[2].u.operand;
1726         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
1727
1728         vPC += OPCODE_LENGTH(op_is_boolean);
1729         NEXT_INSTRUCTION();
1730     }
1731     DEFINE_OPCODE(op_is_number) {
1732         /* is_number dst(r) src(r)
1733
1734            Determines whether the type string for src according to
1735            the ECMAScript rules is "number", and puts the result
1736            in register dst.
1737         */
1738         int dst = vPC[1].u.operand;
1739         int src = vPC[2].u.operand;
1740         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
1741
1742         vPC += OPCODE_LENGTH(op_is_number);
1743         NEXT_INSTRUCTION();
1744     }
1745     DEFINE_OPCODE(op_is_string) {
1746         /* is_string dst(r) src(r)
1747
1748            Determines whether the type string for src according to
1749            the ECMAScript rules is "string", and puts the result
1750            in register dst.
1751         */
1752         int dst = vPC[1].u.operand;
1753         int src = vPC[2].u.operand;
1754         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
1755
1756         vPC += OPCODE_LENGTH(op_is_string);
1757         NEXT_INSTRUCTION();
1758     }
1759     DEFINE_OPCODE(op_is_object) {
1760         /* is_object dst(r) src(r)
1761
1762            Determines whether the type string for src according to
1763            the ECMAScript rules is "object", and puts the result
1764            in register dst.
1765         */
1766         int dst = vPC[1].u.operand;
1767         int src = vPC[2].u.operand;
1768         callFrame->r(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
1769
1770         vPC += OPCODE_LENGTH(op_is_object);
1771         NEXT_INSTRUCTION();
1772     }
1773     DEFINE_OPCODE(op_is_function) {
1774         /* is_function dst(r) src(r)
1775
1776            Determines whether the type string for src according to
1777            the ECMAScript rules is "function", and puts the result
1778            in register dst.
1779         */
1780         int dst = vPC[1].u.operand;
1781         int src = vPC[2].u.operand;
1782         callFrame->r(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
1783
1784         vPC += OPCODE_LENGTH(op_is_function);
1785         NEXT_INSTRUCTION();
1786     }
1787     DEFINE_OPCODE(op_in) {
1788         /* in dst(r) property(r) base(r)
1789
1790            Tests whether register base has a property named register
1791            property, and puts the boolean result in register dst.
1792
1793            Raises an exception if register constructor is not an
1794            object.
1795         */
1796         int dst = vPC[1].u.operand;
1797         int property = vPC[2].u.operand;
1798         int base = vPC[3].u.operand;
1799
1800         JSValue baseVal = callFrame->r(base).jsValue();
1801         if (isInvalidParamForIn(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
1802             goto vm_throw;
1803
1804         JSObject* baseObj = asObject(baseVal);
1805
1806         JSValue propName = callFrame->r(property).jsValue();
1807
1808         uint32_t i;
1809         if (propName.getUInt32(i))
1810             callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
1811         else {
1812             Identifier property(callFrame, propName.toString(callFrame));
1813             CHECK_FOR_EXCEPTION();
1814             callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
1815         }
1816
1817         vPC += OPCODE_LENGTH(op_in);
1818         NEXT_INSTRUCTION();
1819     }
1820     DEFINE_OPCODE(op_resolve) {
1821         /* resolve dst(r) property(id)
1822
1823            Looks up the property named by identifier property in the
1824            scope chain, and writes the resulting value to register
1825            dst. If the property is not found, raises an exception.
1826         */
1827         if (Q_UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
1828             goto vm_throw;
1829
1830         vPC += OPCODE_LENGTH(op_resolve);
1831         NEXT_INSTRUCTION();
1832     }
1833     DEFINE_OPCODE(op_resolve_skip) {
1834         /* resolve_skip dst(r) property(id) skip(n)
1835
1836          Looks up the property named by identifier property in the
1837          scope chain skipping the top 'skip' levels, and writes the resulting
1838          value to register dst. If the property is not found, raises an exception.
1839          */
1840         if (Q_UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
1841             goto vm_throw;
1842
1843         vPC += OPCODE_LENGTH(op_resolve_skip);
1844
1845         NEXT_INSTRUCTION();
1846     }
1847     DEFINE_OPCODE(op_resolve_global) {
1848         /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n)
1849          
1850            Performs a dynamic property lookup for the given property, on the provided
1851            global object.  If structure matches the Structure of the global then perform
1852            a fast lookup using the case offset, otherwise fall back to a full resolve and
1853            cache the new structure and offset
1854          */
1855         if (Q_UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
1856             goto vm_throw;
1857         
1858         vPC += OPCODE_LENGTH(op_resolve_global);
1859         
1860         NEXT_INSTRUCTION();
1861     }
1862     DEFINE_OPCODE(op_get_global_var) {
1863         /* get_global_var dst(r) globalObject(c) index(n)
1864
1865            Gets the global var at global slot index and places it in register dst.
1866          */
1867         int dst = vPC[1].u.operand;
1868         JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[2].u.jsCell);
1869         Q_ASSERT(scope->isGlobalObject());
1870         int index = vPC[3].u.operand;
1871
1872         callFrame->r(dst) = scope->registerAt(index);
1873         vPC += OPCODE_LENGTH(op_get_global_var);
1874         NEXT_INSTRUCTION();
1875     }
1876     DEFINE_OPCODE(op_put_global_var) {
1877         /* put_global_var globalObject(c) index(n) value(r)
1878          
1879            Puts value into global slot index.
1880          */
1881         JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[1].u.jsCell);
1882         Q_ASSERT(scope->isGlobalObject());
1883         int index = vPC[2].u.operand;
1884         int value = vPC[3].u.operand;
1885         
1886         scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
1887         vPC += OPCODE_LENGTH(op_put_global_var);
1888         NEXT_INSTRUCTION();
1889     }            
1890     DEFINE_OPCODE(op_get_scoped_var) {
1891         /* get_scoped_var dst(r) index(n) skip(n)
1892
1893          Loads the contents of the index-th local from the scope skip nodes from
1894          the top of the scope chain, and places it in register dst
1895          */
1896         int dst = vPC[1].u.operand;
1897         int index = vPC[2].u.operand;
1898         int skip = vPC[3].u.operand + callFrame->codeBlock()->needsFullScopeChain();
1899
1900         ScopeChainNode* scopeChain = callFrame->scopeChain();
1901         ScopeChainIterator iter = scopeChain->begin();
1902 #ifndef QT_NO_DEBUG
1903         ScopeChainIterator end = scopeChain->end();
1904 #endif
1905         Q_ASSERT(iter != end);
1906         while (skip--) {
1907             ++iter;
1908             Q_ASSERT(iter != end);
1909         }
1910
1911         Q_ASSERT((*iter)->isVariableObject());
1912         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1913         callFrame->r(dst) = scope->registerAt(index);
1914         vPC += OPCODE_LENGTH(op_get_scoped_var);
1915         NEXT_INSTRUCTION();
1916     }
1917     DEFINE_OPCODE(op_put_scoped_var) {
1918         /* put_scoped_var index(n) skip(n) value(r)
1919
1920          */
1921         int index = vPC[1].u.operand;
1922         int skip = vPC[2].u.operand + callFrame->codeBlock()->needsFullScopeChain();
1923         int value = vPC[3].u.operand;
1924
1925         ScopeChainNode* scopeChain = callFrame->scopeChain();
1926         ScopeChainIterator iter = scopeChain->begin();
1927 #ifndef QT_NO_DEBUG
1928         ScopeChainIterator end = scopeChain->end();
1929 #endif
1930         Q_ASSERT(iter != end);
1931         while (skip--) {
1932             ++iter;
1933             Q_ASSERT(iter != end);
1934         }
1935
1936         Q_ASSERT((*iter)->isVariableObject());
1937         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1938         scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
1939         vPC += OPCODE_LENGTH(op_put_scoped_var);
1940         NEXT_INSTRUCTION();
1941     }
1942     DEFINE_OPCODE(op_resolve_base) {
1943         /* resolve_base dst(r) property(id)
1944
1945            Searches the scope chain for an object containing
1946            identifier property, and if one is found, writes it to
1947            register dst. If none is found, the outermost scope (which
1948            will be the global object) is stored in register dst.
1949         */
1950         resolveBase(callFrame, vPC);
1951
1952         vPC += OPCODE_LENGTH(op_resolve_base);
1953         NEXT_INSTRUCTION();
1954     }
1955     DEFINE_OPCODE(op_resolve_with_base) {
1956         /* resolve_with_base baseDst(r) propDst(r) property(id)
1957
1958            Searches the scope chain for an object containing
1959            identifier property, and if one is found, writes it to
1960            register srcDst, and the retrieved property value to register
1961            propDst. If the property is not found, raises an exception.
1962
1963            This is more efficient than doing resolve_base followed by
1964            resolve, or resolve_base followed by get_by_id, as it
1965            avoids duplicate hash lookups.
1966         */
1967         if (Q_UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
1968             goto vm_throw;
1969
1970         vPC += OPCODE_LENGTH(op_resolve_with_base);
1971         NEXT_INSTRUCTION();
1972     }
1973     DEFINE_OPCODE(op_get_by_id) {
1974         /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
1975
1976            Generic property access: Gets the property named by identifier
1977            property from the value base, and puts the result in register dst.
1978         */
1979         int dst = vPC[1].u.operand;
1980         int base = vPC[2].u.operand;
1981         int property = vPC[3].u.operand;
1982
1983         CodeBlock* codeBlock = callFrame->codeBlock();
1984         Identifier& ident = codeBlock->identifier(property);
1985         JSValue baseValue = callFrame->r(base).jsValue();
1986         PropertySlot slot(baseValue);
1987         JSValue result = baseValue.get(callFrame, ident, slot);
1988         CHECK_FOR_EXCEPTION();
1989
1990         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
1991
1992         callFrame->r(dst) = result;
1993         vPC += OPCODE_LENGTH(op_get_by_id);
1994         NEXT_INSTRUCTION();
1995     }
1996     DEFINE_OPCODE(op_get_by_id_self) {
1997         /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
1998
1999            Cached property access: Attempts to get a cached property from the
2000            value base. If the cache misses, op_get_by_id_self reverts to
2001            op_get_by_id.
2002         */
2003         int base = vPC[2].u.operand;
2004         JSValue baseValue = callFrame->r(base).jsValue();
2005
2006         if (Q_LIKELY(baseValue.isCell())) {
2007             JSCell* baseCell = baseValue.asCell();
2008             Structure* structure = vPC[4].u.structure;
2009
2010             if (Q_LIKELY(baseCell->structure() == structure)) {
2011                 Q_ASSERT(baseCell->isObject());
2012                 JSObject* baseObject = asObject(baseCell);
2013                 int dst = vPC[1].u.operand;
2014                 int offset = vPC[5].u.operand;
2015
2016                 Q_ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2017                 callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
2018
2019                 vPC += OPCODE_LENGTH(op_get_by_id_self);
2020                 NEXT_INSTRUCTION();
2021             }
2022         }
2023
2024         uncacheGetByID(callFrame->codeBlock(), vPC);
2025         NEXT_INSTRUCTION();
2026     }
2027     DEFINE_OPCODE(op_get_by_id_proto) {
2028         /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
2029
2030            Cached property access: Attempts to get a cached property from the
2031            value base's prototype. If the cache misses, op_get_by_id_proto
2032            reverts to op_get_by_id.
2033         */
2034         int base = vPC[2].u.operand;
2035         JSValue baseValue = callFrame->r(base).jsValue();
2036
2037         if (Q_LIKELY(baseValue.isCell())) {
2038             JSCell* baseCell = baseValue.asCell();
2039             Structure* structure = vPC[4].u.structure;
2040
2041             if (Q_LIKELY(baseCell->structure() == structure)) {
2042                 Q_ASSERT(structure->prototypeForLookup(callFrame).isObject());
2043                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
2044                 Structure* prototypeStructure = vPC[5].u.structure;
2045
2046                 if (Q_LIKELY(protoObject->structure() == prototypeStructure)) {
2047                     int dst = vPC[1].u.operand;
2048                     int offset = vPC[6].u.operand;
2049
2050                     Q_ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
2051                     Q_ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
2052                     callFrame->r(dst) = JSValue(protoObject->getDirectOffset(offset));
2053
2054                     vPC += OPCODE_LENGTH(op_get_by_id_proto);
2055                     NEXT_INSTRUCTION();
2056                 }
2057             }
2058         }
2059
2060         uncacheGetByID(callFrame->codeBlock(), vPC);
2061         NEXT_INSTRUCTION();
2062     }
2063     DEFINE_OPCODE(op_get_by_id_chain) {
2064         /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
2065
2066            Cached property access: Attempts to get a cached property from the
2067            value base's prototype chain. If the cache misses, op_get_by_id_chain
2068            reverts to op_get_by_id.
2069         */
2070         int base = vPC[2].u.operand;
2071         JSValue baseValue = callFrame->r(base).jsValue();
2072
2073         if (Q_LIKELY(baseValue.isCell())) {
2074             JSCell* baseCell = baseValue.asCell();
2075             Structure* structure = vPC[4].u.structure;
2076
2077             if (Q_LIKELY(baseCell->structure() == structure)) {
2078                 RefPtr<Structure>* it = vPC[5].u.structureChain->head();
2079                 size_t count = vPC[6].u.operand;
2080                 RefPtr<Structure>* end = it + count;
2081
2082                 while (true) {
2083                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
2084
2085                     if (Q_UNLIKELY(baseObject->structure() != (*it).get()))
2086                         break;
2087
2088                     if (++it == end) {
2089                         int dst = vPC[1].u.operand;
2090                         int offset = vPC[7].u.operand;
2091
2092                         Q_ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2093                         Q_ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2094                         callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
2095
2096                         vPC += OPCODE_LENGTH(op_get_by_id_chain);
2097                         NEXT_INSTRUCTION();
2098                     }
2099
2100                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
2101                     baseCell = baseObject;
2102                 }
2103             }
2104         }
2105
2106         uncacheGetByID(callFrame->codeBlock(), vPC);
2107         NEXT_INSTRUCTION();
2108     }
2109     DEFINE_OPCODE(op_get_by_id_generic) {
2110         /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2111
2112            Generic property access: Gets the property named by identifier
2113            property from the value base, and puts the result in register dst.
2114         */
2115         int dst = vPC[1].u.operand;
2116         int base = vPC[2].u.operand;
2117         int property = vPC[3].u.operand;
2118
2119         Identifier& ident = callFrame->codeBlock()->identifier(property);
2120         JSValue baseValue = callFrame->r(base).jsValue();
2121         PropertySlot slot(baseValue);
2122         JSValue result = baseValue.get(callFrame, ident, slot);
2123         CHECK_FOR_EXCEPTION();
2124
2125         callFrame->r(dst) = result;
2126         vPC += OPCODE_LENGTH(op_get_by_id_generic);
2127         NEXT_INSTRUCTION();
2128     }
2129     DEFINE_OPCODE(op_get_array_length) {
2130         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2131
2132            Cached property access: Gets the length of the array in register base,
2133            and puts the result in register dst. If register base does not hold
2134            an array, op_get_array_length reverts to op_get_by_id.
2135         */
2136
2137         int base = vPC[2].u.operand;
2138         JSValue baseValue = callFrame->r(base).jsValue();
2139         if (Q_LIKELY(isJSArray(globalData, baseValue))) {
2140             int dst = vPC[1].u.operand;
2141             callFrame->r(dst) = jsNumber(callFrame, asArray(baseValue)->length());
2142             vPC += OPCODE_LENGTH(op_get_array_length);
2143             NEXT_INSTRUCTION();
2144         }
2145
2146         uncacheGetByID(callFrame->codeBlock(), vPC);
2147         NEXT_INSTRUCTION();
2148     }
2149     DEFINE_OPCODE(op_get_string_length) {
2150         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2151
2152            Cached property access: Gets the length of the string in register base,
2153            and puts the result in register dst. If register base does not hold
2154            a string, op_get_string_length reverts to op_get_by_id.
2155         */
2156
2157         int base = vPC[2].u.operand;
2158         JSValue baseValue = callFrame->r(base).jsValue();
2159         if (Q_LIKELY(isJSString(globalData, baseValue))) {
2160             int dst = vPC[1].u.operand;
2161             callFrame->r(dst) = jsNumber(callFrame, asString(baseValue)->length());
2162             vPC += OPCODE_LENGTH(op_get_string_length);
2163             NEXT_INSTRUCTION();
2164         }
2165
2166         uncacheGetByID(callFrame->codeBlock(), vPC);
2167         NEXT_INSTRUCTION();
2168     }
2169     DEFINE_OPCODE(op_put_by_id) {
2170         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2171
2172            Generic property access: Sets the property named by identifier
2173            property, belonging to register base, to register value.
2174
2175            Unlike many opcodes, this one does not write any output to
2176            the register file.
2177         */
2178
2179         int base = vPC[1].u.operand;
2180         int property = vPC[2].u.operand;
2181         int value = vPC[3].u.operand;
2182
2183         CodeBlock* codeBlock = callFrame->codeBlock();
2184         JSValue baseValue = callFrame->r(base).jsValue();
2185         Identifier& ident = codeBlock->identifier(property);
2186         PutPropertySlot slot;
2187         baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
2188         CHECK_FOR_EXCEPTION();
2189
2190         tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
2191
2192         vPC += OPCODE_LENGTH(op_put_by_id);
2193         NEXT_INSTRUCTION();
2194     }
2195     DEFINE_OPCODE(op_put_by_id_transition) {
2196         /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n)
2197          
2198            Cached property access: Attempts to set a new property with a cached transition
2199            property named by identifier property, belonging to register base,
2200            to register value. If the cache misses, op_put_by_id_transition
2201            reverts to op_put_by_id_generic.
2202          
2203            Unlike many opcodes, this one does not write any output to
2204            the register file.
2205          */
2206         int base = vPC[1].u.operand;
2207         JSValue baseValue = callFrame->r(base).jsValue();
2208         
2209         if (Q_LIKELY(baseValue.isCell())) {
2210             JSCell* baseCell = baseValue.asCell();
2211             Structure* oldStructure = vPC[4].u.structure;
2212             Structure* newStructure = vPC[5].u.structure;
2213             
2214             if (Q_LIKELY(baseCell->structure() == oldStructure)) {
2215                 Q_ASSERT(baseCell->isObject());
2216                 JSObject* baseObject = asObject(baseCell);
2217
2218                 RefPtr<Structure>* it = vPC[6].u.structureChain->head();
2219
2220                 JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
2221                 while (!proto.isNull()) {
2222                     if (Q_UNLIKELY(asObject(proto)->structure() != (*it).get())) {
2223                         uncachePutByID(callFrame->codeBlock(), vPC);
2224                         NEXT_INSTRUCTION();
2225                     }
2226                     ++it;
2227                     proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
2228                 }
2229
2230                 baseObject->transitionTo(newStructure);
2231
2232                 int value = vPC[3].u.operand;
2233                 unsigned offset = vPC[7].u.operand;
2234                 Q_ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
2235                 baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
2236
2237                 vPC += OPCODE_LENGTH(op_put_by_id_transition);
2238                 NEXT_INSTRUCTION();
2239             }
2240         }
2241         
2242         uncachePutByID(callFrame->codeBlock(), vPC);
2243         NEXT_INSTRUCTION();
2244     }
2245     DEFINE_OPCODE(op_put_by_id_replace) {
2246         /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n)
2247
2248            Cached property access: Attempts to set a pre-existing, cached
2249            property named by identifier property, belonging to register base,
2250            to register value. If the cache misses, op_put_by_id_replace
2251            reverts to op_put_by_id.
2252
2253            Unlike many opcodes, this one does not write any output to
2254            the register file.
2255         */
2256         int base = vPC[1].u.operand;
2257         JSValue baseValue = callFrame->r(base).jsValue();
2258
2259         if (Q_LIKELY(baseValue.isCell())) {
2260             JSCell* baseCell = baseValue.asCell();
2261             Structure* structure = vPC[4].u.structure;
2262
2263             if (Q_LIKELY(baseCell->structure() == structure)) {
2264                 Q_ASSERT(baseCell->isObject());
2265                 JSObject* baseObject = asObject(baseCell);
2266                 int value = vPC[3].u.operand;
2267                 unsigned offset = vPC[5].u.operand;
2268                 
2269                 Q_ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
2270                 baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
2271
2272                 vPC += OPCODE_LENGTH(op_put_by_id_replace);
2273                 NEXT_INSTRUCTION();
2274             }
2275         }
2276
2277         uncachePutByID(callFrame->codeBlock(), vPC);
2278         NEXT_INSTRUCTION();
2279     }
2280     DEFINE_OPCODE(op_put_by_id_generic) {
2281         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2282
2283            Generic property access: Sets the property named by identifier
2284            property, belonging to register base, to register value.
2285
2286            Unlike many opcodes, this one does not write any output to
2287            the register file.
2288         */
2289         int base = vPC[1].u.operand;
2290         int property = vPC[2].u.operand;
2291         int value = vPC[3].u.operand;
2292
2293         JSValue baseValue = callFrame->r(base).jsValue();
2294         Identifier& ident = callFrame->codeBlock()->identifier(property);
2295         PutPropertySlot slot;
2296         baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
2297         CHECK_FOR_EXCEPTION();
2298
2299         vPC += OPCODE_LENGTH(op_put_by_id_generic);
2300         NEXT_INSTRUCTION();
2301     }
2302     DEFINE_OPCODE(op_del_by_id) {
2303         /* del_by_id dst(r) base(r) property(id)
2304
2305            Converts register base to Object, deletes the property
2306            named by identifier property from the object, and writes a
2307            boolean indicating success (if true) or failure (if false)
2308            to register dst.
2309         */
2310         int dst = vPC[1].u.operand;
2311         int base = vPC[2].u.operand;
2312         int property = vPC[3].u.operand;
2313
2314         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
2315         Identifier& ident = callFrame->codeBlock()->identifier(property);
2316         JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
2317         CHECK_FOR_EXCEPTION();
2318         callFrame->r(dst) = result;
2319         vPC += OPCODE_LENGTH(op_del_by_id);
2320         NEXT_INSTRUCTION();
2321     }
2322     DEFINE_OPCODE(op_get_by_pname) {
2323         int dst = vPC[1].u.operand;
2324         int base = vPC[2].u.operand;
2325         int property = vPC[3].u.operand;
2326         int expected = vPC[4].u.operand;
2327         int iter = vPC[5].u.operand;
2328         int i = vPC[6].u.operand;
2329
2330         JSValue baseValue = callFrame->r(base).jsValue();
2331         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
2332         JSValue subscript = callFrame->r(property).jsValue();
2333         JSValue expectedSubscript = callFrame->r(expected).jsValue();
2334         int index = callFrame->r(i).i() - 1;
2335         JSValue result;
2336         int offset = 0;
2337         if (subscript == expectedSubscript && baseValue.isCell() && (baseValue.asCell()->structure() == it->cachedStructure()) && it->getOffset(index, offset)) {
2338             callFrame->r(dst) = asObject(baseValue)->getDirectOffset(offset);
2339             vPC += OPCODE_LENGTH(op_get_by_pname);
2340             NEXT_INSTRUCTION();
2341         }
2342         {
2343             Identifier propertyName(callFrame, subscript.toString(callFrame));
2344             result = baseValue.get(callFrame, propertyName);
2345         }
2346         CHECK_FOR_EXCEPTION();
2347         callFrame->r(dst) = result;
2348         vPC += OPCODE_LENGTH(op_get_by_pname);
2349         NEXT_INSTRUCTION();
2350     }
2351     DEFINE_OPCODE(op_get_by_val) {
2352         /* get_by_val dst(r) base(r) property(r)
2353
2354            Converts register base to Object, gets the property named
2355            by register property from the object, and puts the result
2356            in register dst. property is nominally converted to string
2357            but numbers are treated more efficiently.
2358         */
2359         int dst = vPC[1].u.operand;
2360         int base = vPC[2].u.operand;
2361         int property = vPC[3].u.operand;
2362         
2363         JSValue baseValue = callFrame->r(base).jsValue();
2364         JSValue subscript = callFrame->r(property).jsValue();
2365
2366         JSValue result;
2367
2368         if (Q_LIKELY(subscript.isUInt32())) {
2369             uint32_t i = subscript.asUInt32();
2370             if (isJSArray(globalData, baseValue)) {
2371                 JSArray* jsArray = asArray(baseValue);
2372                 if (jsArray->canGetIndex(i))
2373                     result = jsArray->getIndex(i);
2374                 else
2375                     result = jsArray->JSArray::get(callFrame, i);
2376             } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
2377                 result = asString(baseValue)->getIndex(callFrame, i);
2378             else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i))
2379                 result = asByteArray(baseValue)->getIndex(callFrame, i);
2380             else
2381                 result = baseValue.get(callFrame, i);
2382         } else {
2383             Identifier property(callFrame, subscript.toString(callFrame));
2384             result = baseValue.get(callFrame, property);
2385         }
2386
2387         CHECK_FOR_EXCEPTION();
2388         callFrame->r(dst) = result;
2389         vPC += OPCODE_LENGTH(op_get_by_val);
2390         NEXT_INSTRUCTION();
2391     }
2392     DEFINE_OPCODE(op_put_by_val) {
2393         /* put_by_val base(r) property(r) value(r)
2394
2395            Sets register value on register base as the property named
2396            by register property. Base is converted to object
2397            first. register property is nominally converted to string
2398            but numbers are treated more efficiently.
2399
2400            Unlike many opcodes, this one does not write any output to
2401            the register file.
2402         */
2403         int base = vPC[1].u.operand;
2404         int property = vPC[2].u.operand;
2405         int value = vPC[3].u.operand;
2406
2407         JSValue baseValue = callFrame->r(base).jsValue();
2408         JSValue subscript = callFrame->r(property).jsValue();
2409
2410         if (Q_LIKELY(subscript.isUInt32())) {
2411             uint32_t i = subscript.asUInt32();
2412             if (isJSArray(globalData, baseValue)) {
2413                 JSArray* jsArray = asArray(baseValue);
2414                 if (jsArray->canSetIndex(i))
2415                     jsArray->setIndex(i, callFrame->r(value).jsValue());
2416                 else
2417                     jsArray->JSArray::put(callFrame, i, callFrame->r(value).jsValue());
2418             } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2419                 JSByteArray* jsByteArray = asByteArray(baseValue);
2420                 double dValue = 0;
2421                 JSValue jsValue = callFrame->r(value).jsValue();
2422                 if (jsValue.isInt32())
2423                     jsByteArray->setIndex(i, jsValue.asInt32());
2424                 else if (jsValue.getNumber(dValue))
2425                     jsByteArray->setIndex(i, dValue);
2426                 else
2427                     baseValue.put(callFrame, i, jsValue);
2428             } else
2429                 baseValue.put(callFrame, i, callFrame->r(value).jsValue());
2430         } else {
2431             Identifier property(callFrame, subscript.toString(callFrame));
2432             if (!globalData->exception) { // Don't put to an object if toString threw an exception.
2433                 PutPropertySlot slot;
2434                 baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
2435             }
2436         }
2437
2438         CHECK_FOR_EXCEPTION();
2439         vPC += OPCODE_LENGTH(op_put_by_val);
2440         NEXT_INSTRUCTION();
2441     }
2442     DEFINE_OPCODE(op_del_by_val) {
2443         /* del_by_val dst(r) base(r) property(r)
2444
2445            Converts register base to Object, deletes the property
2446            named by register property from the object, and writes a
2447            boolean indicating success (if true) or failure (if false)
2448            to register dst.
2449         */
2450         int dst = vPC[1].u.operand;
2451         int base = vPC[2].u.operand;
2452         int property = vPC[3].u.operand;
2453
2454         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw
2455
2456         JSValue subscript = callFrame->r(property).jsValue();
2457         JSValue result;
2458         uint32_t i;
2459         if (subscript.getUInt32(i))
2460             result = jsBoolean(baseObj->deleteProperty(callFrame, i));
2461         else {
2462             CHECK_FOR_EXCEPTION();
2463             Identifier property(callFrame, subscript.toString(callFrame));
2464             CHECK_FOR_EXCEPTION();
2465             result = jsBoolean(baseObj->deleteProperty(callFrame, property));
2466         }
2467
2468         CHECK_FOR_EXCEPTION();
2469         callFrame->r(dst) = result;
2470         vPC += OPCODE_LENGTH(op_del_by_val);
2471         NEXT_INSTRUCTION();
2472     }
2473     DEFINE_OPCODE(op_put_by_index) {
2474         /* put_by_index base(r) property(n) value(r)
2475
2476            Sets register value on register base as the property named
2477            by the immediate number property. Base is converted to
2478            object first.
2479
2480            Unlike many opcodes, this one does not write any output to
2481            the register file.
2482
2483            This opcode is mainly used to initialize array literals.
2484         */
2485         int base = vPC[1].u.operand;
2486         unsigned property = vPC[2].u.operand;
2487         int value = vPC[3].u.operand;
2488
2489         callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
2490
2491         vPC += OPCODE_LENGTH(op_put_by_index);
2492         NEXT_INSTRUCTION();
2493     }
2494     DEFINE_OPCODE(op_loop) {
2495         /* loop target(offset)
2496          
2497            Jumps unconditionally to offset target from the current
2498            instruction.
2499
2500            Additionally this loop instruction may terminate JS execution is
2501            the JS timeout is reached.
2502          */
2503 #if ENABLE(OPCODE_STATS)
2504         OpcodeStats::resetLastInstruction();
2505 #endif
2506         int target = vPC[1].u.operand;
2507         CHECK_FOR_TIMEOUT();
2508         vPC += target;
2509         NEXT_INSTRUCTION();
2510     }
2511     DEFINE_OPCODE(op_jmp) {
2512         /* jmp target(offset)
2513
2514            Jumps unconditionally to offset target from the current
2515            instruction.
2516         */
2517 #if ENABLE(OPCODE_STATS)
2518         OpcodeStats::resetLastInstruction();
2519 #endif
2520         int target = vPC[1].u.operand;
2521
2522         vPC += target;
2523         NEXT_INSTRUCTION();
2524     }
2525     DEFINE_OPCODE(op_loop_if_true) {
2526         /* loop_if_true cond(r) target(offset)
2527          
2528            Jumps to offset target from the current instruction, if and
2529            only if register cond converts to boolean as true.
2530
2531            Additionally this loop instruction may terminate JS execution is
2532            the JS timeout is reached.
2533          */
2534         int cond = vPC[1].u.operand;
2535         int target = vPC[2].u.operand;
2536         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
2537             vPC += target;
2538             CHECK_FOR_TIMEOUT();
2539             NEXT_INSTRUCTION();
2540         }
2541         
2542         vPC += OPCODE_LENGTH(op_loop_if_true);
2543         NEXT_INSTRUCTION();
2544     }
2545     DEFINE_OPCODE(op_loop_if_false) {
2546         /* loop_if_true cond(r) target(offset)
2547          
2548            Jumps to offset target from the current instruction, if and
2549            only if register cond converts to boolean as false.
2550
2551            Additionally this loop instruction may terminate JS execution is
2552            the JS timeout is reached.
2553          */
2554         int cond = vPC[1].u.operand;
2555         int target = vPC[2].u.operand;
2556         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
2557             vPC += target;
2558             CHECK_FOR_TIMEOUT();
2559             NEXT_INSTRUCTION();
2560         }
2561         
2562         vPC += OPCODE_LENGTH(op_loop_if_true);
2563         NEXT_INSTRUCTION();
2564     }
2565     DEFINE_OPCODE(op_jtrue) {
2566         /* jtrue cond(r) target(offset)
2567
2568            Jumps to offset target from the current instruction, if and
2569            only if register cond converts to boolean as true.
2570         */
2571         int cond = vPC[1].u.operand;
2572         int target = vPC[2].u.operand;
2573         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
2574             vPC += target;
2575             NEXT_INSTRUCTION();
2576         }
2577
2578         vPC += OPCODE_LENGTH(op_jtrue);
2579         NEXT_INSTRUCTION();
2580     }
2581     DEFINE_OPCODE(op_jfalse) {
2582         /* jfalse cond(r) target(offset)
2583
2584            Jumps to offset target from the current instruction, if and
2585            only if register cond converts to boolean as false.
2586         */
2587         int cond = vPC[1].u.operand;
2588         int target = vPC[2].u.operand;
2589         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
2590             vPC += target;
2591             NEXT_INSTRUCTION();
2592         }
2593
2594         vPC += OPCODE_LENGTH(op_jfalse);
2595         NEXT_INSTRUCTION();
2596     }
2597     DEFINE_OPCODE(op_jeq_null) {
2598         /* jeq_null src(r) target(offset)
2599
2600            Jumps to offset target from the current instruction, if and
2601            only if register src is null.
2602         */
2603         int src = vPC[1].u.operand;
2604         int target = vPC[2].u.operand;
2605         JSValue srcValue = callFrame->r(src).jsValue();
2606
2607         if (srcValue.isUndefinedOrNull()) {
2608             vPC += target;
2609             NEXT_INSTRUCTION();
2610         }
2611
2612         vPC += OPCODE_LENGTH(op_jeq_null);
2613         NEXT_INSTRUCTION();
2614     }
2615     DEFINE_OPCODE(op_jneq_null) {
2616         /* jneq_null src(r) target(offset)
2617
2618            Jumps to offset target from the current instruction, if and
2619            only if register src is not null.
2620         */
2621         int src = vPC[1].u.operand;
2622         int target = vPC[2].u.operand;
2623         JSValue srcValue = callFrame->r(src).jsValue();
2624
2625         if (!srcValue.isUndefinedOrNull() && !srcValue.isCell()) {
2626             vPC += target;
2627             NEXT_INSTRUCTION();
2628         }
2629
2630         vPC += OPCODE_LENGTH(op_jneq_null);
2631         NEXT_INSTRUCTION();
2632     }
2633     DEFINE_OPCODE(op_jneq_ptr) {
2634         /* jneq_ptr src(r) ptr(jsCell) target(offset)
2635          
2636            Jumps to offset target from the current instruction, if the value r is equal
2637            to ptr, using pointer equality.
2638          */
2639         int src = vPC[1].u.operand;
2640         JSValue ptr = JSValue(vPC[2].u.jsCell);
2641         int target = vPC[3].u.operand;
2642         JSValue srcValue = callFrame->r(src).jsValue();
2643         if (srcValue != ptr) {
2644             vPC += target;
2645             NEXT_INSTRUCTION();
2646         }
2647
2648         vPC += OPCODE_LENGTH(op_jneq_ptr);
2649         NEXT_INSTRUCTION();
2650     }
2651     DEFINE_OPCODE(op_loop_if_less) {
2652         /* loop_if_less src1(r) src2(r) target(offset)
2653
2654            Checks whether register src1 is less than register src2, as
2655            with the ECMAScript '<' operator, and then jumps to offset
2656            target from the current instruction, if and only if the 
2657            result of the comparison is true.
2658
2659            Additionally this loop instruction may terminate JS execution is
2660            the JS timeout is reached.
2661          */
2662         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
2663         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
2664         int target = vPC[3].u.operand;
2665         
2666         bool result = jsLess(callFrame, src1, src2);
2667         CHECK_FOR_EXCEPTION();
2668         
2669         if (result) {
2670             vPC += target;
2671             CHECK_FOR_TIMEOUT();
2672             NEXT_INSTRUCTION();
2673         }
2674         
2675         vPC += OPCODE_LENGTH(op_loop_if_less);
2676         NEXT_INSTRUCTION();
2677     }
2678     DEFINE_OPCODE(op_loop_if_lesseq) {
2679         /* loop_if_lesseq src1(r) src2(r) target(offset)
2680
2681            Checks whether register src1 is less than or equal to register
2682            src2, as with the ECMAScript '<=' operator, and then jumps to
2683            offset target from the current instruction, if and only if the 
2684            result of the comparison is true.
2685
2686            Additionally this loop instruction may terminate JS execution is
2687            the JS timeout is reached.
2688         */
2689         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
2690         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
2691         int target = vPC[3].u.operand;
2692         
2693         bool result = jsLessEq(callFrame, src1, src2);
2694         CHECK_FOR_EXCEPTION();
2695         
2696         if (result) {
2697             vPC += target;
2698             CHECK_FOR_TIMEOUT();
2699             NEXT_INSTRUCTION();
2700         }
2701         
2702         vPC += OPCODE_LENGTH(op_loop_if_lesseq);
2703         NEXT_INSTRUCTION();
2704     }
2705     DEFINE_OPCODE(op_jnless) {
2706         /* jnless src1(r) src2(r) target(offset)
2707
2708            Checks whether register src1 is less than register src2, as
2709            with the ECMAScript '<' operator, and then jumps to offset
2710            target from the current instruction, if and only if the 
2711            result of the comparison is false.
2712         */
2713         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
2714         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
2715         int target = vPC[3].u.operand;
2716
2717         bool result = jsLess(callFrame, src1, src2);
2718         CHECK_FOR_EXCEPTION();
2719         
2720         if (!result) {
2721             vPC += target;
2722             NEXT_INSTRUCTION();
2723         }
2724
2725         vPC += OPCODE_LENGTH(op_jnless);
2726         NEXT_INSTRUCTION();
2727     }
2728     DEFINE_OPCODE(op_jless) {
2729         /* jless src1(r) src2(r) target(offset)
2730
2731            Checks whether register src1 is less than register src2, as
2732            with the ECMAScript '<' operator, and then jumps to offset
2733            target from the current instruction, if and only if the 
2734            result of the comparison is true.
2735         */
2736         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
2737         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
2738         int target = vPC[3].u.operand;
2739
2740         bool result = jsLess(callFrame, src1, src2);
2741         CHECK_FOR_EXCEPTION();
2742         
2743         if (result) {
2744             vPC += target;
2745             NEXT_INSTRUCTION();
2746         }
2747
2748         vPC += OPCODE_LENGTH(op_jless);
2749         NEXT_INSTRUCTION();
2750     }
2751     DEFINE_OPCODE(op_jnlesseq) {
2752         /* jnlesseq src1(r) src2(r) target(offset)
2753
2754            Checks whether register src1 is less than or equal to
2755            register src2, as with the ECMAScript '<=' operator,
2756            and then jumps to offset target from the current instruction,
2757            if and only if theresult of the comparison is false.
2758         */
2759         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
2760         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
2761         int target = vPC[3].u.operand;
2762
2763         bool result = jsLessEq(callFrame, src1, src2);
2764         CHECK_FOR_EXCEPTION();
2765         
2766         if (!result) {
2767             vPC += target;
2768             NEXT_INSTRUCTION();
2769         }
2770
2771         vPC += OPCODE_LENGTH(op_jnlesseq);
2772         NEXT_INSTRUCTION();
2773     }
2774     DEFINE_OPCODE(op_switch_imm) {
2775         /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
2776
2777            Performs a range checked switch on the scrutinee value, using
2778            the tableIndex-th immediate switch jump table.  If the scrutinee value
2779            is an immediate number in the range covered by the referenced jump
2780            table, and the value at jumpTable[scrutinee value] is non-zero, then
2781            that value is used as the jump offset, otherwise defaultOffset is used.
2782          */
2783         int tableIndex = vPC[1].u.operand;
2784         int defaultOffset = vPC[2].u.operand;
2785         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
2786         if (scrutinee.isInt32())
2787             vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
2788         else {
2789             double value;
2790             int32_t intValue;
2791             if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
2792                 vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(intValue, defaultOffset);
2793             else
2794                 vPC += defaultOffset;
2795         }
2796         NEXT_INSTRUCTION();
2797     }
2798     DEFINE_OPCODE(op_switch_char) {
2799         /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
2800
2801            Performs a range checked switch on the scrutinee value, using
2802            the tableIndex-th character switch jump table.  If the scrutinee value
2803            is a single character string in the range covered by the referenced jump
2804            table, and the value at jumpTable[scrutinee value] is non-zero, then
2805            that value is used as the jump offset, otherwise defaultOffset is used.
2806          */
2807         int tableIndex = vPC[1].u.operand;
2808         int defaultOffset = vPC[2].u.operand;
2809         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
2810         if (!scrutinee.isString())
2811             vPC += defaultOffset;
2812         else {
2813             UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
2814             if (value->size() != 1)
2815                 vPC += defaultOffset;
2816             else
2817                 vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->data()[0], defaultOffset);
2818         }
2819         NEXT_INSTRUCTION();
2820     }
2821     DEFINE_OPCODE(op_switch_string) {
2822         /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
2823
2824            Performs a sparse hashmap based switch on the value in the scrutinee
2825            register, using the tableIndex-th string switch jump table.  If the 
2826            scrutinee value is a string that exists as a key in the referenced 
2827            jump table, then the value associated with the string is used as the 
2828            jump offset, otherwise defaultOffset is used.
2829          */
2830         int tableIndex = vPC[1].u.operand;
2831         int defaultOffset = vPC[2].u.operand;
2832         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
2833         if (!scrutinee.isString())
2834             vPC += defaultOffset;
2835         else 
2836             vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value(callFrame).rep(), defaultOffset);
2837         NEXT_INSTRUCTION();
2838     }
2839     DEFINE_OPCODE(op_new_func) {
2840         /* new_func dst(r) func(f)
2841
2842            Constructs a new Function instance from function func and
2843            the current scope chain using the original Function
2844            constructor, using the rules for function declarations, and
2845            puts the result in register dst.
2846         */
2847         int dst = vPC[1].u.operand;
2848         int func = vPC[2].u.operand;
2849
2850         callFrame->r(dst) = JSValue(callFrame->codeBlock()->functionDecl(func)->make(callFrame, callFrame->scopeChain()));
2851
2852         vPC += OPCODE_LENGTH(op_new_func);
2853         NEXT_INSTRUCTION();
2854     }
2855     DEFINE_OPCODE(op_new_func_exp) {
2856         /* new_func_exp dst(r) func(f)
2857
2858            Constructs a new Function instance from function func and
2859            the current scope chain using the original Function
2860            constructor, using the rules for function expressions, and
2861            puts the result in register dst.
2862         */
2863         int dst = vPC[1].u.operand;
2864         int funcIndex = vPC[2].u.operand;
2865
2866         FunctionExecutable* function = callFrame->codeBlock()->functionExpr(funcIndex);
2867         JSFunction* func = function->make(callFrame, callFrame->scopeChain());
2868
2869         /* 
2870             The Identifier in a FunctionExpression can be referenced from inside
2871             the FunctionExpression's FunctionBody to allow the function to call
2872             itself recursively. However, unlike in a FunctionDeclaration, the
2873             Identifier in a FunctionExpression cannot be referenced from and
2874             does not affect the scope enclosing the FunctionExpression.
2875          */
2876         if (!function->name().isNull()) {
2877             JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
2878             func->scope().push(functionScopeObject);
2879         }
2880
2881         callFrame->r(dst) = JSValue(func);
2882
2883         vPC += OPCODE_LENGTH(op_new_func_exp);
2884         NEXT_INSTRUCTION();
2885     }
2886     DEFINE_OPCODE(op_call_eval) {
2887         /* call_eval dst(r) func(r) argCount(n) registerOffset(n)
2888
2889            Call a function named "eval" with no explicit "this" value
2890            (which may therefore be the eval operator). If register
2891            thisVal is the global object, and register func contains
2892            that global object's original global eval function, then
2893            perform the eval operator in local scope (interpreting
2894            the argument registers as for the "call"
2895            opcode). Otherwise, act exactly as the "call" opcode would.
2896          */
2897
2898         int dst = vPC[1].u.operand;
2899         int func = vPC[2].u.operand;
2900         int argCount = vPC[3].u.operand;
2901         int registerOffset = vPC[4].u.operand;
2902
2903         JSValue funcVal = callFrame->r(func).jsValue();
2904
2905         Register* newCallFrame = callFrame->registers() + registerOffset;
2906         Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
2907         JSValue thisValue = argv[0].jsValue();
2908         JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
2909
2910         if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
2911             JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
2912             if (exceptionValue)
2913                 goto vm_throw;
2914             callFrame->r(dst) = result;
2915
2916             vPC += OPCODE_LENGTH(op_call_eval);
2917             NEXT_INSTRUCTION();
2918         }
2919
2920         // We didn't find the blessed version of eval, so process this
2921         // instruction as a normal function call.
2922         // fall through to op_call
2923     }
2924     DEFINE_OPCODE(op_call) {
2925         /* call dst(r) func(r) argCount(n) registerOffset(n)
2926
2927            Perform a function call.
2928            
2929            registerOffset is the distance the callFrame pointer should move
2930            before the VM initializes the new call frame's header.
2931            
2932            dst is where op_ret should store its result.
2933          */
2934
2935         int dst = vPC[1].u.operand;
2936         int func = vPC[2].u.operand;
2937         int argCount = vPC[3].u.operand;
2938         int registerOffset = vPC[4].u.operand;
2939
2940         JSValue v = callFrame->r(func).jsValue();
2941
2942         CallData callData;
2943         CallType callType = v.getCallData(callData);
2944
2945         if (callType == CallTypeJS) {
2946             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
2947             CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
2948
2949             CallFrame* previousCallFrame = callFrame;
2950
2951             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
2952             if (Q_UNLIKELY(!callFrame)) {
2953                 callFrame = previousCallFrame;
2954                 exceptionValue = createStackOverflowError(callFrame);
2955                 goto vm_throw;
2956             }
2957
2958             callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
2959             vPC = newCodeBlock->instructions().begin();
2960
2961 #if ENABLE(OPCODE_STATS)
2962             OpcodeStats::resetLastInstruction();
2963 #endif
2964
2965             NEXT_INSTRUCTION();
2966         }
2967
2968         if (callType == CallTypeHost) {
2969             ScopeChainNode* scopeChain = callFrame->scopeChain();
2970             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
2971             // we need the returnValue to be 0 as it is used as flags
2972             newCallFrame->init(0, vPC + 5, scopeChain, callFrame, 0, argCount, asObject(v));
2973             Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
2974             ArgList args(thisRegister + 1, argCount - 1);
2975
2976             // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
2977             JSValue thisValue = thisRegister->jsValue();
2978             if (thisValue == jsNull())
2979                 thisValue = callFrame->globalThisValue();
2980
2981             JSValue returnValue;
2982             {
2983                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
2984                 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
2985             }
2986             CHECK_FOR_EXCEPTION();
2987
2988             callFrame->r(dst) = returnValue;
2989
2990             vPC += OPCODE_LENGTH(op_call);
2991             NEXT_INSTRUCTION();
2992         }
2993
2994         Q_ASSERT(callType == CallTypeNone);
2995
2996         exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
2997         goto vm_throw;
2998     }
2999     DEFINE_OPCODE(op_load_varargs) {
3000         int argCountDst = vPC[1].u.operand;
3001         int argsOffset = vPC[2].u.operand;
3002         
3003         JSValue arguments = callFrame->r(argsOffset).jsValue();
3004         int32_t argCount = 0;
3005         if (!arguments) {
3006             argCount = (uint32_t)(callFrame->argumentCount()) - 1;
3007             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
3008             Register* newEnd = callFrame->registers() + sizeDelta;
3009             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
3010                 exceptionValue = createStackOverflowError(callFrame);
3011                 goto vm_throw;
3012             }
3013             Q_ASSERT(!asFunction(callFrame->callee())->isHostFunction());
3014             int32_t expectedParams = static_cast<JSFunction*>(callFrame->callee())->jsExecutable()->parameterCount();
3015             int32_t inplaceArgs = std::min(argCount, expectedParams);
3016             int32_t i = 0;
3017             Register* argStore = callFrame->registers() + argsOffset;
3018
3019             // First step is to copy the "expected" parameters from their normal location relative to the callframe
3020             for (; i < inplaceArgs; i++)
3021                 argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
3022             // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
3023             for (; i < argCount; i++)
3024                 argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - argCount - 1];
3025         } else if (!arguments.isUndefinedOrNull()) {
3026             if (!arguments.isObject()) {
3027                 exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
3028                 goto vm_throw;
3029             }
3030             if (asObject(arguments)->classInfo() == &Arguments::info) {
3031                 Arguments* args = asArguments(arguments);
3032                 argCount = args->numProvidedArguments(callFrame);
3033                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
3034                 Register* newEnd = callFrame->registers() + sizeDelta;
3035                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
3036                     exceptionValue = createStackOverflowError(callFrame);
3037                     goto vm_throw;
3038                 }
3039                 args->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
3040             } else if (isJSArray(&callFrame->globalData(), arguments)) {
3041                 JSArray* array = asArray(arguments);
3042                 argCount = array->length();
3043                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
3044                 Register* newEnd = callFrame->registers() + sizeDelta;
3045                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
3046                     exceptionValue = createStackOverflowError(callFrame);
3047                     goto vm_throw;
3048                 }
3049                 array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
3050             } else if (asObject(arguments)->inherits(&JSArray::info)) {
3051                 JSObject* argObject = asObject(arguments);
3052                 argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
3053                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
3054                 Register* newEnd = callFrame->registers() + sizeDelta;
3055                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
3056                     exceptionValue = createStackOverflowError(callFrame);
3057                     goto vm_throw;
3058                 }
3059                 Register* argsBuffer = callFrame->registers() + argsOffset;
3060                 for (int32_t i = 0; i < argCount; ++i) {
3061                     argsBuffer[i] = asObject(arguments)->get(callFrame, i);
3062                     CHECK_FOR_EXCEPTION();
3063                 }
3064             } else {
3065                 if (!arguments.isObject()) {
3066                     exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
3067                     goto vm_throw;
3068                 }
3069             }
3070         }
3071         CHECK_FOR_EXCEPTION();
3072         callFrame->r(argCountDst) = Register::withInt(argCount + 1);
3073         vPC += OPCODE_LENGTH(op_load_varargs);
3074         NEXT_INSTRUCTION();
3075     }
3076     DEFINE_OPCODE(op_call_varargs) {
3077         /* call_varargs dst(r) func(r) argCountReg(r) baseRegisterOffset(n)
3078          
3079          Perform a function call with a dynamic set of arguments.
3080          
3081          registerOffset is the distance the callFrame pointer should move
3082          before the VM initializes the new call frame's header, excluding
3083          space for arguments.
3084          
3085          dst is where op_ret should store its result.
3086          */
3087         
3088         int dst = vPC[1].u.operand;
3089         int func = vPC[2].u.operand;
3090         int argCountReg = vPC[3].u.operand;
3091         int registerOffset = vPC[4].u.operand;
3092         
3093         JSValue v = callFrame->r(func).jsValue();
3094         int argCount = callFrame->r(argCountReg).i();
3095         registerOffset += argCount;
3096         CallData callData;
3097         CallType callType = v.getCallData(callData);
3098         
3099         if (callType == CallTypeJS) {
3100             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
3101             CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
3102             
3103             CallFrame* previousCallFrame = callFrame;
3104             
3105             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
3106             if (Q_UNLIKELY(!callFrame)) {
3107                 callFrame = previousCallFrame;
3108                 exceptionValue = createStackOverflowError(callFrame);
3109                 goto vm_throw;
3110             }
3111             
3112             callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
3113             vPC = newCodeBlock->instructions().begin();
3114             
3115 #if ENABLE(OPCODE_STATS)
3116             OpcodeStats::resetLastInstruction();
3117 #endif
3118             
3119             NEXT_INSTRUCTION();
3120         }
3121         
3122         if (callType == CallTypeHost) {
3123             ScopeChainNode* scopeChain = callFrame->scopeChain();
3124             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
3125             // we need the returnValue to be 0 as it is used as flags
3126             newCallFrame->init(0, vPC + 5, scopeChain, callFrame, 0, argCount, asObject(v));
3127             
3128             Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
3129             ArgList args(thisRegister + 1, argCount - 1);
3130             
3131             // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
3132             JSValue thisValue = thisRegister->jsValue();
3133             if (thisValue == jsNull())
3134                 thisValue = callFrame->globalThisValue();
3135             
3136             JSValue returnValue;
3137             {
3138                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
3139                 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
3140             }
3141             CHECK_FOR_EXCEPTION();
3142             
3143             callFrame->r(dst) = returnValue;
3144             
3145             vPC += OPCODE_LENGTH(op_call_varargs);
3146             NEXT_INSTRUCTION();
3147         }
3148         
3149         Q_ASSERT(callType == CallTypeNone);
3150         
3151         exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
3152         goto vm_throw;
3153     }
3154     DEFINE_OPCODE(op_tear_off_activation) {
3155         /* tear_off_activation activation(r)
3156
3157            Copy all locals and parameters to new memory allocated on
3158            the heap, and make the passed activation use this memory
3159            in the future when looking up entries in the symbol table.
3160            If there is an 'arguments' object, then it will also use
3161            this memory for storing the named parameters, but not any
3162            extra arguments.
3163
3164            This opcode should only be used immediately before op_ret.
3165         */
3166
3167         int src = vPC[1].u.operand;
3168         Q_ASSERT(callFrame->codeBlock()->needsFullScopeChain());
3169
3170         asActivation(callFrame->r(src).jsValue())->copyRegisters(callFrame->optionalCalleeArguments());
3171
3172         vPC += OPCODE_LENGTH(op_tear_off_activation);
3173         NEXT_INSTRUCTION();
3174     }
3175     DEFINE_OPCODE(op_tear_off_arguments) {
3176         /* tear_off_arguments
3177
3178            Copy all arguments to new memory allocated on the heap,
3179            and make the 'arguments' object use this memory in the
3180            future when looking up named parameters, but not any
3181            extra arguments. If an activation object exists for the
3182            current function context, then the tear_off_activation
3183            opcode should be used instead.
3184
3185            This opcode should only be used immediately before op_ret.
3186         */
3187
3188         Q_ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
3189
3190         if (callFrame->optionalCalleeArguments())
3191             callFrame->optionalCalleeArguments()->copyRegisters();
3192
3193         vPC += OPCODE_LENGTH(op_tear_off_arguments);
3194         NEXT_INSTRUCTION();
3195     }
3196     DEFINE_OPCODE(op_ret) {
3197         /* ret result(r)
3198            
3199            Return register result as the return value of the current
3200            function call, writing it into the caller's expected return
3201            value register. In addition, unwind one call frame and
3202            restore the scope chain, code block instruction pointer and
3203            register base to those of the calling function.
3204         */
3205
3206         Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
3207         intptr_t sourceId = callFrame->codeBlock()->source()->asID();
3208
3209         int result = vPC[1].u.operand;
3210
3211         if (callFrame->codeBlock()->needsFullScopeChain())
3212             callFrame->scopeChain()->deref();
3213
3214         JSValue returnValue = callFrame->r(result).jsValue();
3215         if (debugger)
3216             debugger->functionExit(returnValue, sourceId);
3217
3218         vPC = callFrame->returnPC();
3219         int dst = callFrame->returnValueRegister();
3220         callFrame = callFrame->callerFrame();
3221         
3222         if (callFrame->hasHostCallFrameFlag())
3223             return returnValue;
3224
3225         callFrame->r(dst) = returnValue;
3226
3227         NEXT_INSTRUCTION();
3228     }
3229     DEFINE_OPCODE(op_enter) {
3230         /* enter
3231
3232            Initializes local variables to undefined and fills constant
3233            registers with their values. If the code block requires an
3234            activation, enter_with_activation should be used instead.
3235
3236            This opcode should only be used at the beginning of a code
3237            block.
3238         */
3239
3240         size_t i = 0;
3241         CodeBlock* codeBlock = callFrame->codeBlock();
3242         
3243         for (size_t count = codeBlock->m_numVars; i < count; ++i)
3244             callFrame->r(i) = jsUndefined();
3245
3246         vPC += OPCODE_LENGTH(op_enter);
3247         NEXT_INSTRUCTION();
3248     }
3249     DEFINE_OPCODE(op_enter_with_activation) {
3250         /* enter_with_activation dst(r)
3251
3252            Initializes local variables to undefined, fills constant
3253            registers with their values, creates an activation object,
3254            and places the new activation both in dst and at the top
3255            of the scope chain. If the code block does not require an
3256            activation, enter should be used instead.
3257
3258            This opcode should only be used at the beginning of a code
3259            block.
3260         */
3261
3262         size_t i = 0;
3263         CodeBlock* codeBlock = callFrame->codeBlock();
3264
3265         for (size_t count = codeBlock->m_numVars; i < count; ++i)
3266             callFrame->r(i) = jsUndefined();
3267
3268         int dst = vPC[1].u.operand;
3269         JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
3270         callFrame->r(dst) = JSValue(activation);
3271         callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
3272
3273         vPC += OPCODE_LENGTH(op_enter_with_activation);
3274         NEXT_INSTRUCTION();
3275     }
3276     DEFINE_OPCODE(op_convert_this) {
3277         /* convert_this this(r)
3278
3279            Takes the value in the 'this' register, converts it to a
3280            value that is suitable for use as the 'this' value, and
3281            stores it in the 'this' register. This opcode is emitted
3282            to avoid doing the conversion in the caller unnecessarily.
3283
3284            This opcode should only be used at the beginning of a code
3285            block.
3286         */
3287
3288         int thisRegister = vPC[1].u.operand;
3289         JSValue thisVal = callFrame->r(thisRegister).jsValue();
3290         if (thisVal.needsThisConversion())
3291             callFrame->r(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
3292
3293         vPC += OPCODE_LENGTH(op_convert_this);
3294         NEXT_INSTRUCTION();
3295     }
3296     DEFINE_OPCODE(op_init_arguments) {
3297         /* create_arguments
3298
3299            Initialises the arguments object reference to null to ensure
3300            we can correctly detect that we need to create it later (or
3301            avoid creating it altogether).
3302
3303            This opcode should only be used at the beginning of a code
3304            block.
3305          */
3306         callFrame->r(RegisterFile::ArgumentsRegister) = JSValue();
3307         vPC += OPCODE_LENGTH(op_init_arguments);
3308         NEXT_INSTRUCTION();
3309     }
3310     DEFINE_OPCODE(op_create_arguments) {
3311         /* create_arguments
3312
3313            Creates the 'arguments' object and places it in both the
3314            'arguments' call frame slot and the local 'arguments'
3315            register, if it has not already been initialised.
3316          */
3317         
3318          if (!callFrame->r(RegisterFile::ArgumentsRegister).jsValue()) {
3319              Arguments* arguments = new (globalData) Arguments(callFrame);
3320              callFrame->setCalleeArguments(arguments);
3321              callFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
3322          }
3323         vPC += OPCODE_LENGTH(op_create_arguments);
3324         NEXT_INSTRUCTION();
3325     }
3326     DEFINE_OPCODE(op_construct) {
3327         /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
3328
3329            Invoke register "func" as a constructor. For JS
3330            functions, the calling convention is exactly as for the
3331            "call" opcode, except that the "this" value is a newly
3332            created Object. For native constructors, no "this"
3333            value is passed. In either case, the argCount and registerOffset
3334            registers are interpreted as for the "call" opcode.
3335
3336            Register proto must contain the prototype property of
3337            register func. This is to enable polymorphic inline
3338            caching of this lookup.
3339         */
3340
3341         int dst = vPC[1].u.operand;
3342         int func = vPC[2].u.operand;
3343         int argCount = vPC[3].u.operand;
3344         int registerOffset = vPC[4].u.operand;
3345         int proto = vPC[5].u.operand;
3346         int thisRegister = vPC[6].u.operand;
3347
3348         JSValue v = callFrame->r(func).jsValue();
3349
3350         ConstructData constructData;
3351         ConstructType constructType = v.getConstructData(constructData);
3352
3353         if (constructType == ConstructTypeJS) {
3354             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
3355             CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
3356
3357             Structure* structure;
3358             JSValue prototype = callFrame->r(proto).jsValue();
3359             if (prototype.isObject())
3360                 structure = asObject(prototype)->inheritorID();
3361             else
3362                 structure = callDataScopeChain->globalObject->emptyObjectStructure();
3363             // ### world-class hack
3364             QT_PREPEND_NAMESPACE(QScriptObject)* newObject = new (globalData) QT_PREPEND_NAMESPACE(QScriptObject)(structure);
3365
3366             callFrame->r(thisRegister) = JSValue(newObject); // "this" value
3367
3368             CallFrame* previousCallFrame = callFrame;
3369
3370             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
3371             if (Q_UNLIKELY(!callFrame)) {
3372                 callFrame = previousCallFrame;
3373                 exceptionValue = createStackOverflowError(callFrame);
3374                 goto vm_throw;
3375             }
3376
3377             callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
3378             vPC = newCodeBlock->instructions().begin();
3379
3380 #if ENABLE(OPCODE_STATS)
3381             OpcodeStats::resetLastInstruction();
3382 #endif
3383
3384             NEXT_INSTRUCTION();
3385         }
3386
3387         if (constructType == ConstructTypeHost) {
3388             ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
3389
3390             ScopeChainNode* scopeChain = callFrame->scopeChain();
3391             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
3392             // we need the returnValue to be 0 as it is used as flags
3393             newCallFrame->init(0, vPC + 7, scopeChain, callFrame, 0, argCount, asObject(v));
3394
3395             JSValue returnValue;
3396             {
3397                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
3398                 returnValue = constructData.native.function(newCallFrame, asObject(v), args);
3399             }
3400             CHECK_FOR_EXCEPTION();
3401             callFrame->r(dst) = JSValue(returnValue);
3402
3403             vPC += OPCODE_LENGTH(op_construct);
3404             NEXT_INSTRUCTION();
3405         }
3406
3407         Q_ASSERT(constructType == ConstructTypeNone);
3408
3409         exceptionValue = createNotAConstructorError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
3410         goto vm_throw;
3411     }
3412     DEFINE_OPCODE(op_construct_verify) {
3413         /* construct_verify dst(r) override(r)
3414
3415            Verifies that register dst holds an object. If not, moves
3416            the object in register override to register dst.
3417         */
3418
3419         int dst = vPC[1].u.operand;
3420         if (Q_LIKELY(callFrame->r(dst).jsValue().isObject())) {
3421             vPC += OPCODE_LENGTH(op_construct_verify);
3422             NEXT_INSTRUCTION();
3423         }
3424
3425         int override = vPC[2].u.operand;
3426         callFrame->r(dst) = callFrame->r(override);
3427
3428         vPC += OPCODE_LENGTH(op_construct_verify);
3429         NEXT_INSTRUCTION();
3430     }
3431     DEFINE_OPCODE(op_strcat) {
3432         int dst = vPC[1].u.operand;
3433         int src = vPC[2].u.operand;
3434         int count = vPC[3].u.operand;
3435
3436         callFrame->r(dst) = jsString(callFrame, &callFrame->registers()[src], count);
3437         CHECK_FOR_EXCEPTION();
3438         vPC += OPCODE_LENGTH(op_strcat);
3439
3440         NEXT_INSTRUCTION();
3441     }
3442     DEFINE_OPCODE(op_to_primitive) {
3443         int dst = vPC[1].u.operand;
3444         int src = vPC[2].u.operand;
3445
3446         callFrame->r(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame);
3447         vPC += OPCODE_LENGTH(op_to_primitive);
3448
3449         NEXT_INSTRUCTION();
3450     }
3451     DEFINE_OPCODE(op_push_scope) {
3452         /* push_scope scope(r)
3453
3454            Converts register scope to object, and pushes it onto the top
3455            of the current scope chain.  The contents of the register scope
3456            are replaced by the result of toObject conversion of the scope.
3457         */
3458         int scope = vPC[1].u.operand;
3459         JSValue v = callFrame->r(scope).jsValue();
3460         JSObject* o = v.toObject(callFrame);
3461         CHECK_FOR_EXCEPTION();
3462
3463         callFrame->r(scope) = JSValue(o);
3464         callFrame->setScopeChain(callFrame->scopeChain()->push(o));
3465
3466         vPC += OPCODE_LENGTH(op_push_scope);
3467         NEXT_INSTRUCTION();
3468     }
3469     DEFINE_OPCODE(op_pop_scope) {
3470         /* pop_scope
3471
3472            Removes the top item from the current scope chain.
3473         */
3474         callFrame->setScopeChain(callFrame->scopeChain()->pop());
3475
3476         vPC += OPCODE_LENGTH(op_pop_scope);
3477         NEXT_INSTRUCTION();
3478     }
3479     DEFINE_OPCODE(op_get_pnames) {
3480         /* get_pnames dst(r) base(r) i(n) size(n) breakTarget(offset)
3481
3482            Creates a property name list for register base and puts it
3483            in register dst, initializing i and size for iteration. If
3484            base is undefined or null, jumps to breakTarget.
3485         */
3486         int dst = vPC[1].u.operand;
3487         int base = vPC[2].u.operand;
3488         int i = vPC[3].u.operand;
3489         int size = vPC[4].u.operand;
3490         int breakTarget = vPC[5].u.operand;
3491
3492         JSValue v = callFrame->r(base).jsValue();
3493         if (v.isUndefinedOrNull()) {
3494             vPC += breakTarget;
3495             NEXT_INSTRUCTION();
3496         }
3497
3498         JSObject* o = v.toObject(callFrame);
3499         Structure* structure = o->structure();
3500         JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
3501         if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
3502             jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
3503
3504         callFrame->r(dst) = jsPropertyNameIterator;
3505         callFrame->r(base) = JSValue(o);
3506         callFrame->r(i) = Register::withInt(0);
3507         callFrame->r(size) = Register::withInt(jsPropertyNameIterator->size());
3508         vPC += OPCODE_LENGTH(op_get_pnames);
3509         NEXT_INSTRUCTION();
3510     }
3511     DEFINE_OPCODE(op_next_pname) {
3512         /* next_pname dst(r) base(r) i(n) size(n) iter(r) target(offset)
3513
3514            Copies the next name from the property name list in
3515            register iter to dst, then jumps to offset target. If there are no
3516            names left, invalidates the iterator and continues to the next
3517            instruction.
3518         */
3519         int dst = vPC[1].u.operand;
3520         int base = vPC[2].u.operand;
3521         int i = vPC[3].u.operand;
3522         int size = vPC[4].u.operand;
3523         int iter = vPC[5].u.operand;
3524         int target = vPC[6].u.operand;
3525
3526         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
3527         while (callFrame->r(i).i() != callFrame->r(size).i()) {
3528             JSValue key = it->get(callFrame, asObject(callFrame->r(base).jsValue()), callFrame->r(i).i());
3529             callFrame->r(i) = Register::withInt(callFrame->r(i).i() + 1);
3530             if (key) {
3531                 CHECK_FOR_TIMEOUT();
3532                 callFrame->r(dst) = key;
3533                 vPC += target;
3534                 NEXT_INSTRUCTION();
3535             }
3536         }
3537
3538         vPC += OPCODE_LENGTH(op_next_pname);
3539         NEXT_INSTRUCTION();
3540     }
3541     DEFINE_OPCODE(op_jmp_scopes) {
3542         /* jmp_scopes count(n) target(offset)
3543
3544            Removes the a number of items from the current scope chain
3545            specified by immediate number count, then jumps to offset
3546            target.
3547         */
3548         int count = vPC[1].u.operand;
3549         int target = vPC[2].u.operand;
3550
3551         ScopeChainNode* tmp = callFrame->scopeChain();
3552         while (count--)
3553             tmp = tmp->pop();
3554         callFrame->setScopeChain(tmp);
3555
3556         vPC += target;
3557         NEXT_INSTRUCTION();
3558     }
3559     DEFINE_OPCODE(op_push_new_scope) {
3560         /* new_scope dst(r) property(id) value(r)
3561          
3562            Constructs a new StaticScopeObject with property set to value.  That scope
3563            object is then pushed onto the ScopeChain.  The scope object is then stored
3564            in dst for GC.
3565          */
3566         callFrame->setScopeChain(createExceptionScope(callFrame, vPC));
3567
3568         vPC += OPCODE_LENGTH(op_push_new_scope);
3569         NEXT_INSTRUCTION();
3570     }
3571     DEFINE_OPCODE(op_catch) {
3572         /* catch ex(r)
3573
3574            Retrieves the VM's current exception and puts it in register
3575            ex. This is only valid after an exception has been raised,
3576            and usually forms the beginning of an exception handler.
3577         */
3578         Q_ASSERT(exceptionValue);
3579         Q_ASSERT(!globalData->exception);
3580
3581         CodeBlock* codeBlock = callFrame->codeBlock();
3582         Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
3583         if (debugger) {
3584             DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
3585             debugger->exceptionCatch(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID());
3586         }
3587
3588         int ex = vPC[1].u.operand;
3589         callFrame->r(ex) = exceptionValue;
3590         exceptionValue = JSValue();
3591
3592         vPC += OPCODE_LENGTH(op_catch);
3593         NEXT_INSTRUCTION();
3594     }
3595     DEFINE_OPCODE(op_throw) {
3596         /* throw ex(r)
3597
3598            Throws register ex as an exception. This involves three
3599            steps: first, it is set as the current exception in the
3600            VM's internal state, then the stack is unwound until an
3601            exception handler or a native code boundary is found, and
3602            then control resumes at the exception handler if any or
3603            else the script returns control to the nearest native caller.
3604         */
3605
3606         int ex = vPC[1].u.operand;
3607         exceptionValue = callFrame->r(ex).jsValue();
3608
3609         handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
3610         if (!handler) {
3611             *exception = exceptionValue;
3612             return jsNull();
3613         }
3614
3615         vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
3616         NEXT_INSTRUCTION();
3617     }
3618     DEFINE_OPCODE(op_new_error) {
3619         /* new_error dst(r) type(n) message(k)
3620
3621            Constructs a new Error instance using the original
3622            constructor, using immediate number n as the type and
3623            constant message as the message string. The result is
3624            written to register dst.
3625         */
3626         int dst = vPC[1].u.operand;
3627         int type = vPC[2].u.operand;
3628         int message = vPC[3].u.operand;
3629
3630         CodeBlock* codeBlock = callFrame->codeBlock();
3631         callFrame->r(dst) = JSValue(Error::create(callFrame, (ErrorType)type, callFrame->r(message).jsValue().toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()));
3632
3633         vPC += OPCODE_LENGTH(op_new_error);
3634         NEXT_INSTRUCTION();
3635     }
3636     DEFINE_OPCODE(op_end) {
3637         /* end result(r)
3638            
3639            Return register result as the value of a global or eval
3640            program. Return control to the calling native code.
3641         */
3642
3643         if (callFrame->codeBlock()->needsFullScopeChain()) {
3644             ScopeChainNode* scopeChain = callFrame->scopeChain();
3645             Q_ASSERT(scopeChain->refCount > 1);
3646             scopeChain->deref();
3647         }
3648         int result = vPC[1].u.operand;
3649         return callFrame->r(result).jsValue();
3650     }
3651     DEFINE_OPCODE(op_put_getter) {
3652         /* put_getter base(r) property(id) function(r)
3653
3654            Sets register function on register base as the getter named
3655            by identifier property. Base and function are assumed to be
3656            objects as this op should only be used for getters defined
3657            in object literal form.
3658
3659            Unlike many opcodes, this one does not write any output to
3660            the register file.
3661         */
3662         int base = vPC[1].u.operand;
3663         int property = vPC[2].u.operand;
3664         int function = vPC[3].u.operand;
3665
3666         Q_ASSERT(callFrame->r(base).jsValue().isObject());
3667         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
3668         Identifier& ident = callFrame->codeBlock()->identifier(property);
3669         Q_ASSERT(callFrame->r(function).jsValue().isObject());
3670         baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
3671
3672         vPC += OPCODE_LENGTH(op_put_getter);
3673         NEXT_INSTRUCTION();
3674     }
3675     DEFINE_OPCODE(op_put_setter) {
3676         /* put_setter base(r) property(id) function(r)
3677
3678            Sets register function on register base as the setter named
3679            by identifier property. Base and function are assumed to be
3680            objects as this op should only be used for setters defined
3681            in object literal form.
3682
3683            Unlike many opcodes, this one does not write any output to
3684            the register file.
3685         */
3686         int base = vPC[1].u.operand;
3687         int property = vPC[2].u.operand;
3688         int function = vPC[3].u.operand;
3689
3690         Q_ASSERT(callFrame->r(base).jsValue().isObject());
3691         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
3692         Identifier& ident = callFrame->codeBlock()->identifier(property);
3693         Q_ASSERT(callFrame->r(function).jsValue().isObject());
3694         baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
3695
3696         vPC += OPCODE_LENGTH(op_put_setter);
3697         NEXT_INSTRUCTION();
3698     }
3699     DEFINE_OPCODE(op_method_check) {
3700         vPC++;
3701         NEXT_INSTRUCTION();
3702     }
3703     DEFINE_OPCODE(op_jsr) {
3704         /* jsr retAddrDst(r) target(offset)
3705
3706            Places the address of the next instruction into the retAddrDst
3707            register and jumps to offset target from the current instruction.
3708         */
3709         int retAddrDst = vPC[1].u.operand;
3710         int target = vPC[2].u.operand;
3711         callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr);
3712
3713         vPC += target;
3714         NEXT_INSTRUCTION();
3715     }
3716     DEFINE_OPCODE(op_sret) {
3717         /* sret retAddrSrc(r)
3718
3719          Jumps to the address stored in the retAddrSrc register. This
3720          differs from op_jmp because the target address is stored in a
3721          register, not as an immediate.
3722         */
3723         int retAddrSrc = vPC[1].u.operand;
3724         vPC = callFrame->r(retAddrSrc).vPC();
3725         NEXT_INSTRUCTION();
3726     }
3727     DEFINE_OPCODE(op_debug) {
3728         /* debug debugHookID(n) firstLine(n) lastLine(n)
3729
3730          Notifies the debugger of the current state of execution. This opcode
3731          is only generated while the debugger is attached.
3732         */
3733         int debugHookID = vPC[1].u.operand;
3734         int firstLine = vPC[2].u.operand;
3735         int lastLine = vPC[3].u.operand;
3736
3737         debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
3738
3739         vPC += OPCODE_LENGTH(op_debug);
3740         NEXT_INSTRUCTION();
3741     }
3742     vm_throw: {
3743         globalData->exception = JSValue();
3744         if (!tickCount) {
3745             // The exceptionValue is a lie! (GCC produces bad code for reasons I 
3746             // cannot fathom if we don't assign to the exceptionValue before branching)
3747             exceptionValue = createInterruptedExecutionException(globalData);
3748         }
3749         handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), false);
3750         if (!handler) {
3751             *exception = exceptionValue;
3752             return jsNull();
3753         }
3754
3755         vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
3756         NEXT_INSTRUCTION();
3757     }
3758     }
3759     } // iterator loop ends
3760     #undef NEXT_INSTRUCTION
3761     #undef DEFINE_OPCODE
3762     #undef CHECK_FOR_EXCEPTION
3763     #undef CHECK_FOR_TIMEOUT
3764 }
3765
3766 JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
3767 {
3768     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
3769     if (!functionCallFrame)
3770         return jsNull();
3771
3772     CodeBlock* codeBlock = functionCallFrame->codeBlock();
3773     if (codeBlock->usesArguments()) {
3774         Q_ASSERT(codeBlock->codeType() == FunctionCode);
3775         SymbolTable& symbolTable = *codeBlock->symbolTable();
3776         int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex();
3777         if (!functionCallFrame->r(argumentsIndex).jsValue()) {
3778             Arguments* arguments = new (callFrame) Arguments(functionCallFrame);
3779             functionCallFrame->setCalleeArguments(arguments);
3780             functionCallFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
3781         }
3782         return functionCallFrame->r(argumentsIndex).jsValue();
3783     }
3784
3785     Arguments* arguments = functionCallFrame->optionalCalleeArguments();
3786     if (!arguments) {
3787         arguments = new (functionCallFrame) Arguments(functionCallFrame);
3788         arguments->copyRegisters();
3789         callFrame->setCalleeArguments(arguments);
3790     }
3791
3792     return arguments;
3793 }
3794
3795 JSValue Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const
3796 {
3797     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
3798     if (!functionCallFrame)
3799         return jsNull();
3800
3801     CallFrame* callerFrame = functionCallFrame->callerFrame();
3802     if (callerFrame->hasHostCallFrameFlag())
3803         return jsNull();
3804
3805     JSValue caller = callerFrame->callee();
3806     if (!caller)
3807         return jsNull();
3808
3809     return caller;
3810 }
3811
3812 void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const
3813 {
3814     function = JSValue();
3815     lineNumber = -1;
3816     sourceURL = UString();
3817
3818     CallFrame* callerFrame = callFrame->callerFrame();
3819     if (callerFrame->hasHostCallFrameFlag())
3820         return;
3821
3822     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
3823     if (!callerCodeBlock)
3824         return;
3825
3826     unsigned bytecodeOffset = bytecodeOffsetForPC(callerCodeBlock, callFrame->returnPC());
3827     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
3828     sourceID = callerCodeBlock->ownerExecutable()->sourceID();
3829     sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
3830     function = callerFrame->callee();
3831 }
3832
3833 CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunction* function)
3834 {
3835     for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) {
3836         if (candidate->callee() == function)
3837             return candidate;
3838     }
3839     return 0;
3840 }
3841
3842 void Interpreter::enableSampler()
3843 {
3844 #if ENABLE(OPCODE_SAMPLING)
3845     if (!m_sampler) {
3846         m_sampler.set(new SamplingTool(this));
3847         m_sampler->setup();
3848     }
3849 #endif
3850 }
3851 void Interpreter::dumpSampleData(ExecState* exec)
3852 {
3853 #if ENABLE(OPCODE_SAMPLING)
3854     if (m_sampler)
3855         m_sampler->dump(exec);
3856 #else
3857     Q_UNUSED(exec);
3858 #endif
3859 }
3860 void Interpreter::startSampling()
3861 {
3862 #if ENABLE(SAMPLING_THREAD)
3863     if (!m_sampleEntryDepth)
3864         SamplingThread::start();
3865
3866     m_sampleEntryDepth++;
3867 #endif
3868 }
3869 void Interpreter::stopSampling()
3870 {
3871 #if ENABLE(SAMPLING_THREAD)
3872     m_sampleEntryDepth--;
3873     if (!m_sampleEntryDepth)
3874         SamplingThread::stop();
3875 #endif
3876 }
3877
3878 } // namespace JSC