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

📄 interpreter.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    Profiler** profiler = Profiler::enabledProfilerReference();    if (*profiler)        (*profiler)->willExecute(callFrame, function);    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, function);    m_registerFile.shrink(oldEnd);    return result;}JSValuePtr Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValuePtr* 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){    ASSERT(!scopeChain->globalData->exception);    if (m_reentryDepth >= MaxReentryDepth) {        *exception = createStackOverflowError(callFrame);        return jsNull();    }    DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());    EvalCodeBlock* codeBlock = &evalNode->bytecode(scopeChain);    JSVariableObject* variableObject;    for (ScopeChainNode* node = scopeChain; ; node = node->next) {        ASSERT(node);        if (node->object->isVariableObject()) {            variableObject = static_cast<JSVariableObject*>(node->object);            break;        }    }    { // Scope for BatchedTransitionOptimizer        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;            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) {            PutPropertySlot slot;            variableObject->put(callFrame, (*it)->m_ident, (*it)->makeFunction(callFrame, scopeChain), slot);        }    }    Register* oldEnd = m_registerFile.end();    Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;    if (!m_registerFile.grow(newEnd)) {        *exception = createStackOverflowError(callFrame);        return jsNull();    }    CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);    // a 0 codeBlock indicates a built-in caller    newCallFrame[codeBlock->thisRegister()] = JSValuePtr(thisObj);    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0);    if (codeBlock->needsFullScopeChain())        scopeChain->ref();    Profiler** profiler = Profiler::enabledProfilerReference();    if (*profiler)        (*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->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, evalNode->sourceURL(), evalNode->lineNo());    m_registerFile.shrink(oldEnd);    return result;}NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine){    Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();    if (!debugger)        return;    switch (debugHookID) {        case DidEnterCallFrame:            debugger->callEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);            return;        case WillLeaveCallFrame:            debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);            return;        case WillExecuteStatement:            debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);            return;        case WillExecuteProgram:            debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);            return;        case DidExecuteProgram:            debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);            return;        case DidReachBreakpoint:            debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);            return;    }}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);    JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);    callFrame[dst] = JSValuePtr(scope);    return callFrame->scopeChain()->push(scope);}NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr baseValue, const PutPropertySlot& slot){    // Recursive invocation may already have specialized this instruction.    if (vPC[0].u.opcode != getOpcode(op_put_by_id))        return;    if (!baseValue.isCell())        return;    // Uncacheable: give up.    if (!slot.isCacheable()) {        vPC[0] = getOpcode(op_put_by_id_generic);        return;    }        JSCell* baseCell = asCell(baseValue);    Structure* structure = baseCell->structure();    if (structure->isDictionary()) {        vPC[0] = getOpcode(op_put_by_id_generic);        return;    }    // Cache miss: record Structure to compare against next time.    Structure* lastStructure = vPC[4].u.structure;    if (structure != lastStructure) {        // First miss: record Structure to compare against next time.        if (!lastStructure) {            vPC[4] = structure;            return;        }        // Second miss: give up.        vPC[0] = getOpcode(op_put_by_id_generic);        return;    }    // Cache hit: Specialize instruction and ref Structures.    // If baseCell != slot.base(), then baseCell must be a proxy for another object.    if (baseCell != slot.base()) {        vPC[0] = getOpcode(op_put_by_id_generic);        return;    }    // Structure transition, cache transition info    if (slot.type() == PutPropertySlot::NewProperty) {        vPC[0] = getOpcode(op_put_by_id_transition);        vPC[4] = structure->previousID();        vPC[5] = structure;        vPC[6] = structure->prototypeChain(callFrame);        vPC[7] = slot.cachedOffset();        codeBlock->refStructures(vPC);        return;    }    vPC[0] = getOpcode(op_put_by_id_replace);    vPC[5] = slot.cachedOffset();    codeBlock->refStructures(vPC);}NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC){    codeBlock->derefStructures(vPC);    vPC[0] = getOpcode(op_put_by_id);    vPC[4] = 0;}NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValuePtr 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))        return;    // FIXME: Cache property access for immediates.    if (!baseValue.isCell()) {        vPC[0] = getOpcode(op_get_by_id_generic);        return;    }    JSGlobalData* globalData = &callFrame->globalData();    if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {        vPC[0] = getOpcode(op_get_array_length);        return;    }    if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {        vPC[0] = getOpcode(op_get_string_length);        return;    }    // Uncacheable: give up.    if (!slot.isCacheable()) {        vPC[0] = getOpcode(op_get_by_id_generic);        return;    }    Structure* structure = asCell(baseValue)->structure();    if (structure->isDictionary()) {        vPC[0] = getOpcode(op_get_by_id_generic);        return;    }    // Cache miss    Structure* lastStructure = vPC[4].u.structure;    if (structure != lastStructure) {        // First miss: record Structure to compare against next time.        if (!lastStructure) {            vPC[4] = structure;            return;        }        // Second miss: give up.        vPC[0] = getOpcode(op_get_by_id_generic);        return;    }    // Cache hit: Specialize instruction and ref Structures.    if (slot.slotBase() == baseValue) {        vPC[0] = getOpcode(op_get_by_id_self);        vPC[5] = slot.cachedOffset();        codeBlock->refStructures(vPC);        return;    }    if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {        ASSERT(slot.slotBase().isObject());        JSObject* baseObject = 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 (baseObject->structure()->isDictionary())            baseObject->setStructure(Structure::fromDictionaryTransition(baseObject->structure()));        vPC[0] = getOpcode(op_get_by_id_proto);        vPC[5] = baseObject->structure();        vPC[6] = slot.cachedOffset();        codeBlock->refStructures(vPC);        return;    }    size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);    if (!count) {        vPC[0] = getOpcode(op_get_by_id_generic);        return;    }    vPC[0] = getOpcode(op_get_by_id_chain);    vPC[4] = structure;    vPC[5] = structure->prototypeChain(callFrame);    vPC[6] = count;    vPC[7] = slot.cachedOffset();    codeBlock->refStructures(vPC);}NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC){    codeBlock->derefStructures(vPC);    vPC[0] = getOpcode(op_get_by_id);    vPC[4] = 0;}JSValuePtr Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValuePtr* 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.    if (flag == InitializeAndReturn) {        #if HAVE(COMPUTED_GOTO)            #define ADD_BYTECODE(id, length) m_opcodeTable[id] = &&id;                FOR_EACH_OPCODE_ID(ADD_BYTECODE);            #undef ADD_BYTECODE            #define ADD_OPCODE_ID(id, length) m_opcodeIDTable.add(&&id, id);                FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);            #undef ADD_OPCODE_ID

⌨️ 快捷键说明

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