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