diff options
Diffstat (limited to 'src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp')
-rw-r--r-- | src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp | 510 |
1 files changed, 214 insertions, 296 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp b/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp index c538eb1..4560db0 100644 --- a/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp @@ -58,6 +58,7 @@ #include "RegExpPrototype.h" #include "Register.h" #include "SamplingTool.h" +#include <limits.h> #include <stdio.h> #include <wtf/Threading.h> @@ -65,14 +66,6 @@ #include "JIT.h" #endif -#if ENABLE(ASSEMBLER) -#include "AssemblerBuffer.h" -#endif - -#ifdef QT_BUILD_SCRIPT_LIB -#include "bridge/qscriptobject_p.h" -#endif - using namespace std; namespace JSC { @@ -357,15 +350,14 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON); 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); + RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue); JSValue result = jsUndefined(); - if (evalNode) - result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue); + if (eval) + result = callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue); return result; } @@ -388,67 +380,92 @@ void Interpreter::dumpCallFrame(CallFrame* callFrame) void Interpreter::dumpRegisters(CallFrame* callFrame) { printf("Register frame: \n\n"); - printf("----------------------------------------------------\n"); - printf(" use | address | value \n"); - printf("----------------------------------------------------\n"); + printf("-----------------------------------------------------------------------------\n"); + printf(" use | address | value \n"); + printf("-----------------------------------------------------------------------------\n"); CodeBlock* codeBlock = callFrame->codeBlock(); RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->interpreter->registerFile(); const Register* it; const Register* end; + JSValue v; if (codeBlock->codeType() == GlobalCode) { it = registerFile->lastGlobal(); end = it + registerFile->numGlobals(); while (it != end) { - printf("[global var] | %10p | %10p \n", it, (*it).v()); + v = (*it).jsValue(); +#if USE(JSVALUE32_64) + printf("[global var] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); +#else + printf("[global var] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); +#endif ++it; } - printf("----------------------------------------------------\n"); + printf("-----------------------------------------------------------------------------\n"); } it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters; - printf("[this] | %10p | %10p \n", it, (*it).v()); ++it; + v = (*it).jsValue(); +#if USE(JSVALUE32_64) + printf("[this] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it; +#else + printf("[this] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it; +#endif end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this" if (it != end) { do { - printf("[param] | %10p | %10p \n", it, (*it).v()); + v = (*it).jsValue(); +#if USE(JSVALUE32_64) + printf("[param] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); +#else + printf("[param] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); +#endif ++it; } while (it != end); } - printf("----------------------------------------------------\n"); - - printf("[CodeBlock] | %10p | %10p \n", it, (*it).v()); ++it; - printf("[ScopeChain] | %10p | %10p \n", it, (*it).v()); ++it; - printf("[CallerRegisters] | %10p | %10p \n", it, (*it).v()); ++it; - printf("[ReturnPC] | %10p | %10p \n", it, (*it).v()); ++it; - printf("[ReturnValueRegister] | %10p | %10p \n", it, (*it).v()); ++it; - printf("[ArgumentCount] | %10p | %10p \n", it, (*it).v()); ++it; - printf("[Callee] | %10p | %10p \n", it, (*it).v()); ++it; - printf("[OptionalCalleeArguments] | %10p | %10p \n", it, (*it).v()); ++it; - printf("----------------------------------------------------\n"); + printf("-----------------------------------------------------------------------------\n"); + printf("[CodeBlock] | %10p | %p \n", it, (*it).codeBlock()); ++it; + printf("[ScopeChain] | %10p | %p \n", it, (*it).scopeChain()); ++it; + printf("[CallerRegisters] | %10p | %d \n", it, (*it).i()); ++it; + printf("[ReturnPC] | %10p | %p \n", it, (*it).vPC()); ++it; + printf("[ReturnValueRegister] | %10p | %d \n", it, (*it).i()); ++it; + printf("[ArgumentCount] | %10p | %d \n", it, (*it).i()); ++it; + printf("[Callee] | %10p | %p \n", it, (*it).function()); ++it; + printf("[OptionalCalleeArguments] | %10p | %p \n", it, (*it).arguments()); ++it; + printf("-----------------------------------------------------------------------------\n"); int registerCount = 0; end = it + codeBlock->m_numVars; if (it != end) { do { - printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v()); + v = (*it).jsValue(); +#if USE(JSVALUE32_64) + printf("[r%2d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v)); +#else + printf("[r%2d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v)); +#endif ++it; ++registerCount; } while (it != end); } - printf("----------------------------------------------------\n"); + printf("-----------------------------------------------------------------------------\n"); end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars; if (it != end) { do { - printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v()); + v = (*it).jsValue(); +#if USE(JSVALUE32_64) + printf("[r%2d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v)); +#else + printf("[r%2d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v)); +#endif ++it; ++registerCount; } while (it != end); } - printf("----------------------------------------------------\n"); + printf("-----------------------------------------------------------------------------\n"); } #endif @@ -471,25 +488,22 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) { DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); - if (callFrame->callee()) { - debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine()); -#ifdef QT_BUILD_SCRIPT_LIB - debugger->functionExit(exceptionValue, codeBlock->ownerNode()->sourceID()); -#endif - } else - debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine()); + if (callFrame->callee()) + debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine()); + else + debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine()); } if (Profiler* profiler = *Profiler::enabledProfilerReference()) { if (callFrame->callee()) profiler->didExecute(callFrame, callFrame->callee()); else - profiler->didExecute(callFrame, codeBlock->ownerNode()->sourceURL(), codeBlock->ownerNode()->lineNo()); + profiler->didExecute(callFrame, codeBlock->ownerExecutable()->sourceURL(), codeBlock->ownerExecutable()->lineNo()); } // If this call frame created an activation or an 'arguments' object, tear it off. if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) { - while (!scopeChain->object->isObject(&JSActivation::info)) + while (!scopeChain->object->inherits(&JSActivation::info)) scopeChain = scopeChain->pop(); static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments()); } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) { @@ -521,9 +535,9 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock); exceptionValue = exception; } else { - if (!exception->hasProperty(callFrame, Identifier(callFrame, JSC_ERROR_LINENUMBER_PROPERTYNAME)) && + if (!exception->hasProperty(callFrame, Identifier(callFrame, "line")) && !exception->hasProperty(callFrame, Identifier(callFrame, "sourceId")) && - !exception->hasProperty(callFrame, Identifier(callFrame, JSC_ERROR_FILENAME_PROPERTYNAME)) && + !exception->hasProperty(callFrame, Identifier(callFrame, "sourceURL")) && !exception->hasProperty(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName)) && !exception->hasProperty(callFrame, Identifier(callFrame, expressionCaretOffsetPropertyName)) && !exception->hasProperty(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName))) { @@ -532,16 +546,16 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV int endOffset = 0; int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(callFrame, bytecodeOffset, divotPoint, startOffset, endOffset); - exception->putWithAttributes(callFrame, Identifier(callFrame, JSC_ERROR_LINENUMBER_PROPERTYNAME), jsNumber(callFrame, line), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, line), ReadOnly | DontDelete); // We only hit this path for error messages and throw statements, which don't have a specific failure position // So we just give the full range of the error/throw statement. exception->putWithAttributes(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName), jsNumber(callFrame, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete); } else - exception->putWithAttributes(callFrame, Identifier(callFrame, JSC_ERROR_LINENUMBER_PROPERTYNAME), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete); - exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerNode()->sourceID()), ReadOnly | DontDelete); - exception->putWithAttributes(callFrame, Identifier(callFrame, JSC_ERROR_FILENAME_PROPERTYNAME), jsOwnedString(callFrame, codeBlock->ownerNode()->sourceURL()), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerExecutable()->sourceID()), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerExecutable()->sourceURL()), ReadOnly | DontDelete); } if (exception->isWatchdogException()) { @@ -553,10 +567,9 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV } } - Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); - if (debugger) { + if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) { DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); - debugger->exception(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)); + debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)); } // If we throw in the middle of a call instruction, we need to notify @@ -578,33 +591,11 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV // Calculate an exception handler vPC, unwinding call frames as necessary. HandlerInfo* handler = 0; - -#ifdef QT_BUILD_SCRIPT_LIB - //try to find handler - bool hasHandler = true; - CallFrame *callFrameTemp = callFrame; - unsigned bytecodeOffsetTemp = bytecodeOffset; - CodeBlock *codeBlockTemp = codeBlock; - while (!(handler = codeBlockTemp->handlerForBytecodeOffset(bytecodeOffsetTemp))) { - void* returnPC = callFrameTemp->returnPC(); - callFrameTemp = callFrameTemp->callerFrame(); - if (callFrameTemp->hasHostCallFrameFlag()) { - hasHandler = false; - break; - } else { - codeBlockTemp = callFrameTemp->codeBlock(); - bytecodeOffsetTemp = bytecodeOffsetForPC(callFrameTemp, codeBlockTemp, returnPC); - } - } - if (debugger) - debugger->exceptionThrow(DebuggerCallFrame(callFrame, exceptionValue), codeBlock->ownerNode()->sourceID(), hasHandler); -#endif - while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) { - if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) { + if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) return 0; - } } + // Now unwind the scope chain within the exception handler's call frame. ScopeChainNode* scopeChain = callFrame->scopeChain(); @@ -618,7 +609,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV return handler; } -JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception) +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception) { ASSERT(!scopeChain->globalData->exception); @@ -629,7 +620,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco } } - CodeBlock* codeBlock = &programNode->bytecode(scopeChain); + CodeBlock* codeBlock = &program->bytecode(callFrame, scopeChain); Register* oldEnd = m_registerFile.end(); Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters; @@ -653,7 +644,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) - (*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo()); + (*profiler)->willExecute(newCallFrame, program->sourceURL(), program->lineNo()); JSValue result; { @@ -661,7 +652,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco m_reentryDepth++; #if ENABLE(JIT) - result = programNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -669,7 +660,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco } if (*profiler) - (*profiler)->didExecute(callFrame, programNode->sourceURL(), programNode->lineNo()); + (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo()); if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject) lastGlobalObject->copyGlobalsTo(m_registerFile); @@ -679,7 +670,7 @@ JSValue Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, Sco return result; } -JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception) +JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception) { ASSERT(!scopeChain->globalData->exception); @@ -707,7 +698,7 @@ JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* call for (ArgList::const_iterator it = args.begin(); it != end; ++it) newCallFrame->r(++dst) = *it; - CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain); + CodeBlock* codeBlock = &functionExecutable->bytecode(callFrame, scopeChain); newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); if (UNLIKELY(!newCallFrame)) { *exception = createStackOverflowError(callFrame); @@ -727,7 +718,7 @@ JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* call m_reentryDepth++; #if ENABLE(JIT) - result = functionBodyNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = functionExecutable->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -741,7 +732,7 @@ JSValue Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* call return result; } -CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception) +CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception) { ASSERT(!scopeChain->globalData->exception); @@ -765,7 +756,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBod for (int i = 0; i < argc; ++i) newCallFrame->r(++dst) = jsUndefined(); - CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain); + CodeBlock* codeBlock = &FunctionExecutable->bytecode(callFrame, scopeChain); newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); if (UNLIKELY(!newCallFrame)) { *exception = createStackOverflowError(callFrame); @@ -775,10 +766,10 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBod // a 0 codeBlock indicates a built-in caller newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function); #if ENABLE(JIT) - functionBodyNode->jitCode(scopeChain); + FunctionExecutable->jitCode(newCallFrame, scopeChain); #endif - CallFrameClosure result = { callFrame, newCallFrame, function, functionBodyNode, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc }; + CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc }; return result; } @@ -795,7 +786,7 @@ JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception) m_reentryDepth++; #if ENABLE(JIT) - result = closure.functionBody->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception); + result = closure.functionExecutable->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception); #else result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception); #endif @@ -812,12 +803,12 @@ void Interpreter::endRepeatCall(CallFrameClosure& closure) m_registerFile.shrink(closure.oldEnd); } -JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception) +JSValue Interpreter::execute(EvalExecutable* eval, 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); + return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->bytecode(callFrame, scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception); } -JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception) +JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception) { ASSERT(!scopeChain->globalData->exception); @@ -830,7 +821,7 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject()); - EvalCodeBlock* codeBlock = &evalNode->bytecode(scopeChain); + EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain); JSVariableObject* variableObject; for (ScopeChainNode* node = scopeChain; ; node = node->next) { @@ -845,21 +836,20 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* BatchedTransitionOptimizer optimizer(variableObject); - const DeclarationStacks::VarStack& varStack = codeBlock->ownerNode()->varStack(); - DeclarationStacks::VarStack::const_iterator varStackEnd = varStack.end(); - for (DeclarationStacks::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) { - const Identifier& ident = (*it).first; + unsigned numVariables = codeBlock->numVariables(); + for (unsigned i = 0; i < numVariables; ++i) { + const Identifier& ident = codeBlock->variable(i); if (!variableObject->hasProperty(callFrame, ident)) { PutPropertySlot slot; variableObject->put(callFrame, ident, jsUndefined(), slot); } } - const DeclarationStacks::FunctionStack& functionStack = codeBlock->ownerNode()->functionStack(); - DeclarationStacks::FunctionStack::const_iterator functionStackEnd = functionStack.end(); - for (DeclarationStacks::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) { + int numFunctions = codeBlock->numberOfFunctionDecls(); + for (int i = 0; i < numFunctions; ++i) { + FunctionExecutable* function = codeBlock->functionDecl(i); PutPropertySlot slot; - variableObject->put(callFrame, (*it)->m_ident, (*it)->makeFunction(callFrame, scopeChain), slot); + variableObject->put(callFrame, function->name(), function->make(callFrame, scopeChain), slot); } } @@ -882,7 +872,7 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) - (*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo()); + (*profiler)->willExecute(newCallFrame, eval->sourceURL(), eval->lineNo()); JSValue result; { @@ -890,7 +880,7 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* m_reentryDepth++; #if ENABLE(JIT) - result = evalNode->jitCode(scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #else result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); #endif @@ -898,13 +888,13 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* } if (*profiler) - (*profiler)->didExecute(callFrame, evalNode->sourceURL(), evalNode->lineNo()); + (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo()); m_registerFile.shrink(oldEnd); return result; } -NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine, int column) +NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine) { Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); if (!debugger) @@ -912,22 +902,22 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook switch (debugHookID) { case DidEnterCallFrame: - debugger->callEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine); + debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine); return; case WillLeaveCallFrame: - debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine); + debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine); return; case WillExecuteStatement: - debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine, column); + debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine); return; case WillExecuteProgram: - debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine); + debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine); return; case DidExecuteProgram: - debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine); + debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine); return; case DidReachBreakpoint: - debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine, column); + debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine); return; } } @@ -1145,7 +1135,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi } #if ENABLE(JIT) - // Currently with CTI enabled we never interpret functions + // Mixing Interpreter + JIT is not supported. ASSERT_NOT_REACHED(); #endif #if !USE(INTERPRETER) @@ -1161,7 +1151,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Instruction* vPC = callFrame->codeBlock()->instructions().begin(); Profiler** enabledProfilerReference = Profiler::enabledProfilerReference(); - unsigned tickCount = globalData->timeoutChecker->ticksUntilNextCheck(); + unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); #define CHECK_FOR_EXCEPTION() \ do { \ @@ -1177,11 +1167,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #define CHECK_FOR_TIMEOUT() \ if (!--tickCount) { \ - if (globalData->timeoutChecker->didTimeOut(callFrame)) { \ + if (globalData->timeoutChecker.didTimeOut(callFrame)) { \ exceptionValue = jsNull(); \ goto vm_throw; \ } \ - tickCount = globalData->timeoutChecker->ticksUntilNextCheck(); \ + tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \ } #if ENABLE(OPCODE_SAMPLING) @@ -1275,8 +1265,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) - callFrame->r(dst) = JSFastMath::equal(src1, src2); + if (src1.isInt32() && src2.isInt32()) + callFrame->r(dst) = jsBoolean(src1.asInt32() == src2.asInt32()); else { JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); @@ -1315,8 +1305,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) - callFrame->r(dst) = JSFastMath::notEqual(src1, src2); + if (src1.isInt32() && src2.isInt32()) + callFrame->r(dst) = jsBoolean(src1.asInt32() != src2.asInt32()); else { JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); @@ -1417,8 +1407,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ int srcDst = (++vPC)->u.operand; JSValue v = callFrame->r(srcDst).jsValue(); - if (JSFastMath::canDoFastAdditiveOperations(v)) - callFrame->r(srcDst) = JSValue(JSFastMath::incImmediateNumber(v)); + if (v.isInt32() && v.asInt32() < INT_MAX) + callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1); else { JSValue result = jsNumber(callFrame, v.toNumber(callFrame) + 1); CHECK_FOR_EXCEPTION(); @@ -1436,8 +1426,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ int srcDst = (++vPC)->u.operand; JSValue v = callFrame->r(srcDst).jsValue(); - if (JSFastMath::canDoFastAdditiveOperations(v)) - callFrame->r(srcDst) = JSValue(JSFastMath::decImmediateNumber(v)); + if (v.isInt32() && v.asInt32() > INT_MIN) + callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1); else { JSValue result = jsNumber(callFrame, v.toNumber(callFrame) - 1); CHECK_FOR_EXCEPTION(); @@ -1457,14 +1447,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; int srcDst = (++vPC)->u.operand; JSValue v = callFrame->r(srcDst).jsValue(); - if (JSFastMath::canDoFastAdditiveOperations(v)) { + if (v.isInt32() && v.asInt32() < INT_MAX) { + callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1); callFrame->r(dst) = v; - callFrame->r(srcDst) = JSValue(JSFastMath::incImmediateNumber(v)); } else { JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame); CHECK_FOR_EXCEPTION(); + callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() + 1); callFrame->r(dst) = number; - callFrame->r(srcDst) = JSValue(jsNumber(callFrame, number.uncheckedGetNumber() + 1)); } ++vPC; @@ -1480,14 +1470,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; int srcDst = (++vPC)->u.operand; JSValue v = callFrame->r(srcDst).jsValue(); - if (JSFastMath::canDoFastAdditiveOperations(v)) { + if (v.isInt32() && v.asInt32() > INT_MIN) { + callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1); callFrame->r(dst) = v; - callFrame->r(srcDst) = JSValue(JSFastMath::decImmediateNumber(v)); } else { JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame); CHECK_FOR_EXCEPTION(); + callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() - 1); callFrame->r(dst) = number; - callFrame->r(srcDst) = JSValue(jsNumber(callFrame, number.uncheckedGetNumber() - 1)); } ++vPC; @@ -1523,16 +1513,15 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ int dst = (++vPC)->u.operand; JSValue src = callFrame->r((++vPC)->u.operand).jsValue(); - ++vPC; - double v; - if (src.getNumber(v)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, -v)); + if (src.isInt32() && src.asInt32()) + callFrame->r(dst) = jsNumber(callFrame, -src.asInt32()); else { JSValue result = jsNumber(callFrame, -src.toNumber(callFrame)); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; } + ++vPC; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_add) { @@ -1545,8 +1534,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - if (JSFastMath::canDoFastAdditiveOperations(src1, src2)) - callFrame->r(dst) = JSValue(JSFastMath::addImmediateNumbers(src1, src2)); + if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() & 0xc0000000)) // no overflow + callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() + src2.asInt32()); else { JSValue result = jsAdd(callFrame, src1, src2); CHECK_FOR_EXCEPTION(); @@ -1564,17 +1553,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - double left; - double right; - if (JSValue::areBothInt32Fast(src1, src2)) { - int32_t left = src1.getInt32Fast(); - int32_t right = src2.getInt32Fast(); - if ((left | right) >> 15 == 0) - callFrame->r(dst) = JSValue(jsNumber(callFrame, left * right)); - else - callFrame->r(dst) = JSValue(jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right))); - } else if (src1.getNumber(left) && src2.getNumber(right)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, left * right)); + if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow + callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() * src2.asInt32()); else { JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame)); CHECK_FOR_EXCEPTION(); @@ -1594,16 +1574,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue dividend = callFrame->r((++vPC)->u.operand).jsValue(); JSValue divisor = callFrame->r((++vPC)->u.operand).jsValue(); - double left; - double right; - if (dividend.getNumber(left) && divisor.getNumber(right)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, left / right)); - else { - JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame)); - CHECK_FOR_EXCEPTION(); - callFrame->r(dst) = result; - } - ++vPC; + + JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame)); + CHECK_FOR_EXCEPTION(); + callFrame->r(dst) = result; + + vPC += 2; NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_mod) { @@ -1614,24 +1590,22 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi remainder in register dst. */ int dst = (++vPC)->u.operand; - int dividend = (++vPC)->u.operand; - int divisor = (++vPC)->u.operand; - - JSValue dividendValue = callFrame->r(dividend).jsValue(); - JSValue divisorValue = callFrame->r(divisor).jsValue(); + JSValue dividend = callFrame->r((++vPC)->u.operand).jsValue(); + JSValue divisor = callFrame->r((++vPC)->u.operand).jsValue(); - 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. - JSValue result = JSValue::makeInt32Fast(dividendValue.getInt32Fast() % divisorValue.getInt32Fast()); + if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) { + JSValue result = jsNumber(callFrame, dividend.asInt32() % divisor.asInt32()); ASSERT(result); callFrame->r(dst) = result; ++vPC; NEXT_INSTRUCTION(); } - double d = dividendValue.toNumber(callFrame); - JSValue result = jsNumber(callFrame, fmod(d, divisorValue.toNumber(callFrame))); + // Conversion to double must happen outside the call to fmod since the + // order of argument evaluation is not guaranteed. + double d1 = dividend.toNumber(callFrame); + double d2 = divisor.toNumber(callFrame); + JSValue result = jsNumber(callFrame, fmod(d1, d2)); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; ++vPC; @@ -1647,12 +1621,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - double left; - double right; - if (JSFastMath::canDoFastAdditiveOperations(src1, src2)) - callFrame->r(dst) = JSValue(JSFastMath::subImmediateNumbers(src1, src2)); - else if (src1.getNumber(left) && src2.getNumber(right)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, left - right)); + if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() & 0xc0000000)) // no overflow + callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() - src2.asInt32()); else { JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame)); CHECK_FOR_EXCEPTION(); @@ -1671,12 +1641,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue val = callFrame->r((++vPC)->u.operand).jsValue(); JSValue shift = callFrame->r((++vPC)->u.operand).jsValue(); - int32_t left; - uint32_t right; - if (JSValue::areBothInt32Fast(val, shift)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, val.getInt32Fast() << (shift.getInt32Fast() & 0x1f))); - else if (val.numberToInt32(left) && shift.numberToUInt32(right)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, left << (right & 0x1f))); + + if (val.isInt32() && shift.isInt32()) + callFrame->r(dst) = jsNumber(callFrame, val.asInt32() << (shift.asInt32() & 0x1f)); else { JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f)); CHECK_FOR_EXCEPTION(); @@ -1696,12 +1663,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue val = callFrame->r((++vPC)->u.operand).jsValue(); JSValue shift = callFrame->r((++vPC)->u.operand).jsValue(); - int32_t left; - uint32_t right; - if (JSFastMath::canDoFastRshift(val, shift)) - callFrame->r(dst) = JSValue(JSFastMath::rightShiftImmediateNumbers(val, shift)); - else if (val.numberToInt32(left) && shift.numberToUInt32(right)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, left >> (right & 0x1f))); + + if (val.isInt32() && shift.isInt32()) + callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f)); else { JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); CHECK_FOR_EXCEPTION(); @@ -1721,8 +1685,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue val = callFrame->r((++vPC)->u.operand).jsValue(); JSValue shift = callFrame->r((++vPC)->u.operand).jsValue(); - if (JSFastMath::canDoFastUrshift(val, shift)) - callFrame->r(dst) = JSValue(JSFastMath::rightShiftImmediateNumbers(val, shift)); + if (val.isUInt32() && shift.isInt32()) + callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f)); else { JSValue result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); CHECK_FOR_EXCEPTION(); @@ -1742,12 +1706,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - int32_t left; - int32_t right; - if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) - callFrame->r(dst) = JSValue(JSFastMath::andImmediateNumbers(src1, src2)); - else if (src1.numberToInt32(left) && src2.numberToInt32(right)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, left & right)); + if (src1.isInt32() && src2.isInt32()) + callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() & src2.asInt32()); else { JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame)); CHECK_FOR_EXCEPTION(); @@ -1767,12 +1727,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - int32_t left; - int32_t right; - if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) - callFrame->r(dst) = JSValue(JSFastMath::xorImmediateNumbers(src1, src2)); - else if (src1.numberToInt32(left) && src2.numberToInt32(right)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, left ^ right)); + if (src1.isInt32() && src2.isInt32()) + callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() ^ src2.asInt32()); else { JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame)); CHECK_FOR_EXCEPTION(); @@ -1792,12 +1748,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - int32_t left; - int32_t right; - if (JSFastMath::canDoFastBitwiseOperations(src1, src2)) - callFrame->r(dst) = JSValue(JSFastMath::orImmediateNumbers(src1, src2)); - else if (src1.numberToInt32(left) && src2.numberToInt32(right)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, left | right)); + if (src1.isInt32() && src2.isInt32()) + callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() | src2.asInt32()); else { JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame)); CHECK_FOR_EXCEPTION(); @@ -1815,9 +1767,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ int dst = (++vPC)->u.operand; JSValue src = callFrame->r((++vPC)->u.operand).jsValue(); - int32_t value; - if (src.numberToInt32(value)) - callFrame->r(dst) = JSValue(jsNumber(callFrame, ~value)); + if (src.isInt32()) + callFrame->r(dst) = jsNumber(callFrame, ~src.asInt32()); else { JSValue result = jsNumber(callFrame, ~src.toInt32(callFrame)); CHECK_FOR_EXCEPTION(); @@ -2151,27 +2102,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi vPC += 4; NEXT_INSTRUCTION(); } - DEFINE_OPCODE(op_resolve_func) { - /* resolve_func baseDst(r) funcDst(r) property(id) - - Searches the scope chain for an object containing - identifier property, and if one is found, writes the - appropriate object to use as "this" when calling its - properties to register baseDst; and the retrieved property - value to register propDst. If the property is not found, - raises an exception. - - This differs from resolve_with_base, because the - global this value will be substituted for activations or - the global object, which is the right behavior for function - calls but not for other property lookup. - */ - if (UNLIKELY(!resolveBaseAndFunc(callFrame, vPC, exceptionValue))) - goto vm_throw; - - vPC += 4; - NEXT_INSTRUCTION(); - } DEFINE_OPCODE(op_get_by_id) { /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n) @@ -2352,7 +2282,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSValue baseValue = callFrame->r(base).jsValue(); if (LIKELY(isJSArray(globalData, baseValue))) { int dst = vPC[1].u.operand; - callFrame->r(dst) = JSValue(jsNumber(callFrame, asArray(baseValue)->length())); + callFrame->r(dst) = jsNumber(callFrame, asArray(baseValue)->length()); vPC += 8; NEXT_INSTRUCTION(); } @@ -2372,7 +2302,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSValue baseValue = callFrame->r(base).jsValue(); if (LIKELY(isJSString(globalData, baseValue))) { int dst = vPC[1].u.operand; - callFrame->r(dst) = JSValue(jsNumber(callFrame, asString(baseValue)->value().size())); + callFrame->r(dst) = jsNumber(callFrame, asString(baseValue)->value().size()); vPC += 8; NEXT_INSTRUCTION(); } @@ -2550,8 +2480,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSValue result; - if (LIKELY(subscript.isUInt32Fast())) { - uint32_t i = subscript.getUInt32Fast(); + if (LIKELY(subscript.isUInt32())) { + uint32_t i = subscript.asUInt32(); if (isJSArray(globalData, baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canGetIndex(i)) @@ -2592,8 +2522,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSValue baseValue = callFrame->r(base).jsValue(); JSValue subscript = callFrame->r(property).jsValue(); - if (LIKELY(subscript.isUInt32Fast())) { - uint32_t i = subscript.getUInt32Fast(); + if (LIKELY(subscript.isUInt32())) { + uint32_t i = subscript.asUInt32(); if (isJSArray(globalData, baseValue)) { JSArray* jsArray = asArray(baseValue); if (jsArray->canSetIndex(i)) @@ -2604,8 +2534,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSByteArray* jsByteArray = asByteArray(baseValue); double dValue = 0; JSValue jsValue = callFrame->r(value).jsValue(); - if (jsValue.isInt32Fast()) - jsByteArray->setIndex(i, jsValue.getInt32Fast()); + if (jsValue.isInt32()) + jsByteArray->setIndex(i, jsValue.asInt32()); else if (jsValue.getNumber(dValue)) jsByteArray->setIndex(i, dValue); else @@ -2925,8 +2855,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int tableIndex = (++vPC)->u.operand; int defaultOffset = (++vPC)->u.operand; JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue(); - if (scrutinee.isInt32Fast()) - vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.getInt32Fast(), defaultOffset); + if (scrutinee.isInt32()) + vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset); else { double value; int32_t intValue; @@ -2989,7 +2919,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = (++vPC)->u.operand; int func = (++vPC)->u.operand; - callFrame->r(dst) = callFrame->codeBlock()->function(func)->makeFunction(callFrame, callFrame->scopeChain()); + callFrame->r(dst) = JSValue(callFrame->codeBlock()->functionDecl(func)->make(callFrame, callFrame->scopeChain())); ++vPC; NEXT_INSTRUCTION(); @@ -3003,9 +2933,24 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi puts the result in register dst. */ int dst = (++vPC)->u.operand; - int func = (++vPC)->u.operand; + int funcIndex = (++vPC)->u.operand; + + FunctionExecutable* function = callFrame->codeBlock()->functionExpr(funcIndex); + JSFunction* func = function->make(callFrame, callFrame->scopeChain()); + + /* + The Identifier in a FunctionExpression can be referenced from inside + the FunctionExpression's FunctionBody to allow the function to call + itself recursively. However, unlike in a FunctionDeclaration, the + Identifier in a FunctionExpression cannot be referenced from and + does not affect the scope enclosing the FunctionExpression. + */ + if (!function->name().isNull()) { + JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete); + func->scope().push(functionScopeObject); + } - callFrame->r(dst) = callFrame->codeBlock()->functionExpression(func)->makeFunction(callFrame, callFrame->scopeChain()); + callFrame->r(dst) = JSValue(func); ++vPC; NEXT_INSTRUCTION(); @@ -3071,8 +3016,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; - FunctionBodyNode* functionBodyNode = callData.js.functionBody; - CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain); + CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain); CallFrame* previousCallFrame = callFrame; @@ -3096,7 +3040,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (callType == CallTypeHost) { ScopeChainNode* scopeChain = callFrame->scopeChain(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v)); + newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0); Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; ArgList args(thisRegister + 1, argCount - 1); @@ -3113,7 +3057,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi } CHECK_FOR_EXCEPTION(); - callFrame->r(dst) = JSValue(returnValue); + callFrame->r(dst) = returnValue; vPC += 5; NEXT_INSTRUCTION(); @@ -3138,7 +3082,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi exceptionValue = createStackOverflowError(callFrame); goto vm_throw; } - int32_t expectedParams = static_cast<JSFunction*>(callFrame->callee())->body()->parameterCount(); + ASSERT(!callFrame->callee()->isHostFunction()); + int32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount(); int32_t inplaceArgs = min(argCount, expectedParams); int32_t i = 0; Register* argStore = callFrame->registers() + argsOffset; @@ -3196,7 +3141,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi } } CHECK_FOR_EXCEPTION(); - callFrame->r(argCountDst) = argCount + 1; + callFrame->r(argCountDst) = Register::withInt(argCount + 1); ++vPC; NEXT_INSTRUCTION(); } @@ -3225,8 +3170,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; - FunctionBodyNode* functionBodyNode = callData.js.functionBody; - CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain); + CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain); CallFrame* previousCallFrame = callFrame; @@ -3250,7 +3194,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (callType == CallTypeHost) { ScopeChainNode* scopeChain = callFrame->scopeChain(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v)); + newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0); Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; ArgList args(thisRegister + 1, argCount - 1); @@ -3267,7 +3211,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi } CHECK_FOR_EXCEPTION(); - callFrame->r(dst) = JSValue(returnValue); + callFrame->r(dst) = returnValue; vPC += 5; NEXT_INSTRUCTION(); @@ -3313,6 +3257,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain()); + if (callFrame->optionalCalleeArguments()) callFrame->optionalCalleeArguments()->copyRegisters(); @@ -3329,31 +3274,21 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi register base to those of the calling function. */ -#ifdef QT_BUILD_SCRIPT_LIB - Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); - intptr_t sourceId = callFrame->codeBlock()->source()->asID(); -#endif - int result = (++vPC)->u.operand; if (callFrame->codeBlock()->needsFullScopeChain()) callFrame->scopeChain()->deref(); JSValue returnValue = callFrame->r(result).jsValue(); -#ifdef QT_BUILD_SCRIPT_LIB - if (debugger) { - debugger->functionExit(returnValue, sourceId); - } -#endif vPC = callFrame->returnPC(); int dst = callFrame->returnValueRegister(); callFrame = callFrame->callerFrame(); - + if (callFrame->hasHostCallFrameFlag()) return returnValue; - callFrame->r(dst) = JSValue(returnValue); + callFrame->r(dst) = returnValue; NEXT_INSTRUCTION(); } @@ -3397,8 +3332,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(i) = jsUndefined(); int dst = (++vPC)->u.operand; - JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionBodyNode*>(codeBlock->ownerNode())); - callFrame->r(dst) = activation; + JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable())); + callFrame->r(dst) = JSValue(activation); callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); ++vPC; @@ -3449,7 +3384,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (!callFrame->r(RegisterFile::ArgumentsRegister).jsValue()) { Arguments* arguments = new (globalData) Arguments(callFrame); callFrame->setCalleeArguments(arguments); - callFrame->r(RegisterFile::ArgumentsRegister) = arguments; + callFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments); } ++vPC; NEXT_INSTRUCTION(); @@ -3483,8 +3418,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (constructType == ConstructTypeJS) { ScopeChainNode* callDataScopeChain = constructData.js.scopeChain; - FunctionBodyNode* functionBodyNode = constructData.js.functionBody; - CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain); + CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecode(callFrame, callDataScopeChain); Structure* structure; JSValue prototype = callFrame->r(proto).jsValue(); @@ -3492,12 +3426,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi structure = asObject(prototype)->inheritorID(); else structure = callDataScopeChain->globalObject()->emptyObjectStructure(); -#ifdef QT_BUILD_SCRIPT_LIB - // ### world-class hack - QScriptObject* newObject = new (globalData) QScriptObject(structure); -#else JSObject* newObject = new (globalData) JSObject(structure); -#endif + callFrame->r(thisRegister) = JSValue(newObject); // "this" value CallFrame* previousCallFrame = callFrame; @@ -3523,9 +3453,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1); ScopeChainNode* scopeChain = callFrame->scopeChain(); - CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, asObject(v)); + newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0); JSValue returnValue; { @@ -3696,16 +3625,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ ASSERT(exceptionValue); ASSERT(!globalData->exception); - -#ifdef QT_BUILD_SCRIPT_LIB - CodeBlock* codeBlock = callFrame->codeBlock(); - Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); - if (debugger) { - DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); - debugger->exceptionCatch(debuggerCallFrame, codeBlock->ownerNode()->sourceID()); - } -#endif - int ex = (++vPC)->u.operand; callFrame->r(ex) = exceptionValue; exceptionValue = JSValue(); @@ -3749,7 +3668,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int message = (++vPC)->u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); - callFrame->r(dst) = JSValue(Error::create(callFrame, (ErrorType)type, callFrame->r(message).jsValue().toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL())); + callFrame->r(dst) = JSValue(Error::create(callFrame, (ErrorType)type, callFrame->r(message).jsValue().toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL())); ++vPC; NEXT_INSTRUCTION(); @@ -3846,7 +3765,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_debug) { - /* debug debugHookID(n) firstLine(n) lastLine(n) columnNumber(n) + /* debug debugHookID(n) firstLine(n) lastLine(n) Notifies the debugger of the current state of execution. This opcode is only generated while the debugger is attached. @@ -3854,9 +3773,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int debugHookID = (++vPC)->u.operand; int firstLine = (++vPC)->u.operand; int lastLine = (++vPC)->u.operand; - int column = (++vPC)->u.operand; - debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); + debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); ++vPC; NEXT_INSTRUCTION(); @@ -3925,12 +3843,12 @@ JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* functio CodeBlock* codeBlock = functionCallFrame->codeBlock(); if (codeBlock->usesArguments()) { ASSERT(codeBlock->codeType() == FunctionCode); - SymbolTable& symbolTable = codeBlock->symbolTable(); + SymbolTable& symbolTable = *codeBlock->symbolTable(); int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex(); - if (!functionCallFrame->r(argumentsIndex).arguments()) { + if (!functionCallFrame->r(argumentsIndex).jsValue()) { Arguments* arguments = new (callFrame) Arguments(functionCallFrame); functionCallFrame->setCalleeArguments(arguments); - functionCallFrame->r(RegisterFile::ArgumentsRegister) = arguments; + functionCallFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments); } return functionCallFrame->r(argumentsIndex).jsValue(); } @@ -3978,8 +3896,8 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp unsigned bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC()); lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1); - sourceID = callerCodeBlock->ownerNode()->sourceID(); - sourceURL = callerCodeBlock->ownerNode()->sourceURL(); + sourceID = callerCodeBlock->ownerExecutable()->sourceID(); + sourceURL = callerCodeBlock->ownerExecutable()->sourceURL(); function = callerFrame->callee(); } |