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