📄 bytecodegenerator.cpp
字号:
instructions().append(m_thisRegister.index()); } for (size_t i = 0; i < parameterCount; ++i) addParameter(parameters[i]); allocateConstants(functionBody->neededConstants());}BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock) : m_shouldEmitDebugHooks(!!debugger) , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling()) , m_scopeChain(&scopeChain) , m_symbolTable(symbolTable) , m_scopeNode(evalNode) , m_codeBlock(codeBlock) , m_thisRegister(RegisterFile::ProgramCodeThisRegister) , m_finallyDepth(0) , m_dynamicScopeDepth(0) , m_baseScopeDepth(codeBlock->baseScopeDepth()) , m_codeType(EvalCode) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) , m_emitNodeDepth(0) , m_regeneratingForExceptionInfo(false) , m_codeBlockBeingRegeneratedFrom(0){ if (m_shouldEmitDebugHooks || m_baseScopeDepth) m_codeBlock->setNeedsFullScopeChain(true); emitOpcode(op_enter); codeBlock->setGlobalData(m_globalData); m_codeBlock->m_numParameters = 1; // Allocate space for "this" allocateConstants(evalNode->neededConstants());}RegisterID* BytecodeGenerator::addParameter(const Identifier& ident){ // Parameters overwrite var declarations, but not function declarations. RegisterID* result = 0; UString::Rep* rep = ident.ustring().rep(); if (!m_functions.contains(rep)) { symbolTable().set(rep, m_nextParameterIndex); RegisterID& parameter = registerFor(m_nextParameterIndex); parameter.setIndex(m_nextParameterIndex); result = ¶meter; } // To maintain the calling convention, we have to allocate unique space for // each parameter, even if the parameter doesn't make it into the symbol table. ++m_nextParameterIndex; ++m_codeBlock->m_numParameters; return result;}RegisterID* BytecodeGenerator::registerFor(const Identifier& ident){ if (ident == propertyNames().thisIdentifier) return &m_thisRegister; if (!shouldOptimizeLocals()) return 0; SymbolTableEntry entry = symbolTable().get(ident.ustring().rep()); if (entry.isNull()) return 0; return ®isterFor(entry.getIndex());}RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident){ if (m_codeType == EvalCode) return 0; SymbolTableEntry entry = symbolTable().get(ident.ustring().rep()); ASSERT(!entry.isNull()); return ®isterFor(entry.getIndex());}bool BytecodeGenerator::isLocal(const Identifier& ident){ if (ident == propertyNames().thisIdentifier) return true; return shouldOptimizeLocals() && symbolTable().contains(ident.ustring().rep());}bool BytecodeGenerator::isLocalConstant(const Identifier& ident){ return symbolTable().get(ident.ustring().rep()).isReadOnly();}RegisterID* BytecodeGenerator::newRegister(){ m_calleeRegisters.append(m_calleeRegisters.size()); m_codeBlock->m_numCalleeRegisters = max<int>(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size()); return &m_calleeRegisters.last();}RegisterID* BytecodeGenerator::newTemporary(){ // Reclaim free register IDs. while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount()) m_calleeRegisters.removeLast(); RegisterID* result = newRegister(); result->setTemporary(); return result;}RegisterID* BytecodeGenerator::highestUsedRegister(){ size_t count = m_codeBlock->m_numCalleeRegisters; while (m_calleeRegisters.size() < count) newRegister(); return &m_calleeRegisters.last();}PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name){ // Reclaim free label scopes. while (m_labelScopes.size() && !m_labelScopes.last().refCount()) m_labelScopes.removeLast(); // Allocate new label scope. LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : 0); // Only loops have continue targets. m_labelScopes.append(scope); return &m_labelScopes.last();}PassRefPtr<Label> BytecodeGenerator::newLabel(){ // Reclaim free label IDs. while (m_labels.size() && !m_labels.last().refCount()) m_labels.removeLast(); // Allocate new label ID. m_labels.append(m_codeBlock); return &m_labels.last();}PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0){ unsigned newLabelIndex = instructions().size(); l0->setLocation(newLabelIndex); if (m_codeBlock->numberOfJumpTargets()) { unsigned lastLabelIndex = m_codeBlock->lastJumpTarget(); ASSERT(lastLabelIndex <= newLabelIndex); if (newLabelIndex == lastLabelIndex) { // Peephole optimizations have already been disabled by emitting the last label return l0; } } m_codeBlock->addJumpTarget(newLabelIndex); // This disables peephole optimizations when an instruction is a jump target m_lastOpcodeID = op_end; return l0;}void BytecodeGenerator::emitOpcode(OpcodeID opcodeID){ instructions().append(globalData()->interpreter->getOpcode(opcodeID)); m_lastOpcodeID = opcodeID;}void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index){ ASSERT(instructions().size() >= 4); size_t size = instructions().size(); dstIndex = instructions().at(size - 3).u.operand; src1Index = instructions().at(size - 2).u.operand; src2Index = instructions().at(size - 1).u.operand;}void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex){ ASSERT(instructions().size() >= 3); size_t size = instructions().size(); dstIndex = instructions().at(size - 2).u.operand; srcIndex = instructions().at(size - 1).u.operand;}void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp(){ ASSERT(instructions().size() >= 4); instructions().shrink(instructions().size() - 4);}void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp(){ ASSERT(instructions().size() >= 3); instructions().shrink(instructions().size() - 3);}PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target){ emitOpcode(target->isForward() ? op_jmp : op_loop); instructions().append(target->offsetFrom(instructions().size())); return target;}PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target){ if (m_lastOpcodeID == op_less && !target->isForward()) { int dstIndex; int src1Index; int src2Index; retrieveLastBinaryOp(dstIndex, src1Index, src2Index); if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindBinaryOp(); emitOpcode(op_loop_if_less); instructions().append(src1Index); instructions().append(src2Index); instructions().append(target->offsetFrom(instructions().size())); return target; } } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) { int dstIndex; int src1Index; int src2Index; retrieveLastBinaryOp(dstIndex, src1Index, src2Index); if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindBinaryOp(); emitOpcode(op_loop_if_lesseq); instructions().append(src1Index); instructions().append(src2Index); instructions().append(target->offsetFrom(instructions().size())); return target; } } else if (m_lastOpcodeID == op_eq_null && target->isForward()) { int dstIndex; int srcIndex; retrieveLastUnaryOp(dstIndex, srcIndex); if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); emitOpcode(op_jeq_null); instructions().append(srcIndex); instructions().append(target->offsetFrom(instructions().size())); return target; } } else if (m_lastOpcodeID == op_neq_null && target->isForward()) { int dstIndex; int srcIndex; retrieveLastUnaryOp(dstIndex, srcIndex); if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); emitOpcode(op_jneq_null); instructions().append(srcIndex); instructions().append(target->offsetFrom(instructions().size())); return target; } } emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true); instructions().append(cond->index()); instructions().append(target->offsetFrom(instructions().size())); return target;}PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target){ ASSERT(target->isForward()); if (m_lastOpcodeID == op_less) { int dstIndex; int src1Index; int src2Index; retrieveLastBinaryOp(dstIndex, src1Index, src2Index); if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindBinaryOp(); emitOpcode(op_jnless); instructions().append(src1Index); instructions().append(src2Index); instructions().append(target->offsetFrom(instructions().size())); return target; } } else if (m_lastOpcodeID == op_not) { int dstIndex; int srcIndex; retrieveLastUnaryOp(dstIndex, srcIndex); if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); emitOpcode(op_jtrue); instructions().append(srcIndex); instructions().append(target->offsetFrom(instructions().size())); return target; } } else if (m_lastOpcodeID == op_eq_null) { int dstIndex; int srcIndex; retrieveLastUnaryOp(dstIndex, srcIndex); if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); emitOpcode(op_jneq_null); instructions().append(srcIndex); instructions().append(target->offsetFrom(instructions().size())); return target; } } else if (m_lastOpcodeID == op_neq_null) { int dstIndex; int srcIndex; retrieveLastUnaryOp(dstIndex, srcIndex); if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); emitOpcode(op_jeq_null); instructions().append(srcIndex); instructions().append(target->offsetFrom(instructions().size())); return target; } } emitOpcode(op_jfalse); instructions().append(cond->index()); instructions().append(target->offsetFrom(instructions().size())); return target;}unsigned BytecodeGenerator::addConstant(FuncDeclNode* n){ // No need to explicitly unique function body nodes -- they're unique already. return m_codeBlock->addFunction(n);}unsigned BytecodeGenerator::addConstant(FuncExprNode* n){ // No need to explicitly unique function expression nodes -- they're unique already. return m_codeBlock->addFunctionExpression(n);}unsigned BytecodeGenerator::addConstant(const Identifier& ident){ UString::Rep* rep = ident.ustring().rep(); pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers()); if (result.second) // new entry m_codeBlock->addIdentifier(Identifier(m_globalData, rep));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -