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