⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interpreter.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);    JSValuePtr result = jsUndefined();    if (evalNode)        result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);    return result;}Interpreter::Interpreter()    : m_sampler(0)    , m_reentryDepth(0){    privateExecute(InitializeAndReturn, 0, 0, 0);}#ifndef NDEBUGvoid Interpreter::dumpCallFrame(CallFrame* callFrame){    callFrame->codeBlock()->dump(callFrame);    dumpRegisters(callFrame);}void Interpreter::dumpRegisters(CallFrame* callFrame){    printf("Register frame: \n\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;    if (codeBlock->codeType() == GlobalCode) {        it = registerFile->lastGlobal();        end = it + registerFile->numGlobals();        while (it != end) {            printf("[global var]               | %10p | %10p \n", it, (*it).v());            ++it;        }        printf("----------------------------------------------------\n");    }        it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;    printf("[this]                     | %10p | %10p \n", it, (*it).v()); ++it;    end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"    if (it != end) {        do {            printf("[param]                    | %10p | %10p \n", it, (*it).v());            ++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");    int registerCount = 0;    end = it + codeBlock->m_numVars;    if (it != end) {        do {            printf("[r%2d]                      | %10p | %10p \n", registerCount, it, (*it).v());            ++it;            ++registerCount;        } while (it != end);    }    printf("----------------------------------------------------\n");    end = it + codeBlock->m_numConstants;    if (it != end) {        do {            printf("[r%2d]                      | %10p | %10p \n", registerCount, it, (*it).v());            ++it;            ++registerCount;        } while (it != end);    }    printf("----------------------------------------------------\n");    end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numConstants - codeBlock->m_numVars;    if (it != end) {        do {            printf("[r%2d]                      | %10p | %10p \n", registerCount, it, (*it).v());            ++it;            ++registerCount;        } while (it != end);    }    printf("----------------------------------------------------\n");}#endifbool Interpreter::isOpcode(Opcode opcode){#if HAVE(COMPUTED_GOTO)    return opcode != HashTraits<Opcode>::emptyValue()        && !HashTraits<Opcode>::isDeletedValue(opcode)        && m_opcodeIDTable.contains(opcode);#else    return opcode >= 0 && opcode <= op_end;#endif}NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValuePtr exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock){    CodeBlock* oldCodeBlock = codeBlock;    ScopeChainNode* scopeChain = callFrame->scopeChain();    if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {        DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);        if (callFrame->callee())            debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());        else            debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());    }    if (Profiler* profiler = *Profiler::enabledProfilerReference()) {        if (callFrame->callee())            profiler->didExecute(callFrame, callFrame->callee());        else            profiler->didExecute(callFrame, codeBlock->ownerNode()->sourceURL(), codeBlock->ownerNode()->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))            scopeChain = scopeChain->pop();        static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments());    } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) {        if (!arguments->isTornOff())            arguments->copyRegisters();    }    if (oldCodeBlock->needsFullScopeChain())        scopeChain->deref();    void* returnPC = callFrame->returnPC();    callFrame = callFrame->callerFrame();    if (callFrame->hasHostCallFrameFlag())        return false;    codeBlock = callFrame->codeBlock();    bytecodeOffset = bytecodeOffsetForPC(callFrame, codeBlock, returnPC);    return true;}NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValuePtr& exceptionValue, unsigned bytecodeOffset, bool explicitThrow){    // Set up the exception object    CodeBlock* codeBlock = callFrame->codeBlock();    if (exceptionValue.isObject()) {        JSObject* exception = asObject(exceptionValue);        if (exception->isNotAnObjectErrorStub()) {            exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock);            exceptionValue = exception;        } else {            if (!exception->hasProperty(callFrame, Identifier(callFrame, "line")) &&                 !exception->hasProperty(callFrame, Identifier(callFrame, "sourceId")) &&                 !exception->hasProperty(callFrame, Identifier(callFrame, "sourceURL")) &&                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName)) &&                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionCaretOffsetPropertyName)) &&                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName))) {                if (explicitThrow) {                    int startOffset = 0;                    int endOffset = 0;                    int divotPoint = 0;                    int line = codeBlock->expressionRangeForBytecodeOffset(callFrame, bytecodeOffset, divotPoint, startOffset, endOffset);                    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, "line"), 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, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerNode()->sourceURL()), ReadOnly | DontDelete);            }                        if (exception->isWatchdogException()) {                while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {                    // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.                }                return 0;            }        }    }    if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {        DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);        debugger->exception(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset));    }    // If we throw in the middle of a call instruction, we need to notify    // the profiler manually that the call instruction has returned, since    // we'll never reach the relevant op_profile_did_call.    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));        else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))            profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue(callFrame));#else        int functionRegisterIndex;        if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))            profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue(callFrame));#endif    }    // Calculate an exception handler vPC, unwinding call frames as necessary.    HandlerInfo* handler = 0;    while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {        if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock))            return 0;    }    // Now unwind the scope chain within the exception handler's call frame.    ScopeChainNode* scopeChain = callFrame->scopeChain();    ScopeChain sc(scopeChain);    int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;    ASSERT(scopeDelta >= 0);    while (scopeDelta--)        scopeChain = scopeChain->pop();    callFrame->setScopeChain(scopeChain);    return handler;}JSValuePtr Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValuePtr* exception){    ASSERT(!scopeChain->globalData->exception);    if (m_reentryDepth >= MaxReentryDepth) {        *exception = createStackOverflowError(callFrame);        return jsNull();    }    CodeBlock* codeBlock = &programNode->bytecode(scopeChain);    Register* oldEnd = m_registerFile.end();    Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;    if (!m_registerFile.grow(newEnd)) {        *exception = createStackOverflowError(callFrame);        return jsNull();    }    DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject());    JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();    JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();    globalObject->copyGlobalsTo(m_registerFile);    CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);    newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);    newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0);    if (codeBlock->needsFullScopeChain())        scopeChain->ref();    Profiler** profiler = Profiler::enabledProfilerReference();    if (*profiler)        (*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo());    JSValuePtr 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);#else        result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);#endif        m_reentryDepth--;    }    if (*profiler)        (*profiler)->didExecute(callFrame, programNode->sourceURL(), programNode->lineNo());    if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)        lastGlobalObject->copyGlobalsTo(m_registerFile);    m_registerFile.shrink(oldEnd);    return result;}JSValuePtr Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValuePtr* exception){    ASSERT(!scopeChain->globalData->exception);    if (m_reentryDepth >= MaxReentryDepth) {        *exception = createStackOverflowError(callFrame);        return jsNull();    }    Register* oldEnd = m_registerFile.end();    int argc = 1 + args.size(); // implicit "this" parameter    if (!m_registerFile.grow(oldEnd + argc)) {        *exception = createStackOverflowError(callFrame);        return jsNull();    }    DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());    CallFrame* newCallFrame = CallFrame::create(oldEnd);    size_t dst = 0;    newCallFrame[0] = JSValuePtr(thisObj);    ArgList::const_iterator end = args.end();    for (ArgList::const_iterator it = args.begin(); it != end; ++it)        newCallFrame[++dst] = *it;    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 jsNull();    }    // a 0 codeBlock indicates a built-in caller    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -