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

📄 jit.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
#if ENABLE(OPCODE_SAMPLING)        if (m_bytecodeIndex > 0) // Avoid the overhead of sampling op_enter twice.            sampleInstruction(currentInstruction);#endif        if (m_labels[m_bytecodeIndex].isUsed())            killLastResultRegister();                m_labels[m_bytecodeIndex] = label();        OpcodeID opcodeID = m_interpreter->getOpcodeID(currentInstruction->u.opcode);        switch (opcodeID) {        case op_mov: {            int src = currentInstruction[2].u.operand;            int dst = currentInstruction[1].u.operand;            if (m_codeBlock->isConstantRegisterIndex(src)) {                storePtr(ImmPtr(JSValuePtr::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register)));                if (dst == m_lastResultBytecodeRegister)                    killLastResultRegister();            } else if ((src == m_lastResultBytecodeRegister) || (dst == m_lastResultBytecodeRegister)) {                // If either the src or dst is the cached register go though                // get/put registers to make sure we track this correctly.                emitGetVirtualRegister(src, regT0);                emitPutVirtualRegister(dst);            } else {                // Perform the copy via regT1; do not disturb any mapping in regT0.                loadPtr(Address(callFrameRegister, src * sizeof(Register)), regT1);                storePtr(regT1, Address(callFrameRegister, dst * sizeof(Register)));            }            NEXT_OPCODE(op_mov);        }        case op_add: {            compileFastArith_op_add(currentInstruction);            NEXT_OPCODE(op_add);        }        case op_end: {            if (m_codeBlock->needsFullScopeChain())                emitCTICall(JITStubs::cti_op_end);            ASSERT(returnValueRegister != callFrameRegister);            emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);            push(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register))));            ret();            NEXT_OPCODE(op_end);        }        case op_jmp: {            unsigned target = currentInstruction[1].u.operand;            addJump(jump(), target + 1);            RECORD_JUMP_TARGET(target + 1);            NEXT_OPCODE(op_jmp);        }        case op_pre_inc: {            compileFastArith_op_pre_inc(currentInstruction[1].u.operand);            NEXT_OPCODE(op_pre_inc);        }        case op_loop: {            emitTimeoutCheck();            unsigned target = currentInstruction[1].u.operand;            addJump(jump(), target + 1);            NEXT_OPCODE(op_end);        }        case op_loop_if_less: {            emitTimeoutCheck();            unsigned op1 = currentInstruction[1].u.operand;            unsigned op2 = currentInstruction[2].u.operand;            unsigned target = currentInstruction[3].u.operand;            if (isOperandConstantImmediateInt(op2)) {                emitGetVirtualRegister(op1, regT0);                emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE)                int32_t op2imm = getConstantOperandImmediateInt(op2);#else                int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));#endif                addJump(branch32(LessThan, regT0, Imm32(op2imm)), target + 3);            } else {                emitGetVirtualRegisters(op1, regT0, op2, regT1);                emitJumpSlowCaseIfNotImmediateInteger(regT0);                emitJumpSlowCaseIfNotImmediateInteger(regT1);                addJump(branch32(LessThan, regT0, regT1), target + 3);            }            NEXT_OPCODE(op_loop_if_less);        }        case op_loop_if_lesseq: {            emitTimeoutCheck();            unsigned op1 = currentInstruction[1].u.operand;            unsigned op2 = currentInstruction[2].u.operand;            unsigned target = currentInstruction[3].u.operand;            if (isOperandConstantImmediateInt(op2)) {                emitGetVirtualRegister(op1, regT0);                emitJumpSlowCaseIfNotImmediateInteger(regT0);#if USE(ALTERNATE_JSIMMEDIATE)                int32_t op2imm = getConstantOperandImmediateInt(op2);#else                int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));#endif                addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target + 3);            } else {                emitGetVirtualRegisters(op1, regT0, op2, regT1);                emitJumpSlowCaseIfNotImmediateInteger(regT0);                emitJumpSlowCaseIfNotImmediateInteger(regT1);                addJump(branch32(LessThanOrEqual, regT0, regT1), target + 3);            }            NEXT_OPCODE(op_loop_if_less);        }        case op_new_object: {            emitCTICall(JITStubs::cti_op_new_object);            emitPutVirtualRegister(currentInstruction[1].u.operand);            NEXT_OPCODE(op_new_object);        }        case op_put_by_id: {            compilePutByIdHotPath(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, propertyAccessInstructionIndex++);            NEXT_OPCODE(op_put_by_id);        }        case op_get_by_id: {            compileGetByIdHotPath(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), propertyAccessInstructionIndex++);            NEXT_OPCODE(op_get_by_id);        }        case op_instanceof: {            emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); // value            emitGetVirtualRegister(currentInstruction[3].u.operand, regT2); // baseVal            emitGetVirtualRegister(currentInstruction[4].u.operand, regT1); // proto            // check if any are immediates            move(regT0, regT3);            orPtr(regT2, regT3);            orPtr(regT1, regT3);            emitJumpSlowCaseIfNotJSCell(regT3);            // check that all are object type - this is a bit of a bithack to avoid excess branching;            // we check that the sum of the three type codes from Structures is exactly 3 * ObjectType,            // this works because NumberType and StringType are smaller            move(Imm32(3 * ObjectType), regT3);            loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT0);            loadPtr(Address(regT2, FIELD_OFFSET(JSCell, m_structure)), regT2);            loadPtr(Address(regT1, FIELD_OFFSET(JSCell, m_structure)), regT1);            sub32(Address(regT0, FIELD_OFFSET(Structure, m_typeInfo.m_type)), regT3);            sub32(Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_type)), regT3);            addSlowCase(branch32(NotEqual, Address(regT1, FIELD_OFFSET(Structure, m_typeInfo.m_type)), regT3));            // check that baseVal's flags include ImplementsHasInstance but not OverridesHasInstance            load32(Address(regT2, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), regT2);            and32(Imm32(ImplementsHasInstance | OverridesHasInstance), regT2);            addSlowCase(branch32(NotEqual, regT2, Imm32(ImplementsHasInstance)));            emitGetVirtualRegister(currentInstruction[2].u.operand, regT2); // reload value            emitGetVirtualRegister(currentInstruction[4].u.operand, regT1); // reload proto            // optimistically load true result            move(ImmPtr(JSValuePtr::encode(jsBoolean(true))), regT0);            Label loop(this);            // load value's prototype            loadPtr(Address(regT2, FIELD_OFFSET(JSCell, m_structure)), regT2);            loadPtr(Address(regT2, FIELD_OFFSET(Structure, m_prototype)), regT2);            Jump exit = branchPtr(Equal, regT2, regT1);            branchPtr(NotEqual, regT2, ImmPtr(JSValuePtr::encode(jsNull())), loop);            move(ImmPtr(JSValuePtr::encode(jsBoolean(false))), regT0);            exit.link(this);            emitPutVirtualRegister(currentInstruction[1].u.operand);            NEXT_OPCODE(op_instanceof);        }        case op_del_by_id: {            emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, regT2);            Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));            emitPutJITStubArgConstant(ident, 2);            emitCTICall(JITStubs::cti_op_del_by_id);            emitPutVirtualRegister(currentInstruction[1].u.operand);            NEXT_OPCODE(op_del_by_id);        }        case op_mul: {            compileFastArith_op_mul(currentInstruction);            NEXT_OPCODE(op_mul);        }        case op_new_func: {            FuncDeclNode* func = m_codeBlock->function(currentInstruction[2].u.operand);            emitPutJITStubArgConstant(func, 1);            emitCTICall(JITStubs::cti_op_new_func);            emitPutVirtualRegister(currentInstruction[1].u.operand);            NEXT_OPCODE(op_new_func);        }        case op_call: {            compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);            NEXT_OPCODE(op_call);        }        case op_call_eval: {            compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);            NEXT_OPCODE(op_call_eval);        }        case op_construct: {            compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);            NEXT_OPCODE(op_construct);        }        case op_get_global_var: {            JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[2].u.jsCell);            move(ImmPtr(globalObject), regT0);            emitGetVariableObjectRegister(regT0, currentInstruction[3].u.operand, regT0);            emitPutVirtualRegister(currentInstruction[1].u.operand);            NEXT_OPCODE(op_get_global_var);        }        case op_put_global_var: {            emitGetVirtualRegister(currentInstruction[3].u.operand, regT1);            JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[1].u.jsCell);            move(ImmPtr(globalObject), regT0);            emitPutVariableObjectRegister(regT1, regT0, currentInstruction[2].u.operand);            NEXT_OPCODE(op_put_global_var);        }        case op_get_scoped_var: {            int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();            emitGetFromCallFrameHeader(RegisterFile::ScopeChain, regT0);            while (skip--)                loadPtr(Address(regT0, FIELD_OFFSET(ScopeChainNode, next)), regT0);            loadPtr(Address(regT0, FIELD_OFFSET(ScopeChainNode, object)), regT0);            emitGetVariableObjectRegister(regT0, currentInstruction[2].u.operand, regT0);            emitPutVirtualRegister(currentInstruction[1].u.operand);            NEXT_OPCODE(op_get_scoped_var);        }        case op_put_scoped_var: {            int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();            emitGetFromCallFrameHeader(RegisterFile::ScopeChain, regT1);            emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);            while (skip--)                loadPtr(Address(regT1, FIELD_OFFSET(ScopeChainNode, next)), regT1);            loadPtr(Address(regT1, FIELD_OFFSET(ScopeChainNode, object)), regT1);            emitPutVariableObjectRegister(regT0, regT1, currentInstruction[1].u.operand);            NEXT_OPCODE(op_put_scoped_var);        }        case op_tear_off_activation: {            emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, regT2);            emitCTICall(JITStubs::cti_op_tear_off_activation);            NEXT_OPCODE(op_tear_off_activation);        }        case op_tear_off_arguments: {            emitCTICall(JITStubs::cti_op_tear_off_arguments);            NEXT_OPCODE(op_tear_off_arguments);        }        case op_ret: {            // We could JIT generate the deref, only calling out to C when the refcount hits zero.            if (m_codeBlock->needsFullScopeChain())                emitCTICall(JITStubs::cti_op_ret_scopeChain);            ASSERT(callFrameRegister != regT1);            ASSERT(regT1 != returnValueRegister);            ASSERT(returnValueRegister != callFrameRegister);            // Return the result in %eax.            emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);            // Grab the return address.            emitGetFromCallFrameHeader(RegisterFile::ReturnPC, regT1);            // Restore our caller's "r".            emitGetFromCallFrameHeader(RegisterFile::CallerFrame, callFrameRegister);            // Return.            push(regT1);            ret();            NEXT_OPCODE(op_ret);        }        case op_new_array: {            emitPutJITStubArgConstant(currentInstruction[2].u.operand, 1);            emitPutJITStubArgConstant(currentInstruction[3].u.operand, 2);            emitCTICall(JITStubs::cti_op_new_array);            emitPutVirtualRegister(currentInstruction[1].u.operand);            NEXT_OPCODE(op_new_array);        }        case op_resolve: {            Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));            emitPutJITStubArgConstant(ident, 1);            emitCTICall(JITStubs::cti_op_resolve);            emitPutVirtualRegister(currentInstruction[1].u.operand);            NEXT_OPCODE(op_resolve);        }        case op_construct_verify: {            emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);            emitJumpSlowCaseIfNotJSCell(regT0);            loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2);            addSlowCase(branch32(NotEqual, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));            NEXT_OPCODE(op_construct_verify);        }        case op_get_by_val: {            emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);

⌨️ 快捷键说明

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