📄 bytecodegenerator.cpp
字号:
return result.first->second;}RegisterID* BytecodeGenerator::addConstant(JSValuePtr v){ pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValuePtr::encode(v), m_nextConstantIndex); if (result.second) { RegisterID& constant = m_calleeRegisters[m_nextConstantIndex]; ++m_nextConstantIndex; m_codeBlock->addConstantRegister(JSValuePtr(v)); return &constant; } return ®isterFor(result.first->second);}unsigned BytecodeGenerator::addUnexpectedConstant(JSValuePtr v){ return m_codeBlock->addUnexpectedConstant(v);}unsigned BytecodeGenerator::addRegExp(RegExp* r){ return m_codeBlock->addRegExp(r);}RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src){ emitOpcode(op_mov); instructions().append(dst->index()); instructions().append(src->index()); return dst;}RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src){ emitOpcode(opcodeID); instructions().append(dst->index()); instructions().append(src->index()); return dst;}RegisterID* BytecodeGenerator::emitPreInc(RegisterID* srcDst){ emitOpcode(op_pre_inc); instructions().append(srcDst->index()); return srcDst;}RegisterID* BytecodeGenerator::emitPreDec(RegisterID* srcDst){ emitOpcode(op_pre_dec); instructions().append(srcDst->index()); return srcDst;}RegisterID* BytecodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst){ emitOpcode(op_post_inc); instructions().append(dst->index()); instructions().append(srcDst->index()); return dst;}RegisterID* BytecodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst){ emitOpcode(op_post_dec); instructions().append(dst->index()); instructions().append(srcDst->index()); return dst;}RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types){ emitOpcode(opcodeID); instructions().append(dst->index()); instructions().append(src1->index()); instructions().append(src2->index()); if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor || opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub) { instructions().append(types.toInt()); } return dst;}RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2){ if (m_lastOpcodeID == op_typeof) { int dstIndex; int srcIndex; retrieveLastUnaryOp(dstIndex, srcIndex); if (src1->index() == dstIndex && src1->isTemporary() && m_codeBlock->isConstantRegisterIndex(src2->index()) && m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()).isString()) { const UString& value = asString(m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()))->value(); if (value == "undefined") { rewindUnaryOp(); emitOpcode(op_is_undefined); instructions().append(dst->index()); instructions().append(srcIndex); return dst; } if (value == "boolean") { rewindUnaryOp(); emitOpcode(op_is_boolean); instructions().append(dst->index()); instructions().append(srcIndex); return dst; } if (value == "number") { rewindUnaryOp(); emitOpcode(op_is_number); instructions().append(dst->index()); instructions().append(srcIndex); return dst; } if (value == "string") { rewindUnaryOp(); emitOpcode(op_is_string); instructions().append(dst->index()); instructions().append(srcIndex); return dst; } if (value == "object") { rewindUnaryOp(); emitOpcode(op_is_object); instructions().append(dst->index()); instructions().append(srcIndex); return dst; } if (value == "function") { rewindUnaryOp(); emitOpcode(op_is_function); instructions().append(dst->index()); instructions().append(srcIndex); return dst; } } } emitOpcode(opcodeID); instructions().append(dst->index()); instructions().append(src1->index()); instructions().append(src2->index()); return dst;}RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b){ return emitLoad(dst, jsBoolean(b));}RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number){ // FIXME: Our hash tables won't hold infinity, so we make a new JSNumberCell each time. // Later we can do the extra work to handle that like the other cases. if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number)) return emitLoad(dst, jsNumber(globalData(), number)); JSValuePtr& valueInMap = m_numberMap.add(number, noValue()).first->second; if (!valueInMap) valueInMap = jsNumber(globalData(), number); return emitLoad(dst, valueInMap);}RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier){ JSString*& stringInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second; if (!stringInMap) stringInMap = jsOwnedString(globalData(), identifier.ustring()); return emitLoad(dst, JSValuePtr(stringInMap));}RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValuePtr v){ RegisterID* constantID = addConstant(v); if (dst) return emitMove(dst, constantID); return constantID;}RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b){ emitOpcode(op_unexpected_load); instructions().append(dst->index()); instructions().append(addUnexpectedConstant(jsBoolean(b))); return dst;}RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d){ emitOpcode(op_unexpected_load); instructions().append(dst->index()); instructions().append(addUnexpectedConstant(jsNumber(globalData(), d))); return dst;}bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSObject*& globalObject){ // Cases where we cannot statically optimize the lookup. if (property == propertyNames().arguments || !canOptimizeNonLocals()) { stackDepth = 0; index = missingSymbolMarker(); if (shouldOptimizeLocals() && m_codeType == GlobalCode) { ScopeChainIterator iter = m_scopeChain->begin(); globalObject = *iter; ASSERT((++iter) == m_scopeChain->end()); } return false; } size_t depth = 0; ScopeChainIterator iter = m_scopeChain->begin(); ScopeChainIterator end = m_scopeChain->end(); for (; iter != end; ++iter, ++depth) { JSObject* currentScope = *iter; if (!currentScope->isVariableObject()) break; JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope); SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.ustring().rep()); // Found the property if (!entry.isNull()) { if (entry.isReadOnly() && forWriting) { stackDepth = 0; index = missingSymbolMarker(); if (++iter == end) globalObject = currentVariableObject; return false; } stackDepth = depth; index = entry.getIndex(); if (++iter == end) globalObject = currentVariableObject; return true; } if (currentVariableObject->isDynamicScope()) break; } // Can't locate the property but we're able to avoid a few lookups. stackDepth = depth; index = missingSymbolMarker(); JSObject* scope = *iter; if (++iter == end) globalObject = scope; return true;}RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype){ emitOpcode(op_instanceof); instructions().append(dst->index()); instructions().append(value->index()); instructions().append(base->index()); instructions().append(basePrototype->index()); return dst;}RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& property){ size_t depth = 0; int index = 0; JSObject* globalObject = 0; if (!findScopedProperty(property, index, depth, false, globalObject) && !globalObject) { // We can't optimise at all :-( emitOpcode(op_resolve); instructions().append(dst->index()); instructions().append(addConstant(property)); return dst; } if (globalObject) { bool forceGlobalResolve = false; if (m_regeneratingForExceptionInfo) {#if ENABLE(JIT) forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size());#else forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size());#endif } if (index != missingSymbolMarker() && !forceGlobalResolve) { // Directly index the property lookup across multiple scopes. return emitGetScopedVar(dst, depth, index, globalObject); }#if ENABLE(JIT) m_codeBlock->addGlobalResolveInfo(instructions().size());#else m_codeBlock->addGlobalResolveInstruction(instructions().size());#endif emitOpcode(op_resolve_global); instructions().append(dst->index()); instructions().append(globalObject); instructions().append(addConstant(property)); instructions().append(0); instructions().append(0); return dst; } if (index != missingSymbolMarker()) { // Directly index the property lookup across multiple scopes. return emitGetScopedVar(dst, depth, index, globalObject); } // In this case we are at least able to drop a few scope chains from the // lookup chain, although we still need to hash from then on. emitOpcode(op_resolve_skip); instructions().append(dst->index()); instructions().append(addConstant(property)); instructions().append(depth); return dst;}RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValuePtr globalObject){ if (globalObject) { emitOpcode(op_get_global_var); instructions().append(dst->index()); instructions().append(asCell(globalObject)); instructions().append(index); return dst; } emitOpcode(op_get_scoped_var); instructions().append(dst->index()); instructions().append(index); instructions().append(depth); return dst;}RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValuePtr globalObject){ if (globalObject) { emitOpcode(op_put_global_var); instructions().append(asCell(globalObject)); instructions().append(index); instructions().append(value->index()); return value; } emitOpcode(op_put_scoped_var); instructions().append(index); instructions().append(depth); instructions().append(value->index()); return value;}RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -