📄 codeblock.cpp
字号:
int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); break; } case op_jmp_scopes: { int scopeDelta = (++it)->u.operand; int offset = (++it)->u.operand; printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset)); break; } case op_catch: { int r0 = (++it)->u.operand; printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str()); break; } case op_throw: { int r0 = (++it)->u.operand; printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str()); break; } case op_new_error: { int r0 = (++it)->u.operand; int errorType = (++it)->u.operand; int k0 = (++it)->u.operand; printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, unexpectedConstant(k0)).c_str()); break; } case op_jsr: { int retAddrDst = (++it)->u.operand; int offset = (++it)->u.operand; printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset)); break; } case op_sret: { int retAddrSrc = (++it)->u.operand; printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str()); break; } case op_debug: { int debugHookID = (++it)->u.operand; int firstLine = (++it)->u.operand; int lastLine = (++it)->u.operand; printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine); break; } case op_profile_will_call: { int function = (++it)->u.operand; printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str()); break; } case op_profile_did_call: { int function = (++it)->u.operand; printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str()); break; } case op_end: { int r0 = (++it)->u.operand; printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str()); break; } }}#endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)#if DUMP_CODE_BLOCK_STATISTICSstatic HashSet<CodeBlock*> liveCodeBlockSet;#endif#define FOR_EACH_MEMBER_VECTOR(macro) \ macro(instructions) \ macro(globalResolveInfos) \ macro(structureStubInfos) \ macro(callLinkInfos) \ macro(linkedCallerList) \ macro(identifiers) \ macro(functionExpressions) \ macro(constantRegisters)#define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \ macro(regexps) \ macro(functions) \ macro(unexpectedConstants) \ macro(exceptionHandlers) \ macro(immediateSwitchJumpTables) \ macro(characterSwitchJumpTables) \ macro(stringSwitchJumpTables) \ macro(functionRegisterInfos)#define FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(macro) \ macro(expressionInfo) \ macro(lineInfo) \ macro(getByIdExceptionInfo) \ macro(pcVector)template<typename T>static size_t sizeInBytes(const Vector<T>& vector){ return vector.capacity() * sizeof(T);}void CodeBlock::dumpStatistics(){#if DUMP_CODE_BLOCK_STATISTICS #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0; FOR_EACH_MEMBER_VECTOR(DEFINE_VARS) FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS) FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(DEFINE_VARS) #undef DEFINE_VARS // Non-vector data members size_t evalCodeCacheIsNotEmpty = 0; size_t symbolTableIsNotEmpty = 0; size_t symbolTableTotalSize = 0; size_t hasExceptionInfo = 0; size_t hasRareData = 0; size_t isFunctionCode = 0; size_t isGlobalCode = 0; size_t isEvalCode = 0; HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end(); for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) { CodeBlock* codeBlock = *it; #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); } FOR_EACH_MEMBER_VECTOR(GET_STATS) #undef GET_STATS if (!codeBlock->m_symbolTable.isEmpty()) { symbolTableIsNotEmpty++; symbolTableTotalSize += (codeBlock->m_symbolTable.capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType))); } if (codeBlock->m_exceptionInfo) { hasExceptionInfo++; #define GET_STATS(name) if (!codeBlock->m_exceptionInfo->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_exceptionInfo->m_##name); } FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_STATS) #undef GET_STATS } if (codeBlock->m_rareData) { hasRareData++; #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); } FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS) #undef GET_STATS if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty()) evalCodeCacheIsNotEmpty++; } switch (codeBlock->codeType()) { case FunctionCode: ++isFunctionCode; break; case GlobalCode: ++isGlobalCode; break; case EvalCode: ++isEvalCode; break; } } size_t totalSize = 0; #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize; FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE) FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE) FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_TOTAL_SIZE) #undef GET_TOTAL_SIZE totalSize += symbolTableTotalSize; totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock)); printf("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size()); printf("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock)); printf("Size of all CodeBlocks: %zu\n", totalSize); printf("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size()); printf("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size()); printf("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size()); printf("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size()); printf("Number of CodeBlocks with exception info: %zu (%.3f%%)\n", hasExceptionInfo, static_cast<double>(hasExceptionInfo) * 100.0 / liveCodeBlockSet.size()); printf("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size()); #define PRINT_STATS(name) printf("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); printf("Size of all " #name ": %zu\n", name##TotalSize); FOR_EACH_MEMBER_VECTOR(PRINT_STATS) FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS) FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(PRINT_STATS) #undef PRINT_STATS printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty); printf("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty); printf("Size of all symbolTables: %zu\n", symbolTableTotalSize);#else printf("Dumping CodeBlock statistics is not enabled.\n");#endif}CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) : m_numCalleeRegisters(0) , m_numConstants(0) , m_numVars(0) , m_numParameters(0) , m_ownerNode(ownerNode) , m_globalData(0)#ifndef NDEBUG , m_instructionCount(0)#endif , m_needsFullScopeChain(ownerNode->needsActivation()) , m_usesEval(ownerNode->usesEval()) , m_isNumericCompareFunction(false) , m_codeType(codeType) , m_source(sourceProvider) , m_sourceOffset(sourceOffset) , m_exceptionInfo(new ExceptionInfo){ ASSERT(m_source);#if DUMP_CODE_BLOCK_STATISTICS liveCodeBlockSet.add(this);#endif}CodeBlock::~CodeBlock(){#if !ENABLE(JIT) for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i) derefStructures(&m_instructions[m_globalResolveInstructions[i]]); for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) derefStructures(&m_instructions[m_propertyAccessInstructions[i]]);#else for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) { if (m_globalResolveInfos[i].structure) m_globalResolveInfos[i].structure->deref(); } for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) m_structureStubInfos[i].deref(); for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) { CallLinkInfo* callLinkInfo = &m_callLinkInfos[i]; if (callLinkInfo->isLinked()) callLinkInfo->callee->removeCaller(callLinkInfo); } unlinkCallers();#endif#if DUMP_CODE_BLOCK_STATISTICS liveCodeBlockSet.remove(this);#endif}#if ENABLE(JIT) void CodeBlock::unlinkCallers(){ size_t size = m_linkedCallerList.size(); for (size_t i = 0; i < size; ++i) { CallLinkInfo* currentCaller = m_linkedCallerList[i]; JIT::unlinkCall(currentCaller); currentCaller->setUnlinked(); } m_linkedCallerList.clear();}#endifvoid CodeBlock::derefStructures(Instruction* vPC) const{ Interpreter* interpreter = m_globalData->interpreter; if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { vPC[4].u.structure->deref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { vPC[4].u.structure->deref(); vPC[5].u.structure->deref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { vPC[4].u.structure->deref(); vPC[5].u.structureChain->deref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { vPC[4].u.structure->deref(); vPC[5].u.structure->deref(); vPC[6].u.structureChain->deref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) { vPC[4].u.structure->deref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) { if(vPC[4].u.structure) vPC[4].u.structure->deref(); return; } if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list)) || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) { PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures; polymorphicStructures->derefStructures(vPC[5].u.operand); delete polymorphicStructures; return; } // These instructions don't ref their Structures. ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));}void CodeBlock::refStructures(Instruction* vPC) const{ Interpreter* interpreter = m_globalData->interpreter; if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { vPC[4].u.structure->ref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { vPC[4].u.structure->ref(); vPC[5].u.structure->ref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { vPC[4].u.structure->ref(); vPC[5].u.structureChain->ref(); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -