diff options
Diffstat (limited to 'JavaScriptCore/interpreter/Interpreter.cpp')
| -rw-r--r-- | JavaScriptCore/interpreter/Interpreter.cpp | 3108 |
1 files changed, 639 insertions, 2469 deletions
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp index 8178d15..d980962 100644 --- a/JavaScriptCore/interpreter/Interpreter.cpp +++ b/JavaScriptCore/interpreter/Interpreter.cpp @@ -32,11 +32,14 @@ #include "Arguments.h" #include "BatchedTransitionOptimizer.h" +#include "CallFrame.h" +#include "CallFrameClosure.h" #include "CodeBlock.h" +#include "Collector.h" +#include "Debugger.h" #include "DebuggerCallFrame.h" #include "EvalCodeCache.h" #include "ExceptionHelpers.h" -#include "CallFrame.h" #include "GlobalEvalFunction.h" #include "JSActivation.h" #include "JSArray.h" @@ -44,19 +47,19 @@ #include "JSFunction.h" #include "JSNotAnObject.h" #include "JSPropertyNameIterator.h" +#include "LiteralParser.h" #include "JSStaticScopeObject.h" #include "JSString.h" #include "ObjectPrototype.h" +#include "Operations.h" #include "Parser.h" #include "Profiler.h" #include "RegExpObject.h" #include "RegExpPrototype.h" #include "Register.h" -#include "Collector.h" -#include "Debugger.h" -#include "Operations.h" #include "SamplingTool.h" #include <stdio.h> +#include <wtf/Threading.h> #if ENABLE(JIT) #include "JIT.h" @@ -88,7 +91,8 @@ static int depth(CodeBlock* codeBlock, ScopeChain& sc) return sc.localDepth(); } -NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) +#if USE(INTERPRETER) +NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) { int dst = (vPC + 1)->u.operand; int property = (vPC + 2)->u.operand; @@ -104,11 +108,11 @@ NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, J JSObject* o = *iter; PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { - JSValuePtr result = slot.getValue(callFrame, ident); + JSValue result = slot.getValue(callFrame, ident); exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[dst] = JSValuePtr(result); + callFrame[dst] = JSValue(result); return true; } } while (++iter != end); @@ -116,7 +120,7 @@ NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, J return false; } -NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) +NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) { CodeBlock* codeBlock = callFrame->codeBlock(); @@ -137,11 +141,11 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP JSObject* o = *iter; PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { - JSValuePtr result = slot.getValue(callFrame, ident); + JSValue result = slot.getValue(callFrame, ident); exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[dst] = JSValuePtr(result); + callFrame[dst] = JSValue(result); return true; } } while (++iter != end); @@ -149,7 +153,7 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP return false; } -NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) +NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) { int dst = (vPC + 1)->u.operand; JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell); @@ -159,7 +163,7 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* int offset = (vPC + 5)->u.operand; if (structure == globalObject->structure()) { - callFrame[dst] = JSValuePtr(globalObject->getDirectOffset(offset)); + callFrame[dst] = JSValue(globalObject->getDirectOffset(offset)); return true; } @@ -167,21 +171,21 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* Identifier& ident = codeBlock->identifier(property); PropertySlot slot(globalObject); if (globalObject->getPropertySlot(callFrame, ident, slot)) { - JSValuePtr result = slot.getValue(callFrame, ident); - if (slot.isCacheable() && !globalObject->structure()->isDictionary()) { + JSValue result = slot.getValue(callFrame, ident); + if (slot.isCacheable() && !globalObject->structure()->isDictionary() && slot.slotBase() == globalObject) { if (vPC[4].u.structure) vPC[4].u.structure->deref(); globalObject->structure()->ref(); vPC[4] = globalObject->structure(); vPC[5] = slot.cachedOffset(); - callFrame[dst] = JSValuePtr(result); + callFrame[dst] = JSValue(result); return true; } exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[dst] = JSValuePtr(result); + callFrame[dst] = JSValue(result); return true; } @@ -193,10 +197,10 @@ NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vP { int dst = (vPC + 1)->u.operand; int property = (vPC + 2)->u.operand; - callFrame[dst] = JSValuePtr(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain())); + callFrame[dst] = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain())); } -NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) +NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) { int baseDst = (vPC + 1)->u.operand; int propDst = (vPC + 2)->u.operand; @@ -217,12 +221,12 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst base = *iter; PropertySlot slot(base); if (base->getPropertySlot(callFrame, ident, slot)) { - JSValuePtr result = slot.getValue(callFrame, ident); + JSValue result = slot.getValue(callFrame, ident); exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[propDst] = JSValuePtr(result); - callFrame[baseDst] = JSValuePtr(base); + callFrame[propDst] = JSValue(result); + callFrame[baseDst] = JSValue(base); return true; } ++iter; @@ -232,7 +236,7 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst return false; } -NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValuePtr& exceptionValue) +NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) { int baseDst = (vPC + 1)->u.operand; int funcDst = (vPC + 2)->u.operand; @@ -261,13 +265,13 @@ NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruct // that in host objects you always get a valid object for this. // We also handle wrapper substitution for the global object at the same time. JSObject* thisObj = base->toThisObject(callFrame); - JSValuePtr result = slot.getValue(callFrame, ident); + JSValue result = slot.getValue(callFrame, ident); exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; - callFrame[baseDst] = JSValuePtr(thisObj); - callFrame[funcDst] = JSValuePtr(result); + callFrame[baseDst] = JSValue(thisObj); + callFrame[funcDst] = JSValue(result); return true; } ++iter; @@ -277,6 +281,8 @@ NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruct return false; } +#endif // USE(INTERPRETER) + ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc) { Register* r = callFrame->registers(); @@ -314,31 +320,46 @@ ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newC return CallFrame::create(r); } -static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValuePtr value, JSValuePtr& exceptionData) +#if USE(INTERPRETER) +static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData) { if (value.isObject()) return false; - exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instanceof" : "in" , value, vPC - codeBlock->instructions().begin(), codeBlock); + exceptionData = createInvalidParamError(callFrame, "in" , value, vPC - codeBlock->instructions().begin(), codeBlock); return true; } -NEVER_INLINE JSValuePtr Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValuePtr& exceptionValue) +static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData) +{ + if (value.isObject() && asObject(value)->structure()->typeInfo().implementsHasInstance()) + return false; + exceptionData = createInvalidParamError(callFrame, "instanceof" , value, vPC - codeBlock->instructions().begin(), codeBlock); + return true; +} +#endif + +NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue& exceptionValue) { if (argc < 2) return jsUndefined(); - JSValuePtr program = argv[1].jsValue(callFrame); + JSValue program = argv[1].jsValue(); if (!program.isString()) return program; UString programSource = asString(program)->value(); + LiteralParser preparser(callFrame, programSource); + if (JSValue parsedObject = preparser.tryLiteralParse()) + return parsedObject; + + ScopeChainNode* scopeChain = callFrame->scopeChain(); CodeBlock* codeBlock = callFrame->codeBlock(); RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue); - JSValuePtr result = jsUndefined(); + JSValue result = jsUndefined(); if (evalNode) result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue); @@ -449,7 +470,7 @@ bool Interpreter::isOpcode(Opcode opcode) #endif } -NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValuePtr exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock) +NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock) { CodeBlock* oldCodeBlock = codeBlock; ScopeChainNode* scopeChain = callFrame->scopeChain(); @@ -492,7 +513,7 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValuePtr return true; } -NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValuePtr& exceptionValue, unsigned bytecodeOffset, bool explicitThrow) +NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset, bool explicitThrow) { // Set up the exception object @@ -546,13 +567,13 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV if (Profiler* profiler = *Profiler::enabledProfilerReference()) { #if !ENABLE(JIT) if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode)) - profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 2].u.operand].jsValue(callFrame)); + profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 2].u.operand].jsValue()); else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct)) - profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue(callFrame)); + profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue()); #else int functionRegisterIndex; if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex)) - profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue(callFrame)); + profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue()); #endif } @@ -577,13 +598,15 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV return handler; } -JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValuePtr* exception) +JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception) { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxReentryDepth) { - *exception = createStackOverflowError(callFrame); - return jsNull(); + if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { + if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + *exception = createStackOverflowError(callFrame); + return jsNull(); + } } CodeBlock* codeBlock = &programNode->bytecode(scopeChain); @@ -602,7 +625,7 @@ JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, globalObject->copyGlobalsTo(m_registerFile); CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize); - newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj); + newCallFrame[codeBlock->thisRegister()] = JSValue(thisObj); newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0); if (codeBlock->needsFullScopeChain()) @@ -612,15 +635,13 @@ JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, if (*profiler) (*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo()); - JSValuePtr result; + JSValue result; { SamplingTool::CallRecord callRecord(m_sampler); m_reentryDepth++; #if ENABLE(JIT) - if (!codeBlock->jitCode()) - JIT::compile(scopeChain->globalData, codeBlock); - result = codeBlock->jitCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = programNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -638,13 +659,15 @@ JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, return result; } -JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValuePtr* exception) +JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception) { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxReentryDepth) { - *exception = createStackOverflowError(callFrame); - return jsNull(); + if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { + if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + *exception = createStackOverflowError(callFrame); + return jsNull(); + } } Register* oldEnd = m_registerFile.end(); @@ -659,7 +682,7 @@ JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* c CallFrame* newCallFrame = CallFrame::create(oldEnd); size_t dst = 0; - newCallFrame[0] = JSValuePtr(thisObj); + newCallFrame[0] = JSValue(thisObj); ArgList::const_iterator end = args.end(); for (ArgList::const_iterator it = args.begin(); it != end; ++it) newCallFrame[++dst] = *it; @@ -678,15 +701,13 @@ JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* c if (*profiler) (*profiler)->willExecute(callFrame, function); - JSValuePtr result; + JSValue result; { SamplingTool::CallRecord callRecord(m_sampler); m_reentryDepth++; #if ENABLE(JIT) - if (!codeBlock->jitCode()) - JIT::compile(scopeChain->globalData, codeBlock); - result = codeBlock->jitCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = functionBodyNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -700,18 +721,91 @@ JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* c return result; } -JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* exception) +CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception) +{ + ASSERT(!scopeChain->globalData->exception); + + if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { + if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + *exception = createStackOverflowError(callFrame); + return CallFrameClosure(); + } + } + + Register* oldEnd = m_registerFile.end(); + int argc = 1 + argCount; // implicit "this" parameter + + if (!m_registerFile.grow(oldEnd + argc)) { + *exception = createStackOverflowError(callFrame); + return CallFrameClosure(); + } + + CallFrame* newCallFrame = CallFrame::create(oldEnd); + size_t dst = 0; + for (int i = 0; i < argc; ++i) + newCallFrame[++dst] = jsUndefined(); + + CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain); + newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); + if (UNLIKELY(!newCallFrame)) { + *exception = createStackOverflowError(callFrame); + m_registerFile.shrink(oldEnd); + return CallFrameClosure(); + } + // a 0 codeBlock indicates a built-in caller + newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function); +#if ENABLE(JIT) + functionBodyNode->jitCode(scopeChain); +#endif + + CallFrameClosure result = { callFrame, newCallFrame, function, functionBodyNode, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc }; + return result; +} + +JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception) +{ + closure.resetCallFrame(); + Profiler** profiler = Profiler::enabledProfilerReference(); + if (*profiler) + (*profiler)->willExecute(closure.oldCallFrame, closure.function); + + JSValue result; + { + SamplingTool::CallRecord callRecord(m_sampler); + + m_reentryDepth++; +#if ENABLE(JIT) + result = closure.functionBody->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception); +#else + result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception); +#endif + m_reentryDepth--; + } + + if (*profiler) + (*profiler)->didExecute(closure.oldCallFrame, closure.function); + return result; +} + +void Interpreter::endRepeatCall(CallFrameClosure& closure) +{ + m_registerFile.shrink(closure.oldEnd); +} + +JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception) { return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNode->bytecode(scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception); } -JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValuePtr* exception) +JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception) { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxReentryDepth) { - *exception = createStackOverflowError(callFrame); - return jsNull(); + if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { + if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + *exception = createStackOverflowError(callFrame); + return jsNull(); + } } DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject()); @@ -760,7 +854,7 @@ JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObje CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset); // a 0 codeBlock indicates a built-in caller - newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj); + newCallFrame[codeBlock->thisRegister()] = JSValue(thisObj); newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0); if (codeBlock->needsFullScopeChain()) @@ -770,15 +864,13 @@ JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObje if (*profiler) (*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo()); - JSValuePtr result; + JSValue result; { SamplingTool::CallRecord callRecord(m_sampler); m_reentryDepth++; #if ENABLE(JIT) - if (!codeBlock->jitCode()) - JIT::compile(scopeChain->globalData, codeBlock); - result = codeBlock->jitCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = evalNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -819,30 +911,21 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook return; } } - + +#if USE(INTERPRETER) NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC) { int dst = (++vPC)->u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); Identifier& property = codeBlock->identifier((++vPC)->u.operand); - JSValuePtr value = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue value = callFrame[(++vPC)->u.operand].jsValue(); JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete); - callFrame[dst] = JSValuePtr(scope); + callFrame[dst] = JSValue(scope); return callFrame->scopeChain()->push(scope); } -static StructureChain* cachePrototypeChain(CallFrame* callFrame, Structure* structure) -{ - JSValuePtr prototype = structure->prototypeForLookup(callFrame); - if (!prototype.isCell()) - return 0; - RefPtr<StructureChain> chain = StructureChain::create(asObject(prototype)->structure()); - structure->setCachedPrototypeChain(chain.release()); - return structure->cachedPrototypeChain(); -} - -NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const PutPropertySlot& slot) +NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const PutPropertySlot& slot) { // Recursive invocation may already have specialized this instruction. if (vPC[0].u.opcode != getOpcode(op_put_by_id)) @@ -892,16 +975,7 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* vPC[0] = getOpcode(op_put_by_id_transition); vPC[4] = structure->previousID(); vPC[5] = structure; - StructureChain* chain = structure->cachedPrototypeChain(); - if (!chain) { - chain = cachePrototypeChain(callFrame, structure); - if (!chain) { - // This happens if someone has manually inserted null into the prototype chain - vPC[0] = getOpcode(op_put_by_id_generic); - return; - } - } - vPC[6] = chain; + vPC[6] = structure->prototypeChain(callFrame); vPC[7] = slot.cachedOffset(); codeBlock->refStructures(vPC); return; @@ -919,7 +993,7 @@ NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC[4] = 0; } -NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot) +NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot) { // Recursive invocation may already have specialized this instruction. if (vPC[0].u.opcode != getOpcode(op_get_by_id)) @@ -986,11 +1060,8 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* // Since we're accessing a prototype in a loop, it's a good bet that it // should not be treated as a dictionary. - if (baseObject->structure()->isDictionary()) { - RefPtr<Structure> transition = Structure::fromDictionaryTransition(baseObject->structure()); - baseObject->setStructure(transition.release()); - asCell(baseValue)->structure()->setCachedPrototypeChain(0); - } + if (baseObject->structure()->isDictionary()) + baseObject->setStructure(Structure::fromDictionaryTransition(baseObject->structure())); vPC[0] = getOpcode(op_get_by_id_proto); vPC[5] = baseObject->structure(); @@ -1006,14 +1077,9 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* return; } - StructureChain* chain = structure->cachedPrototypeChain(); - if (!chain) - chain = cachePrototypeChain(callFrame, structure); - ASSERT(chain); - vPC[0] = getOpcode(op_get_by_id_chain); vPC[4] = structure; - vPC[5] = chain; + vPC[5] = structure->prototypeChain(callFrame); vPC[6] = count; vPC[7] = slot.cachedOffset(); codeBlock->refStructures(vPC); @@ -1026,7 +1092,9 @@ NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC[4] = 0; } -JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValuePtr* exception) +#endif // USE(INTERPRETER) + +JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue* exception) { // One-time initialization of our address tables. We have to put this code // here because our labels are only in scope inside this function. @@ -1041,16 +1109,22 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe #undef ADD_OPCODE_ID ASSERT(m_opcodeIDTable.size() == numOpcodeIDs); #endif // HAVE(COMPUTED_GOTO) - return noValue(); + return JSValue(); } #if ENABLE(JIT) // Currently with CTI enabled we never interpret functions ASSERT_NOT_REACHED(); #endif +#if !USE(INTERPRETER) + UNUSED_PARAM(registerFile); + UNUSED_PARAM(callFrame); + UNUSED_PARAM(exception); + return JSValue(); +#else JSGlobalData* globalData = &callFrame->globalData(); - JSValuePtr exceptionValue = noValue(); + JSValue exceptionValue; HandlerInfo* handler = 0; Instruction* vPC = callFrame->codeBlock()->instructions().begin(); @@ -1059,7 +1133,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe #define CHECK_FOR_EXCEPTION() \ do { \ - if (UNLIKELY(globalData->exception != noValue())) { \ + if (UNLIKELY(globalData->exception != JSValue())) { \ exceptionValue = globalData->exception; \ goto vm_throw; \ } \ @@ -1111,7 +1185,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe constructor, and puts the result in register dst. */ int dst = (++vPC)->u.operand; - callFrame[dst] = JSValuePtr(constructEmptyObject(callFrame)); + callFrame[dst] = JSValue(constructEmptyObject(callFrame)); ++vPC; NEXT_INSTRUCTION(); @@ -1128,7 +1202,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int firstArg = (++vPC)->u.operand; int argCount = (++vPC)->u.operand; ArgList args(callFrame->registers() + firstArg, argCount); - callFrame[dst] = JSValuePtr(constructArray(callFrame, args)); + callFrame[dst] = JSValue(constructArray(callFrame, args)); ++vPC; NEXT_INSTRUCTION(); @@ -1142,7 +1216,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int regExp = (++vPC)->u.operand; - callFrame[dst] = JSValuePtr(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp))); + callFrame[dst] = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp))); ++vPC; NEXT_INSTRUCTION(); @@ -1167,12 +1241,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) callFrame[dst] = JSFastMath::equal(src1, src2); else { - JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCase(callFrame, src1, src2)); + JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1187,7 +1261,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src = callFrame[(++vPC)->u.operand].jsValue(); if (src.isUndefinedOrNull()) { callFrame[dst] = jsBoolean(true); @@ -1207,12 +1281,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) callFrame[dst] = JSFastMath::notEqual(src1, src2); else { - JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCase(callFrame, src1, src2)); + JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1227,7 +1301,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe operator, and puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src = callFrame[(++vPC)->u.operand].jsValue(); if (src.isUndefinedOrNull()) { callFrame[dst] = jsBoolean(false); @@ -1247,9 +1321,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - callFrame[dst] = jsBoolean(JSValuePtr::strictEqual(src1, src2)); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); + callFrame[dst] = jsBoolean(JSValue::strictEqual(src1, src2)); ++vPC; NEXT_INSTRUCTION(); @@ -1262,9 +1336,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - callFrame[dst] = jsBoolean(!JSValuePtr::strictEqual(src1, src2)); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); + callFrame[dst] = jsBoolean(!JSValue::strictEqual(src1, src2)); ++vPC; NEXT_INSTRUCTION(); @@ -1277,9 +1351,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr result = jsBoolean(jsLess(callFrame, src1, src2)); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue result = jsBoolean(jsLess(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; @@ -1294,9 +1368,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe puts the result as a boolean in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr result = jsBoolean(jsLessEq(callFrame, src1, src2)); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; @@ -1310,11 +1384,11 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe back in register srcDst. */ int srcDst = (++vPC)->u.operand; - JSValuePtr v = callFrame[srcDst].jsValue(callFrame); + JSValue v = callFrame[srcDst].jsValue(); if (JSFastMath::canDoFastAdditiveOperations(v)) - callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v)); + callFrame[srcDst] = JSValue(JSFastMath::incImmediateNumber(v)); else { - JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) + 1); + JSValue result = jsNumber(callFrame, v.toNumber(callFrame) + 1); CHECK_FOR_EXCEPTION(); callFrame[srcDst] = result; } @@ -1329,11 +1403,11 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe back in register srcDst. */ int srcDst = (++vPC)->u.operand; - JSValuePtr v = callFrame[srcDst].jsValue(callFrame); + JSValue v = callFrame[srcDst].jsValue(); if (JSFastMath::canDoFastAdditiveOperations(v)) - callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v)); + callFrame[srcDst] = JSValue(JSFastMath::decImmediateNumber(v)); else { - JSValuePtr result = jsNumber(callFrame, v.toNumber(callFrame) - 1); + JSValue result = jsNumber(callFrame, v.toNumber(callFrame) - 1); CHECK_FOR_EXCEPTION(); callFrame[srcDst] = result; } @@ -1350,15 +1424,15 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int srcDst = (++vPC)->u.operand; - JSValuePtr v = callFrame[srcDst].jsValue(callFrame); + JSValue v = callFrame[srcDst].jsValue(); if (JSFastMath::canDoFastAdditiveOperations(v)) { callFrame[dst] = v; - callFrame[srcDst] = JSValuePtr(JSFastMath::incImmediateNumber(v)); + callFrame[srcDst] = JSValue(JSFastMath::incImmediateNumber(v)); } else { - JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame); + JSValue number = callFrame[srcDst].jsValue().toJSNumber(callFrame); CHECK_FOR_EXCEPTION(); callFrame[dst] = number; - callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() + 1)); + callFrame[srcDst] = JSValue(jsNumber(callFrame, number.uncheckedGetNumber() + 1)); } ++vPC; @@ -1373,15 +1447,15 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int srcDst = (++vPC)->u.operand; - JSValuePtr v = callFrame[srcDst].jsValue(callFrame); + JSValue v = callFrame[srcDst].jsValue(); if (JSFastMath::canDoFastAdditiveOperations(v)) { callFrame[dst] = v; - callFrame[srcDst] = JSValuePtr(JSFastMath::decImmediateNumber(v)); + callFrame[srcDst] = JSValue(JSFastMath::decImmediateNumber(v)); } else { - JSValuePtr number = callFrame[srcDst].jsValue(callFrame).toJSNumber(callFrame); + JSValue number = callFrame[srcDst].jsValue().toJSNumber(callFrame); CHECK_FOR_EXCEPTION(); callFrame[dst] = number; - callFrame[srcDst] = JSValuePtr(jsNumber(callFrame, number.uncheckedGetNumber() - 1)); + callFrame[srcDst] = JSValue(jsNumber(callFrame, number.uncheckedGetNumber() - 1)); } ++vPC; @@ -1396,12 +1470,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - JSValuePtr srcVal = callFrame[src].jsValue(callFrame); + JSValue srcVal = callFrame[src].jsValue(); if (LIKELY(srcVal.isNumber())) callFrame[dst] = callFrame[src]; else { - JSValuePtr result = srcVal.toJSNumber(callFrame); + JSValue result = srcVal.toJSNumber(callFrame); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1416,13 +1490,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe result in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src = callFrame[(++vPC)->u.operand].jsValue(); ++vPC; double v; if (src.getNumber(v)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, -v)); + callFrame[dst] = JSValue(jsNumber(callFrame, -v)); else { - JSValuePtr result = jsNumber(callFrame, -src.toNumber(callFrame)); + JSValue result = jsNumber(callFrame, -src.toNumber(callFrame)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1437,12 +1511,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe numeric add, depending on the types of the operands.) */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); if (JSFastMath::canDoFastAdditiveOperations(src1, src2)) - callFrame[dst] = JSValuePtr(JSFastMath::addImmediateNumbers(src1, src2)); + callFrame[dst] = JSValue(JSFastMath::addImmediateNumbers(src1, src2)); else { - JSValuePtr result = jsAdd(callFrame, src1, src2); + JSValue result = jsAdd(callFrame, src1, src2); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1456,21 +1530,21 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe numbers), and puts the product in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); double left; double right; - if (JSValuePtr::areBothInt32Fast(src1, src2)) { + if (JSValue::areBothInt32Fast(src1, src2)) { int32_t left = src1.getInt32Fast(); int32_t right = src2.getInt32Fast(); if ((left | right) >> 15 == 0) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right)); + callFrame[dst] = JSValue(jsNumber(callFrame, left * right)); else - callFrame[dst] = JSValuePtr(jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right))); + callFrame[dst] = JSValue(jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right))); } else if (src1.getNumber(left) && src2.getNumber(right)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, left * right)); + callFrame[dst] = JSValue(jsNumber(callFrame, left * right)); else { - JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame)); + JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1486,14 +1560,14 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe quotient in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr dividend = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr divisor = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue dividend = callFrame[(++vPC)->u.operand].jsValue(); + JSValue divisor = callFrame[(++vPC)->u.operand].jsValue(); double left; double right; if (dividend.getNumber(left) && divisor.getNumber(right)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, left / right)); + callFrame[dst] = JSValue(jsNumber(callFrame, left / right)); else { - JSValuePtr result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame)); + JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1511,13 +1585,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int dividend = (++vPC)->u.operand; int divisor = (++vPC)->u.operand; - JSValuePtr dividendValue = callFrame[dividend].jsValue(callFrame); - JSValuePtr divisorValue = callFrame[divisor].jsValue(callFrame); + JSValue dividendValue = callFrame[dividend].jsValue(); + JSValue divisorValue = callFrame[divisor].jsValue(); - if (JSValuePtr::areBothInt32Fast(dividendValue, divisorValue) && divisorValue != js0()) { + if (JSValue::areBothInt32Fast(dividendValue, divisorValue) && divisorValue != jsNumber(callFrame, 0)) { // We expect the result of the modulus of a number that was representable as an int32 to also be representable // as an int32. - JSValuePtr result = JSValuePtr::makeInt32Fast(dividendValue.getInt32Fast() % divisorValue.getInt32Fast()); + JSValue result = JSValue::makeInt32Fast(dividendValue.getInt32Fast() % divisorValue.getInt32Fast()); ASSERT(result); callFrame[dst] = result; ++vPC; @@ -1525,7 +1599,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe } double d = dividendValue.toNumber(callFrame); - JSValuePtr result = jsNumber(callFrame, fmod(d, divisorValue.toNumber(callFrame))); + JSValue result = jsNumber(callFrame, fmod(d, divisorValue.toNumber(callFrame))); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; @@ -1539,16 +1613,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); double left; double right; if (JSFastMath::canDoFastAdditiveOperations(src1, src2)) - callFrame[dst] = JSValuePtr(JSFastMath::subImmediateNumbers(src1, src2)); + callFrame[dst] = JSValue(JSFastMath::subImmediateNumbers(src1, src2)); else if (src1.getNumber(left) && src2.getNumber(right)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, left - right)); + callFrame[dst] = JSValue(jsNumber(callFrame, left - right)); else { - JSValuePtr result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame)); + JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1563,16 +1637,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue val = callFrame[(++vPC)->u.operand].jsValue(); + JSValue shift = callFrame[(++vPC)->u.operand].jsValue(); int32_t left; uint32_t right; - if (JSValuePtr::areBothInt32Fast(val, shift)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f))); + if (JSValue::areBothInt32Fast(val, shift)) + callFrame[dst] = JSValue(jsNumber(callFrame, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f))); else if (val.numberToInt32(left) && shift.numberToUInt32(right)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, left << (right & 0x1f))); + callFrame[dst] = JSValue(jsNumber(callFrame, left << (right & 0x1f))); else { - JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f)); + JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1588,16 +1662,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe uint32), and puts the result in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue val = callFrame[(++vPC)->u.operand].jsValue(); + JSValue shift = callFrame[(++vPC)->u.operand].jsValue(); int32_t left; uint32_t right; if (JSFastMath::canDoFastRshift(val, shift)) - callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift)); + callFrame[dst] = JSValue(JSFastMath::rightShiftImmediateNumbers(val, shift)); else if (val.numberToInt32(left) && shift.numberToUInt32(right)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, left >> (right & 0x1f))); + callFrame[dst] = JSValue(jsNumber(callFrame, left >> (right & 0x1f))); else { - JSValuePtr result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); + JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1613,12 +1687,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe uint32), and puts the result in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr val = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr shift = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue val = callFrame[(++vPC)->u.operand].jsValue(); + JSValue shift = callFrame[(++vPC)->u.operand].jsValue(); if (JSFastMath::canDoFastUrshift(val, shift)) - callFrame[dst] = JSValuePtr(JSFastMath::rightShiftImmediateNumbers(val, shift)); + callFrame[dst] = JSValue(JSFastMath::rightShiftImmediateNumbers(val, shift)); else { - JSValuePtr result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); + JSValue result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1634,16 +1708,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); int32_t left; int32_t right; if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) - callFrame[dst] = JSValuePtr(JSFastMath::andImmediateNumbers(src1, src2)); + callFrame[dst] = JSValue(JSFastMath::andImmediateNumbers(src1, src2)); else if (src1.numberToInt32(left) && src2.numberToInt32(right)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, left & right)); + callFrame[dst] = JSValue(jsNumber(callFrame, left & right)); else { - JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame)); + JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1659,16 +1733,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); int32_t left; int32_t right; if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) - callFrame[dst] = JSValuePtr(JSFastMath::xorImmediateNumbers(src1, src2)); + callFrame[dst] = JSValue(JSFastMath::xorImmediateNumbers(src1, src2)); else if (src1.numberToInt32(left) && src2.numberToInt32(right)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, left ^ right)); + callFrame[dst] = JSValue(jsNumber(callFrame, left ^ right)); else { - JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame)); + JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1684,16 +1758,16 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe result in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); int32_t left; int32_t right; if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) - callFrame[dst] = JSValuePtr(JSFastMath::orImmediateNumbers(src1, src2)); + callFrame[dst] = JSValue(JSFastMath::orImmediateNumbers(src1, src2)); else if (src1.numberToInt32(left) && src2.numberToInt32(right)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, left | right)); + callFrame[dst] = JSValue(jsNumber(callFrame, left | right)); else { - JSValuePtr result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame)); + JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1708,12 +1782,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe and puts the result in register dst. */ int dst = (++vPC)->u.operand; - JSValuePtr src = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src = callFrame[(++vPC)->u.operand].jsValue(); int32_t value; if (src.numberToInt32(value)) - callFrame[dst] = JSValuePtr(jsNumber(callFrame, ~value)); + callFrame[dst] = JSValue(jsNumber(callFrame, ~value)); else { - JSValuePtr result = jsNumber(callFrame, ~src.toInt32(callFrame)); + JSValue result = jsNumber(callFrame, ~src.toInt32(callFrame)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; } @@ -1728,7 +1802,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - JSValuePtr result = jsBoolean(!callFrame[src].jsValue(callFrame).toBoolean(callFrame)); + JSValue result = jsBoolean(!callFrame[src].jsValue().toBoolean(callFrame)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; @@ -1753,18 +1827,14 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int base = vPC[3].u.operand; int baseProto = vPC[4].u.operand; - JSValuePtr baseVal = callFrame[base].jsValue(callFrame); + JSValue baseVal = callFrame[base].jsValue(); - if (isNotObject(callFrame, true, callFrame->codeBlock(), vPC, baseVal, exceptionValue)) + if (isInvalidParamForInstanceOf(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue)) goto vm_throw; - JSObject* baseObj = asObject(baseVal); - if (baseObj->structure()->typeInfo().implementsHasInstance()) { - bool result = baseObj->hasInstance(callFrame, callFrame[value].jsValue(callFrame), callFrame[baseProto].jsValue(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame[dst] = jsBoolean(result); - } else - callFrame[dst] = jsBoolean(false); + bool result = asObject(baseVal)->hasInstance(callFrame, callFrame[value].jsValue(), callFrame[baseProto].jsValue()); + CHECK_FOR_EXCEPTION(); + callFrame[dst] = jsBoolean(result); vPC += 5; NEXT_INSTRUCTION(); @@ -1777,7 +1847,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = JSValuePtr(jsTypeStringForValue(callFrame, callFrame[src].jsValue(callFrame))); + callFrame[dst] = JSValue(jsTypeStringForValue(callFrame, callFrame[src].jsValue())); ++vPC; NEXT_INSTRUCTION(); @@ -1791,7 +1861,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - JSValuePtr v = callFrame[src].jsValue(callFrame); + JSValue v = callFrame[src].jsValue(); callFrame[dst] = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()); ++vPC; @@ -1806,7 +1876,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isBoolean()); + callFrame[dst] = jsBoolean(callFrame[src].jsValue().isBoolean()); ++vPC; NEXT_INSTRUCTION(); @@ -1820,7 +1890,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isNumber()); + callFrame[dst] = jsBoolean(callFrame[src].jsValue().isNumber()); ++vPC; NEXT_INSTRUCTION(); @@ -1834,7 +1904,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame).isString()); + callFrame[dst] = jsBoolean(callFrame[src].jsValue().isString()); ++vPC; NEXT_INSTRUCTION(); @@ -1848,7 +1918,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = jsBoolean(jsIsObjectType(callFrame[src].jsValue(callFrame))); + callFrame[dst] = jsBoolean(jsIsObjectType(callFrame[src].jsValue())); ++vPC; NEXT_INSTRUCTION(); @@ -1862,7 +1932,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = jsBoolean(jsIsFunctionType(callFrame[src].jsValue(callFrame))); + callFrame[dst] = jsBoolean(jsIsFunctionType(callFrame[src].jsValue())); ++vPC; NEXT_INSTRUCTION(); @@ -1880,13 +1950,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int property = (++vPC)->u.operand; int base = (++vPC)->u.operand; - JSValuePtr baseVal = callFrame[base].jsValue(callFrame); - if (isNotObject(callFrame, false, callFrame->codeBlock(), vPC, baseVal, exceptionValue)) + JSValue baseVal = callFrame[base].jsValue(); + if (isInvalidParamForIn(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue)) goto vm_throw; JSObject* baseObj = asObject(baseVal); - JSValuePtr propName = callFrame[property].jsValue(callFrame); + JSValue propName = callFrame[property].jsValue(); uint32_t i; if (propName.getUInt32(i)) @@ -1966,7 +2036,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int index = (++vPC)->u.operand; int value = (++vPC)->u.operand; - scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame)); + scope->registerAt(index) = JSValue(callFrame[value].jsValue()); ++vPC; NEXT_INSTRUCTION(); } @@ -2014,7 +2084,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe ASSERT((*iter)->isVariableObject()); JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); - scope->registerAt(index) = JSValuePtr(callFrame[value].jsValue(callFrame)); + scope->registerAt(index) = JSValue(callFrame[value].jsValue()); ++vPC; NEXT_INSTRUCTION(); } @@ -2082,9 +2152,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe CodeBlock* codeBlock = callFrame->codeBlock(); Identifier& ident = codeBlock->identifier(property); - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(callFrame, ident, slot); + JSValue result = baseValue.get(callFrame, ident, slot); CHECK_FOR_EXCEPTION(); tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot); @@ -2101,7 +2171,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe op_get_by_id. */ int base = vPC[2].u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); @@ -2114,7 +2184,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int offset = vPC[5].u.operand; ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); - callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset)); + callFrame[dst] = JSValue(baseObject->getDirectOffset(offset)); vPC += 8; NEXT_INSTRUCTION(); @@ -2132,7 +2202,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe reverts to op_get_by_id. */ int base = vPC[2].u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); @@ -2148,7 +2218,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int offset = vPC[6].u.operand; ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset)); - callFrame[dst] = JSValuePtr(protoObject->getDirectOffset(offset)); + callFrame[dst] = JSValue(protoObject->getDirectOffset(offset)); vPC += 8; NEXT_INSTRUCTION(); @@ -2181,7 +2251,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe reverts to op_get_by_id. */ int base = vPC[2].u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); @@ -2203,7 +2273,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int offset = vPC[7].u.operand; ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); - callFrame[dst] = JSValuePtr(baseObject->getDirectOffset(offset)); + callFrame[dst] = JSValue(baseObject->getDirectOffset(offset)); vPC += 8; NEXT_INSTRUCTION(); @@ -2229,9 +2299,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int property = vPC[3].u.operand; Identifier& ident = callFrame->codeBlock()->identifier(property); - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(callFrame, ident, slot); + JSValue result = baseValue.get(callFrame, ident, slot); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; @@ -2247,10 +2317,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int base = vPC[2].u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); if (LIKELY(isJSArray(globalData, baseValue))) { int dst = vPC[1].u.operand; - callFrame[dst] = JSValuePtr(jsNumber(callFrame, asArray(baseValue)->length())); + callFrame[dst] = JSValue(jsNumber(callFrame, asArray(baseValue)->length())); vPC += 8; NEXT_INSTRUCTION(); } @@ -2267,10 +2337,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int base = vPC[2].u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); if (LIKELY(isJSString(globalData, baseValue))) { int dst = vPC[1].u.operand; - callFrame[dst] = JSValuePtr(jsNumber(callFrame, asString(baseValue)->value().size())); + callFrame[dst] = JSValue(jsNumber(callFrame, asString(baseValue)->value().size())); vPC += 8; NEXT_INSTRUCTION(); } @@ -2293,10 +2363,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int value = vPC[3].u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); Identifier& ident = codeBlock->identifier(property); PutPropertySlot slot; - baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot); + baseValue.put(callFrame, ident, callFrame[value].jsValue(), slot); CHECK_FOR_EXCEPTION(); tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot); @@ -2316,7 +2386,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe the register file. */ int base = vPC[1].u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); @@ -2329,7 +2399,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe RefPtr<Structure>* it = vPC[6].u.structureChain->head(); - JSValuePtr proto = baseObject->structure()->prototypeForLookup(callFrame); + JSValue proto = baseObject->structure()->prototypeForLookup(callFrame); while (!proto.isNull()) { if (UNLIKELY(asObject(proto)->structure() != (*it).get())) { uncachePutByID(callFrame->codeBlock(), vPC); @@ -2344,7 +2414,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int value = vPC[3].u.operand; unsigned offset = vPC[7].u.operand; ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset); - baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame)); + baseObject->putDirectOffset(offset, callFrame[value].jsValue()); vPC += 8; NEXT_INSTRUCTION(); @@ -2366,7 +2436,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe the register file. */ int base = vPC[1].u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); if (LIKELY(baseValue.isCell())) { JSCell* baseCell = asCell(baseValue); @@ -2379,7 +2449,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe unsigned offset = vPC[5].u.operand; ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset); - baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame)); + baseObject->putDirectOffset(offset, callFrame[value].jsValue()); vPC += 8; NEXT_INSTRUCTION(); @@ -2402,10 +2472,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int property = vPC[2].u.operand; int value = vPC[3].u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); Identifier& ident = callFrame->codeBlock()->identifier(property); PutPropertySlot slot; - baseValue.put(callFrame, ident, callFrame[value].jsValue(callFrame), slot); + baseValue.put(callFrame, ident, callFrame[value].jsValue(), slot); CHECK_FOR_EXCEPTION(); vPC += 8; @@ -2423,9 +2493,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int base = (++vPC)->u.operand; int property = (++vPC)->u.operand; - JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame); + JSObject* baseObj = callFrame[base].jsValue().toObject(callFrame); Identifier& ident = callFrame->codeBlock()->identifier(property); - JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, ident)); + JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident)); CHECK_FOR_EXCEPTION(); callFrame[dst] = result; ++vPC; @@ -2443,10 +2513,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int base = (++vPC)->u.operand; int property = (++vPC)->u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); - JSValuePtr subscript = callFrame[property].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); + JSValue subscript = callFrame[property].jsValue(); - JSValuePtr result; + JSValue result; if (LIKELY(subscript.isUInt32Fast())) { uint32_t i = subscript.getUInt32Fast(); @@ -2487,21 +2557,21 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int property = (++vPC)->u.operand; int value = (++vPC)->u.operand; - JSValuePtr baseValue = callFrame[base].jsValue(callFrame); - JSValuePtr subscript = callFrame[property].jsValue(callFrame); + JSValue baseValue = callFrame[base].jsValue(); + JSValue subscript = callFrame[property].jsValue(); if (LIKELY(subscript.isUInt32Fast())) { uint32_t i = subscript.getUInt32Fast(); if (isJSArray(globalData, baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canSetIndex(i)) - jsArray->setIndex(i, callFrame[value].jsValue(callFrame)); + jsArray->setIndex(i, callFrame[value].jsValue()); else - jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue(callFrame)); + jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue()); } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { JSByteArray* jsByteArray = asByteArray(baseValue); double dValue = 0; - JSValuePtr jsValue = callFrame[value].jsValue(callFrame); + JSValue jsValue = callFrame[value].jsValue(); if (jsValue.isInt32Fast()) jsByteArray->setIndex(i, jsValue.getInt32Fast()); else if (jsValue.getNumber(dValue)) @@ -2509,12 +2579,12 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe else baseValue.put(callFrame, i, jsValue); } else - baseValue.put(callFrame, i, callFrame[value].jsValue(callFrame)); + baseValue.put(callFrame, i, callFrame[value].jsValue()); } else { Identifier property(callFrame, subscript.toString(callFrame)); if (!globalData->exception) { // Don't put to an object if toString threw an exception. PutPropertySlot slot; - baseValue.put(callFrame, property, callFrame[value].jsValue(callFrame), slot); + baseValue.put(callFrame, property, callFrame[value].jsValue(), slot); } } @@ -2534,10 +2604,10 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int base = (++vPC)->u.operand; int property = (++vPC)->u.operand; - JSObject* baseObj = callFrame[base].jsValue(callFrame).toObject(callFrame); // may throw + JSObject* baseObj = callFrame[base].jsValue().toObject(callFrame); // may throw - JSValuePtr subscript = callFrame[property].jsValue(callFrame); - JSValuePtr result; + JSValue subscript = callFrame[property].jsValue(); + JSValue result; uint32_t i; if (subscript.getUInt32(i)) result = jsBoolean(baseObj->deleteProperty(callFrame, i)); @@ -2569,7 +2639,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe unsigned property = (++vPC)->u.operand; int value = (++vPC)->u.operand; - callFrame[base].jsValue(callFrame).put(callFrame, property, callFrame[value].jsValue(callFrame)); + callFrame[base].jsValue().put(callFrame, property, callFrame[value].jsValue()); ++vPC; NEXT_INSTRUCTION(); @@ -2616,7 +2686,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int cond = (++vPC)->u.operand; int target = (++vPC)->u.operand; - if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) { + if (callFrame[cond].jsValue().toBoolean(callFrame)) { vPC += target; CHECK_FOR_TIMEOUT(); NEXT_INSTRUCTION(); @@ -2633,7 +2703,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int cond = (++vPC)->u.operand; int target = (++vPC)->u.operand; - if (callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) { + if (callFrame[cond].jsValue().toBoolean(callFrame)) { vPC += target; NEXT_INSTRUCTION(); } @@ -2649,7 +2719,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int cond = (++vPC)->u.operand; int target = (++vPC)->u.operand; - if (!callFrame[cond].jsValue(callFrame).toBoolean(callFrame)) { + if (!callFrame[cond].jsValue().toBoolean(callFrame)) { vPC += target; NEXT_INSTRUCTION(); } @@ -2665,7 +2735,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int src = (++vPC)->u.operand; int target = (++vPC)->u.operand; - JSValuePtr srcValue = callFrame[src].jsValue(callFrame); + JSValue srcValue = callFrame[src].jsValue(); if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) { vPC += target; @@ -2683,7 +2753,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int src = (++vPC)->u.operand; int target = (++vPC)->u.operand; - JSValuePtr srcValue = callFrame[src].jsValue(callFrame); + JSValue srcValue = callFrame[src].jsValue(); if (!srcValue.isUndefinedOrNull() || (srcValue.isCell() && !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) { vPC += target; @@ -2693,6 +2763,24 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe ++vPC; NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_jneq_ptr) { + /* jneq_ptr src(r) ptr(jsCell) target(offset) + + Jumps to offset target from the current instruction, if the value r is equal + to ptr, using pointer equality. + */ + int src = (++vPC)->u.operand; + JSValue ptr = JSValue((++vPC)->u.jsCell); + int target = (++vPC)->u.operand; + JSValue srcValue = callFrame[src].jsValue(); + if (srcValue != ptr) { + vPC += target; + NEXT_INSTRUCTION(); + } + + ++vPC; + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_loop_if_less) { /* loop_if_less src1(r) src2(r) target(offset) @@ -2704,8 +2792,8 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe Additionally this loop instruction may terminate JS execution is the JS timeout is reached. */ - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); int target = (++vPC)->u.operand; bool result = jsLess(callFrame, src1, src2); @@ -2731,8 +2819,8 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe Additionally this loop instruction may terminate JS execution is the JS timeout is reached. */ - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); int target = (++vPC)->u.operand; bool result = jsLessEq(callFrame, src1, src2); @@ -2755,8 +2843,8 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe target from the current instruction, if and only if the result of the comparison is false. */ - JSValuePtr src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame); - JSValuePtr src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); int target = (++vPC)->u.operand; bool result = jsLess(callFrame, src1, src2); @@ -2770,6 +2858,29 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe ++vPC; NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_jnlesseq) { + /* jnlesseq src1(r) src2(r) target(offset) + + Checks whether register src1 is less than or equal to + register src2, as with the ECMAScript '<=' operator, + and then jumps to offset target from the current instruction, + if and only if theresult of the comparison is false. + */ + JSValue src1 = callFrame[(++vPC)->u.operand].jsValue(); + JSValue src2 = callFrame[(++vPC)->u.operand].jsValue(); + int target = (++vPC)->u.operand; + + bool result = jsLessEq(callFrame, src1, src2); + CHECK_FOR_EXCEPTION(); + + if (!result) { + vPC += target; + NEXT_INSTRUCTION(); + } + + ++vPC; + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_switch_imm) { /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r) @@ -2781,7 +2892,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int tableIndex = (++vPC)->u.operand; int defaultOffset = (++vPC)->u.operand; - JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue scrutinee = callFrame[(++vPC)->u.operand].jsValue(); if (scrutinee.isInt32Fast()) vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.getInt32Fast(), defaultOffset); else { @@ -2805,7 +2916,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int tableIndex = (++vPC)->u.operand; int defaultOffset = (++vPC)->u.operand; - JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue scrutinee = callFrame[(++vPC)->u.operand].jsValue(); if (!scrutinee.isString()) vPC += defaultOffset; else { @@ -2828,7 +2939,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int tableIndex = (++vPC)->u.operand; int defaultOffset = (++vPC)->u.operand; - JSValuePtr scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame); + JSValue scrutinee = callFrame[(++vPC)->u.operand].jsValue(); if (!scrutinee.isString()) vPC += defaultOffset; else @@ -2884,15 +2995,15 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int argCount = vPC[3].u.operand; int registerOffset = vPC[4].u.operand; - JSValuePtr funcVal = callFrame[func].jsValue(callFrame); + JSValue funcVal = callFrame[func].jsValue(); Register* newCallFrame = callFrame->registers() + registerOffset; Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; - JSValuePtr thisValue = argv[0].jsValue(callFrame); + JSValue thisValue = argv[0].jsValue(); JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { - JSValuePtr result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); + JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); if (exceptionValue) goto vm_throw; callFrame[dst] = result; @@ -2921,7 +3032,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int argCount = vPC[3].u.operand; int registerOffset = vPC[4].u.operand; - JSValuePtr v = callFrame[func].jsValue(callFrame); + JSValue v = callFrame[func].jsValue(); CallData callData; CallType callType = v.getCallData(callData); @@ -2959,18 +3070,18 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe ArgList args(thisRegister + 1, argCount - 1); // FIXME: All host methods should be calling toThisObject, but this is not presently the case. - JSValuePtr thisValue = thisRegister->jsValue(callFrame); + JSValue thisValue = thisRegister->jsValue(); if (thisValue == jsNull()) thisValue = callFrame->globalThisValue(); - JSValuePtr returnValue; + JSValue returnValue; { SamplingTool::HostCallRecord callRecord(m_sampler); returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args); } CHECK_FOR_EXCEPTION(); - callFrame[dst] = JSValuePtr(returnValue); + callFrame[dst] = JSValue(returnValue); vPC += 5; NEXT_INSTRUCTION(); @@ -2981,6 +3092,160 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock()); goto vm_throw; } + DEFINE_OPCODE(op_load_varargs) { + int argCountDst = (++vPC)->u.operand; + int argsOffset = (++vPC)->u.operand; + + JSValue arguments = callFrame[argsOffset].jsValue(); + uint32_t argCount = 0; + if (!arguments) { + argCount = (uint32_t)(callFrame[RegisterFile::ArgumentCount].u.i) - 1; + int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize; + Register* newEnd = callFrame->registers() + sizeDelta; + if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) { + exceptionValue = createStackOverflowError(callFrame); + goto vm_throw; + } + uint32_t expectedParams = asFunction(callFrame[RegisterFile::Callee].jsValue())->body()->parameterCount(); + uint32_t inplaceArgs = min(argCount, expectedParams); + uint32_t i = 0; + Register* argStore = callFrame->registers() + argsOffset; + + // First step is to copy the "expected" parameters from their normal location relative to the callframe + for (; i < inplaceArgs; i++) + argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams]; + // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this') + for (; i < argCount; i++) + argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - argCount - 1]; + } else if (!arguments.isUndefinedOrNull()) { + if (!arguments.isObject()) { + exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock()); + goto vm_throw; + } + if (asObject(arguments)->classInfo() == &Arguments::info) { + Arguments* args = asArguments(arguments); + argCount = args->numProvidedArguments(callFrame); + int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize; + Register* newEnd = callFrame->registers() + sizeDelta; + if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) { + exceptionValue = createStackOverflowError(callFrame); + goto vm_throw; + } + args->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount); + } else if (isJSArray(&callFrame->globalData(), arguments)) { + JSArray* array = asArray(arguments); + argCount = array->length(); + int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize; + Register* newEnd = callFrame->registers() + sizeDelta; + if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) { + exceptionValue = createStackOverflowError(callFrame); + goto vm_throw; + } + array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount); + } else if (asObject(arguments)->inherits(&JSArray::info)) { + JSObject* argObject = asObject(arguments); + argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame); + int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize; + Register* newEnd = callFrame->registers() + sizeDelta; + if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) { + exceptionValue = createStackOverflowError(callFrame); + goto vm_throw; + } + Register* argsBuffer = callFrame->registers() + argsOffset; + for (unsigned i = 0; i < argCount; ++i) { + argsBuffer[i] = asObject(arguments)->get(callFrame, i); + CHECK_FOR_EXCEPTION(); + } + } else { + if (!arguments.isObject()) { + exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock()); + goto vm_throw; + } + } + } + CHECK_FOR_EXCEPTION(); + callFrame[argCountDst] = argCount + 1; + ++vPC; + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_call_varargs) { + /* call_varargs dst(r) func(r) argCountReg(r) baseRegisterOffset(n) + + Perform a function call with a dynamic set of arguments. + + registerOffset is the distance the callFrame pointer should move + before the VM initializes the new call frame's header, excluding + space for arguments. + + dst is where op_ret should store its result. + */ + + int dst = vPC[1].u.operand; + int func = vPC[2].u.operand; + int argCountReg = vPC[3].u.operand; + int registerOffset = vPC[4].u.operand; + + JSValue v = callFrame[func].jsValue(); + int argCount = callFrame[argCountReg].i(); + registerOffset += argCount; + CallData callData; + CallType callType = v.getCallData(callData); + + if (callType == CallTypeJS) { + ScopeChainNode* callDataScopeChain = callData.js.scopeChain; + FunctionBodyNode* functionBodyNode = callData.js.functionBody; + CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain); + + CallFrame* previousCallFrame = callFrame; + + callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); + if (UNLIKELY(!callFrame)) { + callFrame = previousCallFrame; + exceptionValue = createStackOverflowError(callFrame); + goto vm_throw; + } + + callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v)); + vPC = newCodeBlock->instructions().begin(); + +#if ENABLE(OPCODE_STATS) + OpcodeStats::resetLastInstruction(); +#endif + + NEXT_INSTRUCTION(); + } + + if (callType == CallTypeHost) { + ScopeChainNode* scopeChain = callFrame->scopeChain(); + CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); + newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0); + + Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; + ArgList args(thisRegister + 1, argCount - 1); + + // FIXME: All host methods should be calling toThisObject, but this is not presently the case. + JSValue thisValue = thisRegister->jsValue(); + if (thisValue == jsNull()) + thisValue = callFrame->globalThisValue(); + + JSValue returnValue; + { + SamplingTool::HostCallRecord callRecord(m_sampler); + returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args); + } + CHECK_FOR_EXCEPTION(); + + callFrame[dst] = JSValue(returnValue); + + vPC += 5; + NEXT_INSTRUCTION(); + } + + ASSERT(callType == CallTypeNone); + + exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock()); + goto vm_throw; + } DEFINE_OPCODE(op_tear_off_activation) { /* tear_off_activation activation(r) @@ -2997,7 +3262,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int src = (++vPC)->u.operand; ASSERT(callFrame->codeBlock()->needsFullScopeChain()); - asActivation(callFrame[src].getJSValue())->copyRegisters(callFrame->optionalCalleeArguments()); + asActivation(callFrame[src].jsValue())->copyRegisters(callFrame->optionalCalleeArguments()); ++vPC; NEXT_INSTRUCTION(); @@ -3016,8 +3281,8 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain()); - - callFrame->optionalCalleeArguments()->copyRegisters(); + if (callFrame->optionalCalleeArguments()) + callFrame->optionalCalleeArguments()->copyRegisters(); ++vPC; NEXT_INSTRUCTION(); @@ -3037,7 +3302,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe if (callFrame->codeBlock()->needsFullScopeChain()) callFrame->scopeChain()->deref(); - JSValuePtr returnValue = callFrame[result].jsValue(callFrame); + JSValue returnValue = callFrame[result].jsValue(); vPC = callFrame->returnPC(); int dst = callFrame->returnValueRegister(); @@ -3046,7 +3311,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe if (callFrame->hasHostCallFrameFlag()) return returnValue; - callFrame[dst] = JSValuePtr(returnValue); + callFrame[dst] = JSValue(returnValue); NEXT_INSTRUCTION(); } @@ -3116,28 +3381,40 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int thisRegister = (++vPC)->u.operand; - JSValuePtr thisVal = callFrame[thisRegister].getJSValue(); + JSValue thisVal = callFrame[thisRegister].jsValue(); if (thisVal.needsThisConversion()) - callFrame[thisRegister] = JSValuePtr(thisVal.toThisObject(callFrame)); + callFrame[thisRegister] = JSValue(thisVal.toThisObject(callFrame)); ++vPC; NEXT_INSTRUCTION(); } - DEFINE_OPCODE(op_create_arguments) { + DEFINE_OPCODE(op_init_arguments) { /* create_arguments - Creates the 'arguments' object and places it in both the - 'arguments' call frame slot and the local 'arguments' - register. + Initialises the arguments object reference to null to ensure + we can correctly detect that we need to create it later (or + avoid creating it altogether). This opcode should only be used at the beginning of a code block. - */ + */ + callFrame[RegisterFile::ArgumentsRegister] = JSValue(); + ++vPC; + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_create_arguments) { + /* create_arguments - Arguments* arguments = new (globalData) Arguments(callFrame); - callFrame->setCalleeArguments(arguments); - callFrame[RegisterFile::ArgumentsRegister] = arguments; + Creates the 'arguments' object and places it in both the + 'arguments' call frame slot and the local 'arguments' + register, if it has not already been initialised. + */ + if (!callFrame->optionalCalleeArguments()) { + Arguments* arguments = new (globalData) Arguments(callFrame); + callFrame->setCalleeArguments(arguments); + callFrame[RegisterFile::ArgumentsRegister] = arguments; + } ++vPC; NEXT_INSTRUCTION(); } @@ -3163,7 +3440,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int proto = vPC[5].u.operand; int thisRegister = vPC[6].u.operand; - JSValuePtr v = callFrame[func].jsValue(callFrame); + JSValue v = callFrame[func].jsValue(); ConstructData constructData; ConstructType constructType = v.getConstructData(constructData); @@ -3174,14 +3451,14 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain); Structure* structure; - JSValuePtr prototype = callFrame[proto].jsValue(callFrame); + JSValue prototype = callFrame[proto].jsValue(); if (prototype.isObject()) structure = asObject(prototype)->inheritorID(); else structure = callDataScopeChain->globalObject()->emptyObjectStructure(); JSObject* newObject = new (globalData) JSObject(structure); - callFrame[thisRegister] = JSValuePtr(newObject); // "this" value + callFrame[thisRegister] = JSValue(newObject); // "this" value CallFrame* previousCallFrame = callFrame; @@ -3209,13 +3486,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0); - JSValuePtr returnValue; + JSValue returnValue; { SamplingTool::HostCallRecord callRecord(m_sampler); returnValue = constructData.native.function(newCallFrame, asObject(v), args); } CHECK_FOR_EXCEPTION(); - callFrame[dst] = JSValuePtr(returnValue); + callFrame[dst] = JSValue(returnValue); vPC += 7; NEXT_INSTRUCTION(); @@ -3234,7 +3511,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = vPC[1].u.operand; - if (LIKELY(callFrame[dst].jsValue(callFrame).isObject())) { + if (LIKELY(callFrame[dst].jsValue().isObject())) { vPC += 3; NEXT_INSTRUCTION(); } @@ -3245,6 +3522,25 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe vPC += 3; NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_strcat) { + int dst = (++vPC)->u.operand; + int src = (++vPC)->u.operand; + int count = (++vPC)->u.operand; + + callFrame[dst] = concatenateStrings(callFrame, &callFrame->registers()[src], count); + ++vPC; + + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_to_primitive) { + int dst = (++vPC)->u.operand; + int src = (++vPC)->u.operand; + + callFrame[dst] = callFrame[src].jsValue().toPrimitive(callFrame); + ++vPC; + + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_push_scope) { /* push_scope scope(r) @@ -3253,11 +3549,11 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe are replaced by the result of toObject conversion of the scope. */ int scope = (++vPC)->u.operand; - JSValuePtr v = callFrame[scope].jsValue(callFrame); + JSValue v = callFrame[scope].jsValue(); JSObject* o = v.toObject(callFrame); CHECK_FOR_EXCEPTION(); - callFrame[scope] = JSValuePtr(o); + callFrame[scope] = JSValue(o); callFrame->setScopeChain(callFrame->scopeChain()->push(o)); ++vPC; @@ -3284,7 +3580,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int dst = (++vPC)->u.operand; int base = (++vPC)->u.operand; - callFrame[dst] = JSPropertyNameIterator::create(callFrame, callFrame[base].jsValue(callFrame)); + callFrame[dst] = JSPropertyNameIterator::create(callFrame, callFrame[base].jsValue()); ++vPC; NEXT_INSTRUCTION(); } @@ -3302,9 +3598,9 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int target = (++vPC)->u.operand; JSPropertyNameIterator* it = callFrame[iter].propertyNameIterator(); - if (JSValuePtr temp = it->next(callFrame)) { + if (JSValue temp = it->next(callFrame)) { CHECK_FOR_TIMEOUT(); - callFrame[dst] = JSValuePtr(temp); + callFrame[dst] = JSValue(temp); vPC += target; NEXT_INSTRUCTION(); } @@ -3361,7 +3657,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe ASSERT(!globalData->exception); int ex = (++vPC)->u.operand; callFrame[ex] = exceptionValue; - exceptionValue = noValue(); + exceptionValue = JSValue(); ++vPC; NEXT_INSTRUCTION(); @@ -3378,7 +3674,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int ex = (++vPC)->u.operand; - exceptionValue = callFrame[ex].jsValue(callFrame); + exceptionValue = callFrame[ex].jsValue(); handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true); if (!handler) { @@ -3396,7 +3692,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe */ int dst = (++vPC)->u.operand; int src = (++vPC)->u.operand; - callFrame[dst] = JSValuePtr(callFrame->codeBlock()->unexpectedConstant(src)); + callFrame[dst] = JSValue(callFrame->codeBlock()->unexpectedConstant(src)); ++vPC; NEXT_INSTRUCTION(); @@ -3414,7 +3710,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int message = (++vPC)->u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); - callFrame[dst] = JSValuePtr(Error::create(callFrame, (ErrorType)type, codeBlock->unexpectedConstant(message).toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL())); + callFrame[dst] = JSValue(Error::create(callFrame, (ErrorType)type, codeBlock->unexpectedConstant(message).toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL())); ++vPC; NEXT_INSTRUCTION(); @@ -3432,7 +3728,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe scopeChain->deref(); } int result = (++vPC)->u.operand; - return callFrame[result].jsValue(callFrame); + return callFrame[result].jsValue(); } DEFINE_OPCODE(op_put_getter) { /* put_getter base(r) property(id) function(r) @@ -3449,11 +3745,11 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int property = (++vPC)->u.operand; int function = (++vPC)->u.operand; - ASSERT(callFrame[base].jsValue(callFrame).isObject()); - JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame)); + ASSERT(callFrame[base].jsValue().isObject()); + JSObject* baseObj = asObject(callFrame[base].jsValue()); Identifier& ident = callFrame->codeBlock()->identifier(property); - ASSERT(callFrame[function].jsValue(callFrame).isObject()); - baseObj->defineGetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame))); + ASSERT(callFrame[function].jsValue().isObject()); + baseObj->defineGetter(callFrame, ident, asObject(callFrame[function].jsValue())); ++vPC; NEXT_INSTRUCTION(); @@ -3473,15 +3769,19 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int property = (++vPC)->u.operand; int function = (++vPC)->u.operand; - ASSERT(callFrame[base].jsValue(callFrame).isObject()); - JSObject* baseObj = asObject(callFrame[base].jsValue(callFrame)); + ASSERT(callFrame[base].jsValue().isObject()); + JSObject* baseObj = asObject(callFrame[base].jsValue()); Identifier& ident = callFrame->codeBlock()->identifier(property); - ASSERT(callFrame[function].jsValue(callFrame).isObject()); - baseObj->defineSetter(callFrame, ident, asObject(callFrame[function].jsValue(callFrame))); + ASSERT(callFrame[function].jsValue().isObject()); + baseObj->defineSetter(callFrame, ident, asObject(callFrame[function].jsValue())); ++vPC; NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_method_check) { + vPC++; + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_jsr) { /* jsr retAddrDst(r) target(offset) @@ -3530,7 +3830,7 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int function = vPC[1].u.operand; if (*enabledProfilerReference) - (*enabledProfilerReference)->willExecute(callFrame, callFrame[function].jsValue(callFrame)); + (*enabledProfilerReference)->willExecute(callFrame, callFrame[function].jsValue()); vPC += 2; NEXT_INSTRUCTION(); @@ -3544,13 +3844,13 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe int function = vPC[1].u.operand; if (*enabledProfilerReference) - (*enabledProfilerReference)->didExecute(callFrame, callFrame[function].jsValue(callFrame)); + (*enabledProfilerReference)->didExecute(callFrame, callFrame[function].jsValue()); vPC += 2; NEXT_INSTRUCTION(); } vm_throw: { - globalData->exception = noValue(); + globalData->exception = JSValue(); if (!tickCount) { // The exceptionValue is a lie! (GCC produces bad code for reasons I // cannot fathom if we don't assign to the exceptionValue before branching) @@ -3569,13 +3869,14 @@ JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registe #if !HAVE(COMPUTED_GOTO) } // iterator loop ends #endif +#endif // USE(INTERPRETER) #undef NEXT_INSTRUCTION #undef DEFINE_OPCODE #undef CHECK_FOR_EXCEPTION #undef CHECK_FOR_TIMEOUT } -JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const +JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const { CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function); if (!functionCallFrame) @@ -3586,7 +3887,12 @@ JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* func ASSERT(codeBlock->codeType() == FunctionCode); SymbolTable& symbolTable = codeBlock->symbolTable(); int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex(); - return functionCallFrame[argumentsIndex].jsValue(callFrame); + if (!functionCallFrame[argumentsIndex].arguments()) { + Arguments* arguments = new (callFrame) Arguments(functionCallFrame); + functionCallFrame->setCalleeArguments(arguments); + functionCallFrame[RegisterFile::ArgumentsRegister] = arguments; + } + return functionCallFrame[argumentsIndex].jsValue(); } Arguments* arguments = functionCallFrame->optionalCalleeArguments(); @@ -3599,7 +3905,7 @@ JSValuePtr Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* func return arguments; } -JSValuePtr Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const +JSValue Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const { CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function); if (!functionCallFrame) @@ -3609,16 +3915,16 @@ JSValuePtr Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* f if (callerFrame->hasHostCallFrameFlag()) return jsNull(); - JSValuePtr caller = callerFrame->callee(); + JSValue caller = callerFrame->callee(); if (!caller) return jsNull(); return caller; } -void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValuePtr& function) const +void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const { - function = noValue(); + function = JSValue(); lineNumber = -1; sourceURL = UString(); @@ -3646,2140 +3952,4 @@ CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunc return 0; } -#ifdef MANUAL_MERGE_REQUIRED -#if ENABLE(JIT) - -#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) - -NEVER_INLINE void Interpreter::tryCTICachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const PutPropertySlot& slot) -{ - // The interpreter checks for recursion here; I do not believe this can occur in CTI. - - if (!baseValue.isCell()) - return; - - // Uncacheable: give up. - if (!slot.isCacheable()) { - ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic)); - return; - } - - JSCell* baseCell = asCell(baseValue); - Structure* structure = baseCell->structure(); - - if (structure->isDictionary()) { - ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic)); - return; - } - - // If baseCell != base, then baseCell must be a proxy for another object. - if (baseCell != slot.base()) { - ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_put_by_id_generic)); - return; - } - - StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress); - - // Cache hit: Specialize instruction and ref Structures. - - // Structure transition, cache transition info - if (slot.type() == PutPropertySlot::NewProperty) { - StructureChain* chain = structure->cachedPrototypeChain(); - if (!chain) { - chain = cachePrototypeChain(callFrame, structure); - if (!chain) { - // This happens if someone has manually inserted null into the prototype chain - stubInfo->opcodeID = op_put_by_id_generic; - return; - } - } - stubInfo->initPutByIdTransition(structure->previousID(), structure, chain); - JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), chain, returnAddress); - return; - } - - stubInfo->initPutByIdReplace(structure); - -#if USE(CTI_REPATCH_PIC) - UNUSED_PARAM(callFrame); - JIT::patchPutByIdReplace(stubInfo, structure, slot.cachedOffset(), returnAddress); -#else - JIT::compilePutByIdReplace(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); -#endif -} - -NEVER_INLINE void Interpreter::tryCTICacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress, JSValuePtr baseValue, const Identifier& propertyName, const PropertySlot& slot) -{ - // FIXME: Write a test that proves we need to check for recursion here just - // like the interpreter does, then add a check for recursion. - - // FIXME: Cache property access for immediates. - if (!baseValue.isCell()) { - ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic)); - return; - } - - if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) { -#if USE(CTI_REPATCH_PIC) - JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress); -#else - ctiPatchCallByReturnAddress(returnAddress, m_ctiArrayLengthTrampoline); -#endif - return; - } - if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) { - // The tradeoff of compiling an patched inline string length access routine does not seem - // to pay off, so we currently only do this for arrays. - ctiPatchCallByReturnAddress(returnAddress, m_ctiStringLengthTrampoline); - return; - } - - // Uncacheable: give up. - if (!slot.isCacheable()) { - ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic)); - return; - } - - JSCell* baseCell = asCell(baseValue); - Structure* structure = baseCell->structure(); - - if (structure->isDictionary()) { - ctiPatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(cti_op_get_by_id_generic)); - return; - } - - // In the interpreter the last structure is trapped here; in CTI we use the - // *_second method to achieve a similar (but not quite the same) effect. - - StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress); - - // Cache hit: Specialize instruction and ref Structures. - - if (slot.slotBase() == baseValue) { - // set this up, so derefStructures can do it's job. - stubInfo->initGetByIdSelf(structure); - -#if USE(CTI_REPATCH_PIC) - JIT::patchGetByIdSelf(stubInfo, structure, slot.cachedOffset(), returnAddress); -#else - JIT::compileGetByIdSelf(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); -#endif - return; - } - - if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { - ASSERT(slot.slotBase().isObject()); - - JSObject* slotBaseObject = asObject(slot.slotBase()); - - // Since we're accessing a prototype in a loop, it's a good bet that it - // should not be treated as a dictionary. - if (slotBaseObject->structure()->isDictionary()) { - RefPtr<Structure> transition = Structure::fromDictionaryTransition(slotBaseObject->structure()); - slotBaseObject->setStructure(transition.release()); - asCell(baseValue)->structure()->setCachedPrototypeChain(0); - } - - stubInfo->initGetByIdProto(structure, slotBaseObject->structure()); - - JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), slot.cachedOffset(), returnAddress); - return; - } - - size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot); - if (!count) { - stubInfo->opcodeID = op_get_by_id_generic; - return; - } - - StructureChain* chain = structure->cachedPrototypeChain(); - if (!chain) - chain = cachePrototypeChain(callFrame, structure); - ASSERT(chain); - - stubInfo->initGetByIdChain(structure, chain); - - JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, chain, count, slot.cachedOffset(), returnAddress); -} - -#endif - -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -#define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args) -#else // JIT_STUB_ARGUMENT_REGISTER or JIT_STUB_ARGUMENT_STACK -#define SETUP_VA_LISTL_ARGS -#endif - -#ifndef NDEBUG - -extern "C" { - -static void jscGeneratedNativeCode() -{ - // When executing a CTI function (which might do an allocation), we hack the return address - // to pretend to be executing this function, to keep stack logging tools from blowing out - // memory. -} - -} - -struct StackHack { - ALWAYS_INLINE StackHack(void** location) - { - returnAddressLocation = location; - savedReturnAddress = *returnAddressLocation; - ctiSetReturnAddress(returnAddressLocation, reinterpret_cast<void*>(jscGeneratedNativeCode)); - } - ALWAYS_INLINE ~StackHack() - { - ctiSetReturnAddress(returnAddressLocation, savedReturnAddress); - } - - void** returnAddressLocation; - void* savedReturnAddress; -}; - -#define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS; StackHack stackHack(&STUB_RETURN_ADDRESS_SLOT) -#define STUB_SET_RETURN_ADDRESS(address) stackHack.savedReturnAddress = address -#define STUB_RETURN_ADDRESS stackHack.savedReturnAddress - -#else - -#define BEGIN_STUB_FUNCTION() SETUP_VA_LISTL_ARGS -#define STUB_SET_RETURN_ADDRESS(address) ctiSetReturnAddress(&STUB_RETURN_ADDRESS_SLOT, address); -#define STUB_RETURN_ADDRESS STUB_RETURN_ADDRESS_SLOT - -#endif - -// The reason this is not inlined is to avoid having to do a PIC branch -// to get the address of the ctiVMThrowTrampoline function. It's also -// good to keep the code size down by leaving as much of the exception -// handling code out of line as possible. -static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot) -{ - ASSERT(globalData->exception); - globalData->exceptionLocation = exceptionLocation; - ctiSetReturnAddress(&returnAddressSlot, reinterpret_cast<void*>(ctiVMThrowTrampoline)); -} - -static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot) -{ - globalData->exception = createStackOverflowError(callFrame); - returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot); -} - -#define VM_THROW_EXCEPTION() \ - do { \ - VM_THROW_EXCEPTION_AT_END(); \ - return 0; \ - } while (0) -#define VM_THROW_EXCEPTION_2() \ - do { \ - VM_THROW_EXCEPTION_AT_END(); \ - RETURN_PAIR(0, 0); \ - } while (0) -#define VM_THROW_EXCEPTION_AT_END() \ - returnToThrowTrampoline(ARG_globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS) - -#define CHECK_FOR_EXCEPTION() \ - do { \ - if (UNLIKELY(ARG_globalData->exception != noValue())) \ - VM_THROW_EXCEPTION(); \ - } while (0) -#define CHECK_FOR_EXCEPTION_AT_END() \ - do { \ - if (UNLIKELY(ARG_globalData->exception != noValue())) \ - VM_THROW_EXCEPTION_AT_END(); \ - } while (0) -#define CHECK_FOR_EXCEPTION_VOID() \ - do { \ - if (UNLIKELY(ARG_globalData->exception != noValue())) { \ - VM_THROW_EXCEPTION_AT_END(); \ - return; \ - } \ - } while (0) - -JSObject* Interpreter::cti_op_convert_this(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr v1 = ARG_src1; - CallFrame* callFrame = ARG_callFrame; - - JSObject* result = v1.toThisObject(callFrame); - CHECK_FOR_EXCEPTION_AT_END(); - return result; -} - -void Interpreter::cti_op_end(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - ScopeChainNode* scopeChain = ARG_callFrame->scopeChain(); - ASSERT(scopeChain->refCount > 1); - scopeChain->deref(); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_add(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr v1 = ARG_src1; - JSValuePtr v2 = ARG_src2; - - double left; - double right = 0.0; - - bool rightIsNumber = v2.getNumber(right); - if (rightIsNumber && v1.getNumber(left)) - return JSValuePtr::encode(jsNumber(ARG_globalData, left + right)); - - CallFrame* callFrame = ARG_callFrame; - - bool leftIsString = v1.isString(); - if (leftIsString && v2.isString()) { - RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep()); - if (UNLIKELY(!value)) { - throwOutOfMemoryError(callFrame); - VM_THROW_EXCEPTION(); - } - - return JSValuePtr::encode(jsString(ARG_globalData, value.release())); - } - - if (rightIsNumber & leftIsString) { - RefPtr<UString::Rep> value = v2.isInt32Fast() ? - concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) : - concatenate(asString(v1)->value().rep(), right); - - if (UNLIKELY(!value)) { - throwOutOfMemoryError(callFrame); - VM_THROW_EXCEPTION(); - } - return JSValuePtr::encode(jsString(ARG_globalData, value.release())); - } - - // All other cases are pretty uncommon - JSValuePtr result = jsAddSlowCase(callFrame, v1, v2); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_pre_inc(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr v = ARG_src1; - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) + 1); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -int Interpreter::cti_timeout_check(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - Interpreter* interpreter = ARG_globalData->interpreter; - - if (interpreter->checkTimeout(ARG_callFrame->dynamicGlobalObject())) { - ARG_globalData->exception = createInterruptedExecutionException(ARG_globalData); - VM_THROW_EXCEPTION_AT_END(); - } - - return interpreter->m_ticksUntilNextTimeoutCheck; -} - -void Interpreter::cti_register_file_check(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - if (LIKELY(ARG_registerFile->grow(ARG_callFrame + ARG_callFrame->codeBlock()->m_numCalleeRegisters))) - return; - - // Rewind to the previous call frame because op_call already optimistically - // moved the call frame forward. - CallFrame* oldCallFrame = ARG_callFrame->callerFrame(); - ARG_setCallFrame(oldCallFrame); - throwStackOverflowError(oldCallFrame, ARG_globalData, oldCallFrame->returnPC(), STUB_RETURN_ADDRESS); -} - -int Interpreter::cti_op_loop_if_less(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - CallFrame* callFrame = ARG_callFrame; - - bool result = jsLess(callFrame, src1, src2); - CHECK_FOR_EXCEPTION_AT_END(); - return result; -} - -int Interpreter::cti_op_loop_if_lesseq(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - CallFrame* callFrame = ARG_callFrame; - - bool result = jsLessEq(callFrame, src1, src2); - CHECK_FOR_EXCEPTION_AT_END(); - return result; -} - -JSObject* Interpreter::cti_op_new_object(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return constructEmptyObject(ARG_callFrame); -} - -void Interpreter::cti_op_put_by_id_generic(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - PutPropertySlot slot; - ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot); - CHECK_FOR_EXCEPTION_AT_END(); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_generic(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Identifier& ident = *ARG_id2; - - JSValuePtr baseValue = ARG_src1; - PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(callFrame, ident, slot); - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) - -void Interpreter::cti_op_put_by_id(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Identifier& ident = *ARG_id2; - - PutPropertySlot slot; - ARG_src1.put(callFrame, ident, ARG_src3, slot); - - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_id_second)); - - CHECK_FOR_EXCEPTION_AT_END(); -} - -void Interpreter::cti_op_put_by_id_second(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - PutPropertySlot slot; - ARG_src1.put(ARG_callFrame, *ARG_id2, ARG_src3, slot); - ARG_globalData->interpreter->tryCTICachePutByID(ARG_callFrame, ARG_callFrame->codeBlock(), STUB_RETURN_ADDRESS, ARG_src1, slot); - CHECK_FOR_EXCEPTION_AT_END(); -} - -void Interpreter::cti_op_put_by_id_fail(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Identifier& ident = *ARG_id2; - - PutPropertySlot slot; - ARG_src1.put(callFrame, ident, ARG_src3, slot); - - CHECK_FOR_EXCEPTION_AT_END(); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Identifier& ident = *ARG_id2; - - JSValuePtr baseValue = ARG_src1; - PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(callFrame, ident, slot); - - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_second)); - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_second(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Identifier& ident = *ARG_id2; - - JSValuePtr baseValue = ARG_src1; - PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(callFrame, ident, slot); - - ARG_globalData->interpreter->tryCTICacheGetByID(callFrame, callFrame->codeBlock(), STUB_RETURN_ADDRESS, baseValue, ident, slot); - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_self_fail(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Identifier& ident = *ARG_id2; - - JSValuePtr baseValue = ARG_src1; - PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(callFrame, ident, slot); - - CHECK_FOR_EXCEPTION(); - - if (baseValue.isCell() - && slot.isCacheable() - && !asCell(baseValue)->structure()->isDictionary() - && slot.slotBase() == baseValue) { - - CodeBlock* codeBlock = callFrame->codeBlock(); - StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); - - ASSERT(slot.slotBase().isObject()); - - PolymorphicAccessStructureList* polymorphicStructureList; - int listIndex = 1; - - if (stubInfo->opcodeID == op_get_by_id_self) { - ASSERT(!stubInfo->stubRoutine); - polymorphicStructureList = new PolymorphicAccessStructureList(0, stubInfo->u.getByIdSelf.baseObjectStructure); - stubInfo->initGetByIdSelfList(polymorphicStructureList, 2); - } else { - polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList; - listIndex = stubInfo->u.getByIdSelfList.listSize; - stubInfo->u.getByIdSelfList.listSize++; - } - - JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset()); - - if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic)); - } else { - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic)); - } - return JSValuePtr::encode(result); -} - -static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex) -{ - PolymorphicAccessStructureList* prototypeStructureList = 0; - listIndex = 1; - - switch (stubInfo->opcodeID) { - case op_get_by_id_proto: - prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure); - stubInfo->stubRoutine = 0; - stubInfo->initGetByIdProtoList(prototypeStructureList, 2); - break; - case op_get_by_id_chain: - prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain); - stubInfo->stubRoutine = 0; - stubInfo->initGetByIdProtoList(prototypeStructureList, 2); - break; - case op_get_by_id_proto_list: - prototypeStructureList = stubInfo->u.getByIdProtoList.structureList; - listIndex = stubInfo->u.getByIdProtoList.listSize; - stubInfo->u.getByIdProtoList.listSize++; - break; - default: - ASSERT_NOT_REACHED(); - } - - ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE); - return prototypeStructureList; -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr baseValue = ARG_src1; - PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(callFrame, *ARG_id2, slot); - - CHECK_FOR_EXCEPTION(); - - if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) { - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail)); - return JSValuePtr::encode(result); - } - - Structure* structure = asCell(baseValue)->structure(); - CodeBlock* codeBlock = callFrame->codeBlock(); - StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); - - ASSERT(slot.slotBase().isObject()); - JSObject* slotBaseObject = asObject(slot.slotBase()); - - if (slot.slotBase() == baseValue) - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail)); - else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) { - // Since we're accessing a prototype in a loop, it's a good bet that it - // should not be treated as a dictionary. - if (slotBaseObject->structure()->isDictionary()) { - RefPtr<Structure> transition = Structure::fromDictionaryTransition(slotBaseObject->structure()); - slotBaseObject->setStructure(transition.release()); - asCell(baseValue)->structure()->setCachedPrototypeChain(0); - } - - int listIndex; - PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); - - JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset()); - - if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full)); - } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) { - StructureChain* chain = structure->cachedPrototypeChain(); - if (!chain) - chain = cachePrototypeChain(callFrame, structure); - ASSERT(chain); - - int listIndex; - PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); - - JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, chain, count, slot.cachedOffset()); - - if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full)); - } else - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_fail)); - - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_list_full(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr baseValue = ARG_src1; - PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot); - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_proto_fail(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr baseValue = ARG_src1; - PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot); - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_array_fail(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr baseValue = ARG_src1; - PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot); - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_id_string_fail(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr baseValue = ARG_src1; - PropertySlot slot(baseValue); - JSValuePtr result = baseValue.get(ARG_callFrame, *ARG_id2, slot); - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -#endif - -JSValueEncodedAsPointer* Interpreter::cti_op_instanceof(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr value = ARG_src1; - JSValuePtr baseVal = ARG_src2; - JSValuePtr proto = ARG_src3; - - // at least one of these checks must have failed to get to the slow case - ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell() - || !value.isObject() || !baseVal.isObject() || !proto.isObject() - || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance); - - if (!baseVal.isObject()) { - CallFrame* callFrame = ARG_callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - ARG_globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock); - VM_THROW_EXCEPTION(); - } - - if (!asObject(baseVal)->structure()->typeInfo().implementsHasInstance()) - return JSValuePtr::encode(jsBoolean(false)); - - if (!proto.isObject()) { - throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property."); - VM_THROW_EXCEPTION(); - } - - if (!value.isObject()) - return JSValuePtr::encode(jsBoolean(false)); - - JSValuePtr result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto)); - CHECK_FOR_EXCEPTION_AT_END(); - - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_del_by_id(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - - JSObject* baseObj = ARG_src1.toObject(callFrame); - - JSValuePtr result = jsBoolean(baseObj->deleteProperty(callFrame, *ARG_id2)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_mul(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - double left; - double right; - if (src1.getNumber(left) && src2.getNumber(right)) - return JSValuePtr::encode(jsNumber(ARG_globalData, left * right)); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSObject* Interpreter::cti_op_new_func(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return ARG_func1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain()); -} - -void* Interpreter::cti_op_call_JSFunction(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - -#ifndef NDEBUG - CallData callData; - ASSERT(ARG_src1.getCallData(callData) == CallTypeJS); -#endif - - ScopeChainNode* callDataScopeChain = asFunction(ARG_src1)->m_scopeChain.node(); - CodeBlock* newCodeBlock = &asFunction(ARG_src1)->body()->bytecode(callDataScopeChain); - - if (!newCodeBlock->jitCode()) - JIT::compile(ARG_globalData, newCodeBlock); - - return newCodeBlock; -} - -VoidPtrPair Interpreter::cti_op_call_arityCheck(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - CodeBlock* newCodeBlock = ARG_codeBlock4; - int argCount = ARG_int3; - - ASSERT(argCount != newCodeBlock->m_numParameters); - - CallFrame* oldCallFrame = callFrame->callerFrame(); - - if (argCount > newCodeBlock->m_numParameters) { - size_t numParameters = newCodeBlock->m_numParameters; - Register* r = callFrame->registers() + numParameters; - - Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount; - for (size_t i = 0; i < numParameters; ++i) - argv[i + argCount] = argv[i]; - - callFrame = CallFrame::create(r); - callFrame->setCallerFrame(oldCallFrame); - } else { - size_t omittedArgCount = newCodeBlock->m_numParameters - argCount; - Register* r = callFrame->registers() + omittedArgCount; - Register* newEnd = r + newCodeBlock->m_numCalleeRegisters; - if (!ARG_registerFile->grow(newEnd)) { - // Rewind to the previous call frame because op_call already optimistically - // moved the call frame forward. - ARG_setCallFrame(oldCallFrame); - throwStackOverflowError(oldCallFrame, ARG_globalData, ARG_returnAddress2, STUB_RETURN_ADDRESS); - RETURN_PAIR(0, 0); - } - - Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount; - for (size_t i = 0; i < omittedArgCount; ++i) - argv[i] = jsUndefined(); - - callFrame = CallFrame::create(r); - callFrame->setCallerFrame(oldCallFrame); - } - - RETURN_PAIR(newCodeBlock, callFrame); -} - -void* Interpreter::cti_vm_dontLazyLinkCall(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSFunction* callee = asFunction(ARG_src1); - CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node()); - if (!codeBlock->jitCode()) - JIT::compile(ARG_globalData, codeBlock); - - ctiPatchCallByReturnAddress(ARG_returnAddress2, ARG_globalData->interpreter->m_ctiVirtualCallLink); - - return codeBlock->jitCode(); -} - -void* Interpreter::cti_vm_lazyLinkCall(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSFunction* callee = asFunction(ARG_src1); - CodeBlock* codeBlock = &callee->body()->bytecode(callee->m_scopeChain.node()); - if (!codeBlock->jitCode()) - JIT::compile(ARG_globalData, codeBlock); - - CallLinkInfo* callLinkInfo = &ARG_callFrame->callerFrame()->codeBlock()->getCallLinkInfo(ARG_returnAddress2); - JIT::linkCall(callee, codeBlock, codeBlock->jitCode(), callLinkInfo, ARG_int3); - - return codeBlock->jitCode(); -} - -JSObject* Interpreter::cti_op_push_activation(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSActivation* activation = new (ARG_globalData) JSActivation(ARG_callFrame, static_cast<FunctionBodyNode*>(ARG_callFrame->codeBlock()->ownerNode())); - ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->copy()->push(activation)); - return activation; -} - -JSValueEncodedAsPointer* Interpreter::cti_op_call_NotJSFunction(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr funcVal = ARG_src1; - - CallData callData; - CallType callType = funcVal.getCallData(callData); - - ASSERT(callType != CallTypeJS); - - if (callType == CallTypeHost) { - int registerOffset = ARG_int2; - int argCount = ARG_int3; - CallFrame* previousCallFrame = ARG_callFrame; - CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset); - - callFrame->init(0, static_cast<Instruction*>(STUB_RETURN_ADDRESS), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0); - ARG_setCallFrame(callFrame); - - Register* argv = ARG_callFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; - ArgList argList(argv + 1, argCount - 1); - - JSValuePtr returnValue; - { - SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); - - // FIXME: All host methods should be calling toThisObject, but this is not presently the case. - JSValuePtr thisValue = argv[0].jsValue(callFrame); - if (thisValue == jsNull()) - thisValue = callFrame->globalThisValue(); - - returnValue = callData.native.function(callFrame, asObject(funcVal), thisValue, argList); - } - ARG_setCallFrame(previousCallFrame); - CHECK_FOR_EXCEPTION(); - - return JSValuePtr::encode(returnValue); - } - - ASSERT(callType == CallTypeNone); - - CallFrame* callFrame = ARG_callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - ARG_globalData->exception = createNotAFunctionError(ARG_callFrame, funcVal, vPCIndex, codeBlock); - VM_THROW_EXCEPTION(); -} - -void Interpreter::cti_op_create_arguments(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame); - ARG_callFrame->setCalleeArguments(arguments); - ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments; -} - -void Interpreter::cti_op_create_arguments_no_params(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - Arguments* arguments = new (ARG_globalData) Arguments(ARG_callFrame, Arguments::NoParameters); - ARG_callFrame->setCalleeArguments(arguments); - ARG_callFrame[RegisterFile::ArgumentsRegister] = arguments; -} - -void Interpreter::cti_op_tear_off_activation(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain()); - asActivation(ARG_src1)->copyRegisters(ARG_callFrame->optionalCalleeArguments()); -} - -void Interpreter::cti_op_tear_off_arguments(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - ASSERT(ARG_callFrame->codeBlock()->usesArguments() && !ARG_callFrame->codeBlock()->needsFullScopeChain()); - ARG_callFrame->optionalCalleeArguments()->copyRegisters(); -} - -void Interpreter::cti_op_profile_will_call(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - ASSERT(*ARG_profilerReference); - (*ARG_profilerReference)->willExecute(ARG_callFrame, ARG_src1); -} - -void Interpreter::cti_op_profile_did_call(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - ASSERT(*ARG_profilerReference); - (*ARG_profilerReference)->didExecute(ARG_callFrame, ARG_src1); -} - -void Interpreter::cti_op_ret_scopeChain(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - ASSERT(ARG_callFrame->codeBlock()->needsFullScopeChain()); - ARG_callFrame->scopeChain()->deref(); -} - -JSObject* Interpreter::cti_op_new_array(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - ArgList argList(&ARG_callFrame->registers()[ARG_int1], ARG_int2); - return constructArray(ARG_callFrame, argList); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_resolve(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - ScopeChainNode* scopeChain = callFrame->scopeChain(); - - ScopeChainIterator iter = scopeChain->begin(); - ScopeChainIterator end = scopeChain->end(); - ASSERT(iter != end); - - Identifier& ident = *ARG_id1; - do { - JSObject* o = *iter; - PropertySlot slot(o); - if (o->getPropertySlot(callFrame, ident, slot)) { - JSValuePtr result = slot.getValue(callFrame, ident); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); - } - } while (++iter != end); - - CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); - VM_THROW_EXCEPTION(); -} - -JSObject* Interpreter::cti_op_construct_JSConstruct(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - -#ifndef NDEBUG - ConstructData constructData; - ASSERT(asFunction(ARG_src1)->getConstructData(constructData) == ConstructTypeJS); -#endif - - Structure* structure; - if (ARG_src4.isObject()) - structure = asObject(ARG_src4)->inheritorID(); - else - structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure(); - return new (ARG_globalData) JSObject(structure); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_construct_NotJSConstruct(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr constrVal = ARG_src1; - int argCount = ARG_int3; - int thisRegister = ARG_int5; - - ConstructData constructData; - ConstructType constructType = constrVal.getConstructData(constructData); - - if (constructType == ConstructTypeHost) { - ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1); - - JSValuePtr returnValue; - { - SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); - returnValue = constructData.native.function(callFrame, asObject(constrVal), argList); - } - CHECK_FOR_EXCEPTION(); - - return JSValuePtr::encode(returnValue); - } - - ASSERT(constructType == ConstructTypeNone); - - CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock); - VM_THROW_EXCEPTION(); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Interpreter* interpreter = ARG_globalData->interpreter; - - JSValuePtr baseValue = ARG_src1; - JSValuePtr subscript = ARG_src2; - - JSValuePtr result; - - if (LIKELY(subscript.isUInt32Fast())) { - uint32_t i = subscript.getUInt32Fast(); - if (interpreter->isJSArray(baseValue)) { - JSArray* jsArray = asArray(baseValue); - if (jsArray->canGetIndex(i)) - result = jsArray->getIndex(i); - else - result = jsArray->JSArray::get(callFrame, i); - } else if (interpreter->isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) - result = asString(baseValue)->getIndex(ARG_globalData, i); - else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { - // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val_byte_array)); - return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i)); - } else - result = baseValue.get(callFrame, i); - } else { - Identifier property(callFrame, subscript.toString(callFrame)); - result = baseValue.get(callFrame, property); - } - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_get_by_val_byte_array(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Interpreter* interpreter = ARG_globalData->interpreter; - - JSValuePtr baseValue = ARG_src1; - JSValuePtr subscript = ARG_src2; - - JSValuePtr result; - - if (LIKELY(subscript.isUInt32Fast())) { - uint32_t i = subscript.getUInt32Fast(); - if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { - // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. - return JSValuePtr::encode(asByteArray(baseValue)->getIndex(callFrame, i)); - } - - result = baseValue.get(callFrame, i); - if (!interpreter->isJSByteArray(baseValue)) - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_val)); - } else { - Identifier property(callFrame, subscript.toString(callFrame)); - result = baseValue.get(callFrame, property); - } - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -VoidPtrPair Interpreter::cti_op_resolve_func(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - ScopeChainNode* scopeChain = callFrame->scopeChain(); - - ScopeChainIterator iter = scopeChain->begin(); - ScopeChainIterator end = scopeChain->end(); - - // FIXME: add scopeDepthIsZero optimization - - ASSERT(iter != end); - - Identifier& ident = *ARG_id1; - JSObject* base; - do { - base = *iter; - PropertySlot slot(base); - if (base->getPropertySlot(callFrame, ident, slot)) { - // ECMA 11.2.3 says that if we hit an activation the this value should be null. - // However, section 10.2.3 says that in the case where the value provided - // by the caller is null, the global object should be used. It also says - // that the section does not apply to internal functions, but for simplicity - // of implementation we use the global object anyway here. This guarantees - // that in host objects you always get a valid object for this. - // We also handle wrapper substitution for the global object at the same time. - JSObject* thisObj = base->toThisObject(callFrame); - JSValuePtr result = slot.getValue(callFrame, ident); - CHECK_FOR_EXCEPTION_AT_END(); - - RETURN_PAIR(thisObj, JSValuePtr::encode(result)); - } - ++iter; - } while (iter != end); - - CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); - VM_THROW_EXCEPTION_2(); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_sub(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - double left; - double right; - if (src1.getNumber(left) && src2.getNumber(right)) - return JSValuePtr::encode(jsNumber(ARG_globalData, left - right)); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -void Interpreter::cti_op_put_by_val(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Interpreter* interpreter = ARG_globalData->interpreter; - - JSValuePtr baseValue = ARG_src1; - JSValuePtr subscript = ARG_src2; - JSValuePtr value = ARG_src3; - - if (LIKELY(subscript.isUInt32Fast())) { - uint32_t i = subscript.getUInt32Fast(); - if (interpreter->isJSArray(baseValue)) { - JSArray* jsArray = asArray(baseValue); - if (jsArray->canSetIndex(i)) - jsArray->setIndex(i, value); - else - jsArray->JSArray::put(callFrame, i, value); - } else if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { - JSByteArray* jsByteArray = asByteArray(baseValue); - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_val_byte_array)); - // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. - if (value.isInt32Fast()) { - jsByteArray->setIndex(i, value.getInt32Fast()); - return; - } else { - double dValue = 0; - if (value.getNumber(dValue)) { - jsByteArray->setIndex(i, dValue); - return; - } - } - - baseValue.put(callFrame, i, value); - } else - baseValue.put(callFrame, i, value); - } else { - Identifier property(callFrame, subscript.toString(callFrame)); - if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception. - PutPropertySlot slot; - baseValue.put(callFrame, property, value, slot); - } - } - - CHECK_FOR_EXCEPTION_AT_END(); -} - -void Interpreter::cti_op_put_by_val_array(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr baseValue = ARG_src1; - int i = ARG_int2; - JSValuePtr value = ARG_src3; - - ASSERT(ARG_globalData->interpreter->isJSArray(baseValue)); - - if (LIKELY(i >= 0)) - asArray(baseValue)->JSArray::put(callFrame, i, value); - else { - // This should work since we're re-boxing an immediate unboxed in JIT code. - ASSERT(JSValuePtr::makeInt32Fast(i)); - Identifier property(callFrame, JSValuePtr::makeInt32Fast(i).toString(callFrame)); - // FIXME: can toString throw an exception here? - if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception. - PutPropertySlot slot; - baseValue.put(callFrame, property, value, slot); - } - } - - CHECK_FOR_EXCEPTION_AT_END(); -} - -void Interpreter::cti_op_put_by_val_byte_array(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - Interpreter* interpreter = ARG_globalData->interpreter; - - JSValuePtr baseValue = ARG_src1; - JSValuePtr subscript = ARG_src2; - JSValuePtr value = ARG_src3; - - if (LIKELY(subscript.isUInt32Fast())) { - uint32_t i = subscript.getUInt32Fast(); - if (interpreter->isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { - JSByteArray* jsByteArray = asByteArray(baseValue); - - // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. - if (value.isInt32Fast()) { - jsByteArray->setIndex(i, value.getInt32Fast()); - return; - } else { - double dValue = 0; - if (value.getNumber(dValue)) { - jsByteArray->setIndex(i, dValue); - return; - } - } - } - - if (!interpreter->isJSByteArray(baseValue)) - ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_put_by_val)); - baseValue.put(callFrame, i, value); - } else { - Identifier property(callFrame, subscript.toString(callFrame)); - if (!ARG_globalData->exception) { // Don't put to an object if toString threw an exception. - PutPropertySlot slot; - baseValue.put(callFrame, property, value, slot); - } - } - - CHECK_FOR_EXCEPTION_AT_END(); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_lesseq(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsBoolean(jsLessEq(callFrame, ARG_src1, ARG_src2)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -int Interpreter::cti_op_loop_if_true(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - - CallFrame* callFrame = ARG_callFrame; - - bool result = src1.toBoolean(callFrame); - CHECK_FOR_EXCEPTION_AT_END(); - return result; -} - -JSValueEncodedAsPointer* Interpreter::cti_op_negate(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src = ARG_src1; - - double v; - if (src.getNumber(v)) - return JSValuePtr::encode(jsNumber(ARG_globalData, -v)); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, -src.toNumber(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_resolve_base(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return JSValuePtr::encode(inlineResolveBase(ARG_callFrame, *ARG_id1, ARG_callFrame->scopeChain())); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_resolve_skip(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - ScopeChainNode* scopeChain = callFrame->scopeChain(); - - int skip = ARG_int2; - - ScopeChainIterator iter = scopeChain->begin(); - ScopeChainIterator end = scopeChain->end(); - ASSERT(iter != end); - while (skip--) { - ++iter; - ASSERT(iter != end); - } - Identifier& ident = *ARG_id1; - do { - JSObject* o = *iter; - PropertySlot slot(o); - if (o->getPropertySlot(callFrame, ident, slot)) { - JSValuePtr result = slot.getValue(callFrame, ident); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); - } - } while (++iter != end); - - CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); - VM_THROW_EXCEPTION(); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_resolve_global(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - JSGlobalObject* globalObject = asGlobalObject(ARG_src1); - Identifier& ident = *ARG_id2; - unsigned globalResolveInfoIndex = ARG_int3; - ASSERT(globalObject->isGlobalObject()); - - PropertySlot slot(globalObject); - if (globalObject->getPropertySlot(callFrame, ident, slot)) { - JSValuePtr result = slot.getValue(callFrame, ident); - if (slot.isCacheable() && !globalObject->structure()->isDictionary()) { - GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex); - if (globalResolveInfo.structure) - globalResolveInfo.structure->deref(); - globalObject->structure()->ref(); - globalResolveInfo.structure = globalObject->structure(); - globalResolveInfo.offset = slot.cachedOffset(); - return JSValuePtr::encode(result); - } - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); - } - - unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock()); - VM_THROW_EXCEPTION(); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_div(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - double left; - double right; - if (src1.getNumber(left) && src2.getNumber(right)) - return JSValuePtr::encode(jsNumber(ARG_globalData, left / right)); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_pre_dec(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr v = ARG_src1; - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, v.toNumber(callFrame) - 1); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -int Interpreter::cti_op_jless(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - CallFrame* callFrame = ARG_callFrame; - - bool result = jsLess(callFrame, src1, src2); - CHECK_FOR_EXCEPTION_AT_END(); - return result; -} - -JSValueEncodedAsPointer* Interpreter::cti_op_not(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src = ARG_src1; - - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr result = jsBoolean(!src.toBoolean(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -int Interpreter::cti_op_jtrue(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - - CallFrame* callFrame = ARG_callFrame; - - bool result = src1.toBoolean(callFrame); - CHECK_FOR_EXCEPTION_AT_END(); - return result; -} - -VoidPtrPair Interpreter::cti_op_post_inc(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr v = ARG_src1; - - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr number = v.toJSNumber(callFrame); - CHECK_FOR_EXCEPTION_AT_END(); - - RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() + 1))); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_eq(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - CallFrame* callFrame = ARG_callFrame; - - ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2)); - JSValuePtr result = jsBoolean(JSValuePtr::equalSlowCaseInline(callFrame, src1, src2)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_lshift(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr val = ARG_src1; - JSValuePtr shift = ARG_src2; - - int32_t left; - uint32_t right; - if (JSValuePtr::areBothInt32Fast(val, shift)) - return JSValuePtr::encode(jsNumber(ARG_globalData, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f))); - if (val.numberToInt32(left) && shift.numberToUInt32(right)) - return JSValuePtr::encode(jsNumber(ARG_globalData, left << (right & 0x1f))); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_bitand(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - int32_t left; - int32_t right; - if (src1.numberToInt32(left) && src2.numberToInt32(right)) - return JSValuePtr::encode(jsNumber(ARG_globalData, left & right)); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_rshift(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr val = ARG_src1; - JSValuePtr shift = ARG_src2; - - int32_t left; - uint32_t right; - if (JSFastMath::canDoFastRshift(val, shift)) - return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift)); - if (val.numberToInt32(left) && shift.numberToUInt32(right)) - return JSValuePtr::encode(jsNumber(ARG_globalData, left >> (right & 0x1f))); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_bitnot(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src = ARG_src1; - - int value; - if (src.numberToInt32(value)) - return JSValuePtr::encode(jsNumber(ARG_globalData, ~value)); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsNumber(ARG_globalData, ~src.toInt32(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -VoidPtrPair Interpreter::cti_op_resolve_with_base(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - ScopeChainNode* scopeChain = callFrame->scopeChain(); - - ScopeChainIterator iter = scopeChain->begin(); - ScopeChainIterator end = scopeChain->end(); - - // FIXME: add scopeDepthIsZero optimization - - ASSERT(iter != end); - - Identifier& ident = *ARG_id1; - JSObject* base; - do { - base = *iter; - PropertySlot slot(base); - if (base->getPropertySlot(callFrame, ident, slot)) { - JSValuePtr result = slot.getValue(callFrame, ident); - CHECK_FOR_EXCEPTION_AT_END(); - - RETURN_PAIR(base, JSValuePtr::encode(result)); - } - ++iter; - } while (iter != end); - - CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - ARG_globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); - VM_THROW_EXCEPTION_2(); -} - -JSObject* Interpreter::cti_op_new_func_exp(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return ARG_funcexp1->makeFunction(ARG_callFrame, ARG_callFrame->scopeChain()); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_mod(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr dividendValue = ARG_src1; - JSValuePtr divisorValue = ARG_src2; - - CallFrame* callFrame = ARG_callFrame; - double d = dividendValue.toNumber(callFrame); - JSValuePtr result = jsNumber(ARG_globalData, fmod(d, divisorValue.toNumber(callFrame))); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_less(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsBoolean(jsLess(callFrame, ARG_src1, ARG_src2)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_neq(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - ASSERT(!JSValuePtr::areBothInt32Fast(src1, src2)); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr result = jsBoolean(!JSValuePtr::equalSlowCaseInline(callFrame, src1, src2)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -VoidPtrPair Interpreter::cti_op_post_dec(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr v = ARG_src1; - - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr number = v.toJSNumber(callFrame); - CHECK_FOR_EXCEPTION_AT_END(); - - RETURN_PAIR(JSValuePtr::encode(number), JSValuePtr::encode(jsNumber(ARG_globalData, number.uncheckedGetNumber() - 1))); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_urshift(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr val = ARG_src1; - JSValuePtr shift = ARG_src2; - - CallFrame* callFrame = ARG_callFrame; - - if (JSFastMath::canDoFastUrshift(val, shift)) - return JSValuePtr::encode(JSFastMath::rightShiftImmediateNumbers(val, shift)); - else { - JSValuePtr result = jsNumber(ARG_globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); - } -} - -JSValueEncodedAsPointer* Interpreter::cti_op_bitxor(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSObject* Interpreter::cti_op_new_regexp(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return new (ARG_globalData) RegExpObject(ARG_callFrame->lexicalGlobalObject()->regExpStructure(), ARG_regexp1); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_bitor(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr result = jsNumber(ARG_globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame)); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_call_eval(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - RegisterFile* registerFile = ARG_registerFile; - - Interpreter* interpreter = ARG_globalData->interpreter; - - JSValuePtr funcVal = ARG_src1; - int registerOffset = ARG_int2; - int argCount = ARG_int3; - - Register* newCallFrame = callFrame->registers() + registerOffset; - Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; - JSValuePtr thisValue = argv[0].jsValue(callFrame); - JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); - - if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { - JSValuePtr exceptionValue = noValue(); - JSValuePtr result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); - if (UNLIKELY(exceptionValue != noValue())) { - ARG_globalData->exception = exceptionValue; - VM_THROW_EXCEPTION_AT_END(); - } - return JSValuePtr::encode(result); - } - - return JSValuePtr::encode(jsImpossibleValue()); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_throw(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - - JSValuePtr exceptionValue = ARG_src1; - ASSERT(exceptionValue); - - HandlerInfo* handler = ARG_globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true); - - if (!handler) { - *ARG_exception = exceptionValue; - return JSValuePtr::encode(jsNull()); - } - - ARG_setCallFrame(callFrame); - void* catchRoutine = handler->nativeCode; - ASSERT(catchRoutine); - STUB_SET_RETURN_ADDRESS(catchRoutine); - return JSValuePtr::encode(exceptionValue); -} - -JSPropertyNameIterator* Interpreter::cti_op_get_pnames(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return JSPropertyNameIterator::create(ARG_callFrame, ARG_src1); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_next_pname(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSPropertyNameIterator* it = ARG_pni1; - JSValuePtr temp = it->next(ARG_callFrame); - if (!temp) - it->invalidate(); - return JSValuePtr::encode(temp); -} - -JSObject* Interpreter::cti_op_push_scope(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSObject* o = ARG_src1.toObject(ARG_callFrame); - CHECK_FOR_EXCEPTION(); - ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->push(o)); - return o; -} - -void Interpreter::cti_op_pop_scope(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->pop()); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_typeof(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return JSValuePtr::encode(jsTypeStringForValue(ARG_callFrame, ARG_src1)); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_is_undefined(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr v = ARG_src1; - return JSValuePtr::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined())); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_is_boolean(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return JSValuePtr::encode(jsBoolean(ARG_src1.isBoolean())); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_is_number(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return JSValuePtr::encode(jsBoolean(ARG_src1.isNumber())); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_is_string(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return JSValuePtr::encode(jsBoolean(ARG_globalData->interpreter->isJSString(ARG_src1))); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_is_object(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return JSValuePtr::encode(jsBoolean(jsIsObjectType(ARG_src1))); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_is_function(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - return JSValuePtr::encode(jsBoolean(jsIsFunctionType(ARG_src1))); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_stricteq(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - return JSValuePtr::encode(jsBoolean(JSValuePtr::strictEqual(src1, src2))); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_nstricteq(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src1 = ARG_src1; - JSValuePtr src2 = ARG_src2; - - return JSValuePtr::encode(jsBoolean(!JSValuePtr::strictEqual(src1, src2))); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_to_jsnumber(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr src = ARG_src1; - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr result = src.toJSNumber(callFrame); - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -JSValueEncodedAsPointer* Interpreter::cti_op_in(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - JSValuePtr baseVal = ARG_src2; - - if (!baseVal.isObject()) { - CallFrame* callFrame = ARG_callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); - ARG_globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock); - VM_THROW_EXCEPTION(); - } - - JSValuePtr propName = ARG_src1; - JSObject* baseObj = asObject(baseVal); - - uint32_t i; - if (propName.getUInt32(i)) - return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, i))); - - Identifier property(callFrame, propName.toString(callFrame)); - CHECK_FOR_EXCEPTION(); - return JSValuePtr::encode(jsBoolean(baseObj->hasProperty(callFrame, property))); -} - -JSObject* Interpreter::cti_op_push_new_scope(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSObject* scope = new (ARG_globalData) JSStaticScopeObject(ARG_callFrame, *ARG_id1, ARG_src2, DontDelete); - - CallFrame* callFrame = ARG_callFrame; - callFrame->setScopeChain(callFrame->scopeChain()->push(scope)); - return scope; -} - -void Interpreter::cti_op_jmp_scopes(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - unsigned count = ARG_int1; - CallFrame* callFrame = ARG_callFrame; - - ScopeChainNode* tmp = callFrame->scopeChain(); - while (count--) - tmp = tmp->pop(); - callFrame->setScopeChain(tmp); -} - -void Interpreter::cti_op_put_by_index(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - unsigned property = ARG_int2; - - ARG_src1.put(callFrame, property, ARG_src3); -} - -void* Interpreter::cti_op_switch_imm(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr scrutinee = ARG_src1; - unsigned tableIndex = ARG_int2; - CallFrame* callFrame = ARG_callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - - if (scrutinee.isInt32Fast()) - return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.getInt32Fast()); - else { - int32_t value; - if (scrutinee.numberToInt32(value)) - return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(value); - else - return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault; - } -} - -void* Interpreter::cti_op_switch_char(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr scrutinee = ARG_src1; - unsigned tableIndex = ARG_int2; - CallFrame* callFrame = ARG_callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - - void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault; - - if (scrutinee.isString()) { - UString::Rep* value = asString(scrutinee)->value().rep(); - if (value->size() == 1) - result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]); - } - - return result; -} - -void* Interpreter::cti_op_switch_string(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - JSValuePtr scrutinee = ARG_src1; - unsigned tableIndex = ARG_int2; - CallFrame* callFrame = ARG_callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - - void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault; - - if (scrutinee.isString()) { - UString::Rep* value = asString(scrutinee)->value().rep(); - result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value); - } - - return result; -} - -JSValueEncodedAsPointer* Interpreter::cti_op_del_by_val(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - - JSValuePtr baseValue = ARG_src1; - JSObject* baseObj = baseValue.toObject(callFrame); // may throw - - JSValuePtr subscript = ARG_src2; - JSValuePtr result; - uint32_t i; - if (subscript.getUInt32(i)) - result = jsBoolean(baseObj->deleteProperty(callFrame, i)); - else { - CHECK_FOR_EXCEPTION(); - Identifier property(callFrame, subscript.toString(callFrame)); - CHECK_FOR_EXCEPTION(); - result = jsBoolean(baseObj->deleteProperty(callFrame, property)); - } - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValuePtr::encode(result); -} - -void Interpreter::cti_op_put_getter(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - - ASSERT(ARG_src1.isObject()); - JSObject* baseObj = asObject(ARG_src1); - ASSERT(ARG_src3.isObject()); - baseObj->defineGetter(callFrame, *ARG_id2, asObject(ARG_src3)); -} - -void Interpreter::cti_op_put_setter(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - - ASSERT(ARG_src1.isObject()); - JSObject* baseObj = asObject(ARG_src1); - ASSERT(ARG_src3.isObject()); - baseObj->defineSetter(callFrame, *ARG_id2, asObject(ARG_src3)); -} - -JSObject* Interpreter::cti_op_new_error(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - unsigned type = ARG_int1; - JSValuePtr message = ARG_src2; - unsigned bytecodeOffset = ARG_int3; - - unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset); - return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); -} - -void Interpreter::cti_op_debug(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - - int debugHookID = ARG_int1; - int firstLine = ARG_int2; - int lastLine = ARG_int3; - - ARG_globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); -} - -JSValueEncodedAsPointer* Interpreter::cti_vm_throw(STUB_ARGS) -{ - BEGIN_STUB_FUNCTION(); - - CallFrame* callFrame = ARG_callFrame; - CodeBlock* codeBlock = callFrame->codeBlock(); - JSGlobalData* globalData = ARG_globalData; - - unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, globalData->exceptionLocation); - - JSValuePtr exceptionValue = globalData->exception; - ASSERT(exceptionValue); - globalData->exception = noValue(); - - HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false); - - if (!handler) { - *ARG_exception = exceptionValue; - return JSValuePtr::encode(jsNull()); - } - - ARG_setCallFrame(callFrame); - void* catchRoutine = handler->nativeCode; - ASSERT(catchRoutine); - STUB_SET_RETURN_ADDRESS(catchRoutine); - return JSValuePtr::encode(exceptionValue); -} - -#undef STUB_RETURN_ADDRESS -#undef STUB_SET_RETURN_ADDRESS -#undef BEGIN_STUB_FUNCTION -#undef CHECK_FOR_EXCEPTION -#undef CHECK_FOR_EXCEPTION_AT_END -#undef CHECK_FOR_EXCEPTION_VOID -#undef VM_THROW_EXCEPTION -#undef VM_THROW_EXCEPTION_2 -#undef VM_THROW_EXCEPTION_AT_END - -#endif // ENABLE(JIT) - -#else // MANUAL_MERGE_REQUIRED -#endif // MANUAL_MERGE_REQUIRED } // namespace JSC |
