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

📄 bytecodegenerator.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    ASSERT(!m_scopeContextStack.last().isFinallyBlock);    emitOpcode(op_pop_scope);    m_scopeContextStack.removeLast();    m_dynamicScopeDepth--;}void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine){    if (!m_shouldEmitDebugHooks)        return;    emitOpcode(op_debug);    instructions().append(debugHookID);    instructions().append(firstLine);    instructions().append(lastLine);}void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst){    ControlFlowContext scope;    scope.isFinallyBlock = true;    FinallyContext context = { target, retAddrDst };    scope.finallyContext = context;    m_scopeContextStack.append(scope);    m_finallyDepth++;}void BytecodeGenerator::popFinallyContext(){    ASSERT(m_scopeContextStack.size());    ASSERT(m_scopeContextStack.last().isFinallyBlock);    ASSERT(m_finallyDepth > 0);    m_scopeContextStack.removeLast();    m_finallyDepth--;}LabelScope* BytecodeGenerator::breakTarget(const Identifier& name){    // Reclaim free label scopes.    while (m_labelScopes.size() && !m_labelScopes.last().refCount())        m_labelScopes.removeLast();    if (!m_labelScopes.size())        return 0;    // We special-case the following, which is a syntax error in Firefox:    // label:    //     break;    if (name.isEmpty()) {        for (int i = m_labelScopes.size() - 1; i >= 0; --i) {            LabelScope* scope = &m_labelScopes[i];            if (scope->type() != LabelScope::NamedLabel) {                ASSERT(scope->breakTarget());                return scope;            }        }        return 0;    }    for (int i = m_labelScopes.size() - 1; i >= 0; --i) {        LabelScope* scope = &m_labelScopes[i];        if (scope->name() && *scope->name() == name) {            ASSERT(scope->breakTarget());            return scope;        }    }    return 0;}LabelScope* BytecodeGenerator::continueTarget(const Identifier& name){    // Reclaim free label scopes.    while (m_labelScopes.size() && !m_labelScopes.last().refCount())        m_labelScopes.removeLast();    if (!m_labelScopes.size())        return 0;    if (name.isEmpty()) {        for (int i = m_labelScopes.size() - 1; i >= 0; --i) {            LabelScope* scope = &m_labelScopes[i];            if (scope->type() == LabelScope::Loop) {                ASSERT(scope->continueTarget());                return scope;            }        }        return 0;    }    // Continue to the loop nested nearest to the label scope that matches    // 'name'.    LabelScope* result = 0;    for (int i = m_labelScopes.size() - 1; i >= 0; --i) {        LabelScope* scope = &m_labelScopes[i];        if (scope->type() == LabelScope::Loop) {            ASSERT(scope->continueTarget());            result = scope;        }        if (scope->name() && *scope->name() == name)            return result; // may be 0    }    return 0;}PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope){    while (topScope > bottomScope) {        // First we count the number of dynamic scopes we need to remove to get        // to a finally block.        int nNormalScopes = 0;        while (topScope > bottomScope) {            if (topScope->isFinallyBlock)                break;            ++nNormalScopes;            --topScope;        }        if (nNormalScopes) {            // We need to remove a number of dynamic scopes to get to the next            // finally block            emitOpcode(op_jmp_scopes);            instructions().append(nNormalScopes);            // If topScope == bottomScope then there isn't actually a finally block            // left to emit, so make the jmp_scopes jump directly to the target label            if (topScope == bottomScope) {                instructions().append(target->offsetFrom(instructions().size()));                return target;            }            // Otherwise we just use jmp_scopes to pop a group of scopes and go            // to the next instruction            RefPtr<Label> nextInsn = newLabel();            instructions().append(nextInsn->offsetFrom(instructions().size()));            emitLabel(nextInsn.get());        }        // To get here there must be at least one finally block present        do {            ASSERT(topScope->isFinallyBlock);            emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);            --topScope;            if (!topScope->isFinallyBlock)                break;        } while (topScope > bottomScope);    }    return emitJump(target);}PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetScopeDepth){    ASSERT(scopeDepth() - targetScopeDepth >= 0);    ASSERT(target->isForward());    size_t scopeDelta = scopeDepth() - targetScopeDepth;    ASSERT(scopeDelta <= m_scopeContextStack.size());    if (!scopeDelta)        return emitJump(target);    if (m_finallyDepth)        return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);    emitOpcode(op_jmp_scopes);    instructions().append(scopeDelta);    instructions().append(target->offsetFrom(instructions().size()));    return target;}RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target){    emitOpcode(op_next_pname);    instructions().append(dst->index());    instructions().append(iter->index());    instructions().append(target->offsetFrom(instructions().size()));    return dst;}RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end){#if ENABLE(JIT)    HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, MacroAssembler::CodeLocationLabel() };#else    HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };#endif    m_codeBlock->addExceptionHandler(info);    emitOpcode(op_catch);    instructions().append(targetRegister->index());    return targetRegister;}RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message){    emitOpcode(op_new_error);    instructions().append(dst->index());    instructions().append(static_cast<int>(type));    instructions().append(addUnexpectedConstant(message));    return dst;}PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally){    emitOpcode(op_jsr);    instructions().append(retAddrDst->index());    instructions().append(finally->offsetFrom(instructions().size()));    return finally;}void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc){    emitOpcode(op_sret);    instructions().append(retAddrSrc->index());}void BytecodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value){    ControlFlowContext context;    context.isFinallyBlock = false;    m_scopeContextStack.append(context);    m_dynamicScopeDepth++;        emitOpcode(op_push_new_scope);    instructions().append(dst->index());    instructions().append(addConstant(property));    instructions().append(value->index());}void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type){    SwitchInfo info = { instructions().size(), type };    switch (type) {        case SwitchInfo::SwitchImmediate:            emitOpcode(op_switch_imm);            break;        case SwitchInfo::SwitchCharacter:            emitOpcode(op_switch_char);            break;        case SwitchInfo::SwitchString:            emitOpcode(op_switch_string);            break;        default:            ASSERT_NOT_REACHED();    }    instructions().append(0); // place holder for table index    instructions().append(0); // place holder for default target        instructions().append(scrutineeRegister->index());    m_switchContextStack.append(info);}static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max){    UNUSED_PARAM(max);    ASSERT(node->isNumber());    double value = static_cast<NumberNode*>(node)->value();    int32_t key = static_cast<int32_t>(value);    ASSERT(JSValuePtr::makeInt32Fast(key) && (JSValuePtr::makeInt32Fast(key).getInt32Fast() == value));    ASSERT(key == value);    ASSERT(key >= min);    ASSERT(key <= max);    return key - min;}static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max){    jumpTable.min = min;    jumpTable.branchOffsets.resize(max - min + 1);    jumpTable.branchOffsets.fill(0);    for (uint32_t i = 0; i < clauseCount; ++i) {        // We're emitting this after the clause labels should have been fixed, so         // the labels should not be "forward" references        ASSERT(!labels[i]->isForward());        jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress));     }}static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max){    UNUSED_PARAM(max);    ASSERT(node->isString());    UString::Rep* clause = static_cast<StringNode*>(node)->value().ustring().rep();    ASSERT(clause->size() == 1);        int32_t key = clause->data()[0];    ASSERT(key >= min);    ASSERT(key <= max);    return key - min;}static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max){    jumpTable.min = min;    jumpTable.branchOffsets.resize(max - min + 1);    jumpTable.branchOffsets.fill(0);    for (uint32_t i = 0; i < clauseCount; ++i) {        // We're emitting this after the clause labels should have been fixed, so         // the labels should not be "forward" references        ASSERT(!labels[i]->isForward());        jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress));     }}static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes){    for (uint32_t i = 0; i < clauseCount; ++i) {        // We're emitting this after the clause labels should have been fixed, so         // the labels should not be "forward" references        ASSERT(!labels[i]->isForward());                ASSERT(nodes[i]->isString());        UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();        OffsetLocation location;        location.branchOffset = labels[i]->offsetFrom(switchAddress);        jumpTable.offsetTable.add(clause, location);    }}void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max){    SwitchInfo switchInfo = m_switchContextStack.last();    m_switchContextStack.removeLast();    if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {        instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables();        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);        SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();        prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);    } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {        instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables();        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);                SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();        prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);    } else {        ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);        instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);        StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();        prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes);    }}RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException(){    // It would be nice to do an even better job of identifying exactly where the expression is.    // And we could make the caller pass the node pointer in, if there was some way of getting    // that from an arbitrary node. However, calling emitExpressionInfo without any useful data    // is still good enough to get us an accurate line number.    emitExpressionInfo(0, 0, 0);    RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(globalData(), "Expression too deep"));    emitThrow(exception);    return exception;}} // namespace JSC

⌨️ 快捷键说明

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