diff --git a/assembler/assembly-emitter.cpp b/assembler/assembly-emitter.cpp index e906cb5406b2870333bc8d912e0a15d024b3c545..def9ae2661d4cd185baa10b689105c5504ba8617 100644 --- a/assembler/assembly-emitter.cpp +++ b/assembler/assembly-emitter.cpp @@ -592,9 +592,9 @@ AnnotationItem *AsmEmitter::CreateAnnotationItem(ItemContainer *container, const if (value_type == Value::Type::ARRAY && !value->GetAsArray()->GetValues().empty()) { auto array_element_type = value->GetAsArray()->GetComponentType(); - tag_type = Value::GetArrayTypeAsChar(array_element_type); + tag_type = static_cast(Value::GetArrayTypeAsChar(array_element_type)); } else { - tag_type = Value::GetTypeAsChar(value_type); + tag_type = static_cast(Value::GetTypeAsChar(value_type)); } ASSERT(tag_type != '0'); @@ -1409,8 +1409,8 @@ bool AsmEmitter::EmitFunctions(ItemContainer *items, const Program &program, code->SetNumVregs(func.regs_num); code->SetNumArgs(func.GetParamsNum()); - size_t num_ins = - std::count_if(func.ins.begin(), func.ins.end(), [](auto it) { return it.opcode != Opcode::INVALID; }); + size_t num_ins = static_cast( + std::count_if(func.ins.begin(), func.ins.end(), [](auto it) { return it.opcode != Opcode::INVALID; })); code->SetNumInstructions(num_ins); auto *bytes = code->GetInstructions(); @@ -1618,12 +1618,12 @@ void Function::EmitLocalVariable(panda_file::LineNumberProgramItem *program, Ite size_t Function::GetLineNumber(size_t i) const { - return static_cast(ins[i].ins_debug.line_number); + return ins[i].ins_debug.line_number; } size_t Function::GetColumnNumber(size_t i) const { - return static_cast(ins[i].ins_debug.column_number); + return ins[i].ins_debug.column_number; } void Function::EmitNumber(panda_file::LineNumberProgramItem *program, std::vector *constant_pool, @@ -1646,9 +1646,9 @@ void Function::EmitNumber(panda_file::LineNumberProgramItem *program, std::vecto void Function::EmitLineNumber(panda_file::LineNumberProgramItem *program, std::vector *constant_pool, int32_t &prev_line_number, uint32_t &pc_inc, size_t instruction_number) const { - int32_t line_inc = GetLineNumber(instruction_number) - prev_line_number; + int32_t line_inc = static_cast(GetLineNumber(instruction_number)) - prev_line_number; if (line_inc) { - prev_line_number = GetLineNumber(instruction_number); + prev_line_number = static_cast(GetLineNumber(instruction_number)); EmitNumber(program, constant_pool, pc_inc, line_inc); pc_inc = 0; } @@ -1657,7 +1657,7 @@ void Function::EmitLineNumber(panda_file::LineNumberProgramItem *program, std::v void Function::EmitColumnNumber(panda_file::LineNumberProgramItem *program, std::vector *constant_pool, int32_t &prev_column_number, uint32_t &pc_inc, size_t instruction_number) const { - int32_t cn = GetColumnNumber(instruction_number); + auto cn = static_cast(GetColumnNumber(instruction_number)); if (cn != prev_column_number) { program->EmitColumn(constant_pool, pc_inc, cn); pc_inc = 0; @@ -1677,8 +1677,8 @@ void Function::BuildLineNumberProgram(panda_file::DebugInfoItem *debug_item, con } uint32_t pc_inc = 0; - int32_t prev_line_number = GetLineNumber(0); - int32_t prev_column_number = GetColumnNumber(0); + auto prev_line_number = static_cast(GetLineNumber(0)); + auto prev_column_number = -1; BytecodeInstruction bi(bytecode.data()); debug_item->SetLineNumber(static_cast(prev_line_number)); diff --git a/assembler/assembly-parser.cpp b/assembler/assembly-parser.cpp index bd1af98bfee0091d5de6b9e66c6e76e3e3ea3625..aa8c8be0995597b9ea968daebb0788681b2c255e 100644 --- a/assembler/assembly-parser.cpp +++ b/assembler/assembly-parser.cpp @@ -349,12 +349,13 @@ void Parser::ParseResetFunctionLabelsAndParams() for (const auto &t : context_.function_arguments_lists) { curr_func_ = &(program_.function_table.at(t.first)); - curr_func_->regs_num = curr_func_->value_of_first_param + 1; + curr_func_->regs_num = static_cast(curr_func_->value_of_first_param + 1); for (const auto &v : t.second) { if (!curr_func_->ins.empty() && curr_func_->ins.size() >= v.first && !curr_func_->ins[v.first - 1].regs.empty()) { - curr_func_->ins[v.first - 1].regs[v.second] += curr_func_->value_of_first_param + 1; + curr_func_->ins[v.first - 1].regs[v.second] += + static_cast(curr_func_->value_of_first_param + 1); size_t max_reg_number = (1 << curr_func_->ins[v.first - 1].MaxRegEncodingWidth()); if (curr_func_->ins[v.first - 1].regs[v.second] >= max_reg_number) { const auto &debug = curr_func_->ins[v.first - 1].ins_debug; @@ -393,7 +394,7 @@ void Parser::ParseResetFunctionTable() bool is_initobj = insn_it->opcode == Opcode::INITOBJ || insn_it->opcode == Opcode::INITOBJ_SHORT || insn_it->opcode == Opcode::INITOBJ_RANGE; - auto diff = is_initobj ? 0 : 1; + size_t diff = is_initobj ? 0 : 1; if (insn_it->OperandListLength() - diff < program_.function_table.at(insn_it->ids[0]).GetParamsNum()) { auto insn_idx = std::distance(k.second.ins.begin(), insn_it); const auto &debug = curr_func_->ins[insn_idx].ins_debug; @@ -924,16 +925,16 @@ bool Parser::ParseOperandVreg() if (p[0] == 'v') { p.remove_prefix(1); - int64_t number = ToNumber(p); + int64_t number = static_cast(ToNumber(p)); if (number > *(context_.max_value_of_reg)) { *(context_.max_value_of_reg) = number; } - curr_ins_->regs.push_back(number); + curr_ins_->regs.push_back(static_cast(number)); } else if (p[0] == 'a') { p.remove_prefix(1); - curr_ins_->regs.push_back(ToNumber(p)); + curr_ins_->regs.push_back(static_cast(ToNumber(p))); context_.function_arguments_list->emplace_back(context_.ins_number, curr_ins_->regs.size() - 1); } diff --git a/assembler/assembly-parser.h b/assembler/assembly-parser.h index b3179bde365b117a2b31026c6edb13877ec617d8..725a3906a9329c54ecbe626f46fa10272e8ff320 100644 --- a/assembler/assembly-parser.h +++ b/assembler/assembly-parser.h @@ -104,15 +104,15 @@ private: int8_t shift = 0, int token_shift = 0, const std::string &add_mess = "") const { return Error(mess, line_stric_, err, add_mess, - context_.tokens[context_.number + token_shift - 1].bound_left + shift, - context_.tokens[context_.number + token_shift - 1].bound_right, - context_.tokens[context_.number + token_shift - 1].whole_line); + context_.tokens[static_cast(context_.number) + token_shift - 1].bound_left + shift, + context_.tokens[static_cast(context_.number) + token_shift - 1].bound_right, + context_.tokens[static_cast(context_.number) + token_shift - 1].whole_line); } inline void GetWarning(const std::string &mess = "", Error::ErrorType err = Error::ErrorType::ERR_NONE, int8_t shift = 0, const std::string &add_mess = "") { - war_.emplace_back(mess, line_stric_, err, add_mess, context_.tokens[context_.number - 1].bound_left + shift, + war_.emplace_back(mess, line_stric_, err, add_mess, context_.tokens[context_.number - 1].bound_left + static_cast(shift), context_.tokens[context_.number - 1].bound_right, context_.tokens[context_.number - 1].whole_line, Error::ErrorClass::WARNING); } diff --git a/assembler/lexer.cpp b/assembler/lexer.cpp index 40664f1ae1d3c63f16ba81f35a483a4196b61b63..cb8e4fd27b09dd61bf960658e93e28389a0776fd 100644 --- a/assembler/lexer.cpp +++ b/assembler/lexer.cpp @@ -345,13 +345,15 @@ void Lexer::LexPreprocess() // Searching for comment marker located outside of the string literals. inside_str_lit = curr_line_->buffer.size() > 0 && curr_line_->buffer[0] == '\"'; - cmt_pos = -1; - while ((cmt_pos = curr_line_->buffer.find_first_of("\"#", cmt_pos + 1)) != std::string::npos) { - if (cmt_pos != 0 && curr_line_->buffer[cmt_pos - 1] != '\\' && curr_line_->buffer[cmt_pos] == '\"') { - inside_str_lit = !inside_str_lit; - } else if (curr_line_->buffer[cmt_pos] == PARSE_COMMENT_MARKER && !inside_str_lit) { - break; - } + cmt_pos = curr_line_->buffer.find_first_of("\"#", 0); + if (cmt_pos != std::string::npos) { + do { + if (cmt_pos != 0 && curr_line_->buffer[cmt_pos - 1] != '\\' && curr_line_->buffer[cmt_pos] == '\"') { + inside_str_lit = !inside_str_lit; + } else if (curr_line_->buffer[cmt_pos] == PARSE_COMMENT_MARKER && !inside_str_lit) { + break; + } + } while ((cmt_pos = curr_line_->buffer.find_first_of("\"#", cmt_pos + 1)) != std::string::npos); } if (cmt_pos != std::string::npos) { diff --git a/assembler/utils/number-utils.h b/assembler/utils/number-utils.h index f2d1e3a3ebb13e01a426fcc7943ff000d035d7ed..05c422e62ab7c314677a691ae2199387a9ffd64c 100644 --- a/assembler/utils/number-utils.h +++ b/assembler/utils/number-utils.h @@ -196,7 +196,7 @@ inline size_t ToNumber(std::string_view p) for (char i : p) { if (isdigit(i) != 0) { - sum = sum * DEC_BASE + (i - '0'); + sum = sum * DEC_BASE + static_cast(i - '0'); } else { return MAX_DWORD; } diff --git a/libpandabase/os/mem.h b/libpandabase/os/mem.h index 47451fbe7480d58db0aba6edd1fc592eae24ea11..301f915c508f0682fd6867b129aed0bf94799b53 100644 --- a/libpandabase/os/mem.h +++ b/libpandabase/os/mem.h @@ -167,6 +167,7 @@ public: size_ = other.size_; deleter_ = other.deleter_; other.ptr_ = nullptr; + other.deleter_ = nullptr; } MapPtr &operator=(MapPtr &&other) noexcept @@ -176,6 +177,7 @@ public: size_ = other.size_; deleter_ = other.deleter_; other.ptr_ = nullptr; + other.deleter_ = nullptr; return *this; } @@ -229,6 +231,9 @@ public: */ ~MapPtr() { + if (ptr_ == nullptr) { + return; + } uintptr_t addr = reinterpret_cast(ptr_) - page_offset_; // LINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) size_t size = size_ + page_offset_; diff --git a/libpandabase/os/unix/futex/mutex.cpp b/libpandabase/os/unix/futex/mutex.cpp index 444e02e920a26caf7d4d19bb93b2782ea3256815..d3da1d38f2b800cf1001293bb828b79a95ddb5de 100644 --- a/libpandabase/os/unix/futex/mutex.cpp +++ b/libpandabase/os/unix/futex/mutex.cpp @@ -440,8 +440,8 @@ const int64_t NANOSECONDS_PER_SEC = 1000000000; struct timespec ConvertTime(uint64_t ms, uint64_t ns) { struct timespec time = {0, 0}; - time_t seconds = ms / MILLISECONDS_PER_SEC; - time_t nanoseconds = (ms % MILLISECONDS_PER_SEC) * NANOSECONDS_PER_MILLISEC + ns; + auto seconds = static_cast(ms / MILLISECONDS_PER_SEC); + auto nanoseconds = static_cast((ms % MILLISECONDS_PER_SEC) * NANOSECONDS_PER_MILLISEC + ns); time.tv_sec += seconds; time.tv_nsec += nanoseconds; if (time.tv_nsec >= NANOSECONDS_PER_SEC) { diff --git a/libpandabase/os/unix/mem.cpp b/libpandabase/os/unix/mem.cpp index 20d414996a671a295692f8aabaf27669cd580dad..0cf5584d3ce5023e54da67b1c08cbd0d16ee23da 100644 --- a/libpandabase/os/unix/mem.cpp +++ b/libpandabase/os/unix/mem.cpp @@ -99,7 +99,7 @@ std::optional MakeMemReadOnly(void *mem, size_t size) uintptr_t AlignDownToPageSize(uintptr_t addr) { - const size_t SYS_PAGE_SIZE = sysconf(_SC_PAGESIZE); + const auto SYS_PAGE_SIZE = static_cast(sysconf(_SC_PAGESIZE)); addr &= ~(SYS_PAGE_SIZE - 1); return addr; } diff --git a/libpandabase/os/unix/mutex.cpp b/libpandabase/os/unix/mutex.cpp index af762a6b01529a84dc96817cb5fb5b8d01dde9c8..11ebafe18eb8d9117f211865e48f5431f38095a5 100644 --- a/libpandabase/os/unix/mutex.cpp +++ b/libpandabase/os/unix/mutex.cpp @@ -175,8 +175,8 @@ struct timespec ConvertTime(uint64_t ms, uint64_t ns, bool is_absolute) if (!is_absolute) { clock_gettime(CLOCK_REALTIME, &abs_time); } - time_t seconds = ms / MILLISECONDS_PER_SEC; - time_t nanoseconds = (ms % MILLISECONDS_PER_SEC) * NANOSECONDS_PER_MILLISEC + ns; + auto seconds = static_cast(ms / MILLISECONDS_PER_SEC); + auto nanoseconds = static_cast((ms % MILLISECONDS_PER_SEC) * NANOSECONDS_PER_MILLISEC + ns); abs_time.tv_sec += seconds; abs_time.tv_nsec += nanoseconds; if (abs_time.tv_nsec >= NANOSECONDS_PER_SEC) { diff --git a/libpandabase/os/unix/pipe.cpp b/libpandabase/os/unix/pipe.cpp index e1dc374e399299be433b1c163d9a8bcea93a4884..d933681be9f56ae4c1c55bd261f42528d7827e88 100644 --- a/libpandabase/os/unix/pipe.cpp +++ b/libpandabase/os/unix/pipe.cpp @@ -47,7 +47,7 @@ int SetFdNonblocking(const UniqueFd &fd) if (res < 0) { flags = 0; } else { - flags = res; + flags = static_cast(res); } // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-signed-bitwise) return fcntl(fd.Get(), F_SETFL, flags | O_NONBLOCK); @@ -91,7 +91,7 @@ Expected WaitForEvent(const UniqueFd *handles, size_t size, Event std::vector pollfds(size); for (size_t i = 0; i < size; i++) { pollfds[i].fd = handles[i].Get(); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) - pollfds[i].events = poll_events; + pollfds[i].events = static_cast(poll_events); } while (true) { diff --git a/libpandabase/os/unix/sighooklib/sighook.cpp b/libpandabase/os/unix/sighooklib/sighook.cpp index 2c83a8412810e1fd2782b366799c08f9aa17b32a..9cec549f1aa0320acfcccb4d18ae78a3036cb55f 100644 --- a/libpandabase/os/unix/sighooklib/sighook.cpp +++ b/libpandabase/os/unix/sighooklib/sighook.cpp @@ -207,7 +207,7 @@ static std::array signal_hooks; void SignalHook::CallOldAction(int signo, siginfo_t *siginfo, void *ucontext_raw) { - size_t handler_flags = signal_hooks[signo].old_action_.sa_flags; + auto handler_flags = static_cast(signal_hooks[signo].old_action_.sa_flags); sigset_t mask = signal_hooks[signo].old_action_.sa_mask; real_sigprocmask(SIG_SETMASK, &mask, nullptr); @@ -265,7 +265,7 @@ void SignalHook::Handler(int signo, siginfo_t *siginfo, void *ucontext_raw) } // Call user handler - size_t handler_flags = signal_hooks[signo].user_action_.sa_flags; + auto handler_flags = static_cast(signal_hooks[signo].user_action_.sa_flags); auto *ucontext = static_cast(ucontext_raw); sigset_t mask; sigemptyset(&mask); diff --git a/libpandabase/utils/dfx.cpp b/libpandabase/utils/dfx.cpp index 236e8131f753f8220a962c5a410b0e10688441fe..c825f1ea3bef0be1c83e3216094c143fc1c670ef 100644 --- a/libpandabase/utils/dfx.cpp +++ b/libpandabase/utils/dfx.cpp @@ -72,7 +72,7 @@ void DfxController::ResetOptionValueFromString(const std::string &s) last_pos = s.find_first_not_of(';', pos); pos = s.find(';', last_pos); std::string option_str = arg.substr(0, arg.find(':')); - uint8_t value = std::stoi(arg.substr(arg.find(':') + 1)); + uint8_t value = static_cast(std::stoi(arg.substr(arg.find(':') + 1))); auto dfx_option = DfxOptionHandler::DfxOptionFromString(option_str); if (dfx_option != DfxOptionHandler::END_FLAG) { DfxController::SetOptionValue(dfx_option, value); diff --git a/libpandabase/utils/json_parser.cpp b/libpandabase/utils/json_parser.cpp index f7fa903fe7a03aaaf0f7d1c7b3ba5a9d16a4aa58..9c380ffbbdb46841d751d3faf6fb39a83bd568cb 100644 --- a/libpandabase/utils/json_parser.cpp +++ b/libpandabase/utils/json_parser.cpp @@ -211,7 +211,7 @@ bool JsonObject::Parser::GetValue() // Save source string of parsed value: auto pos_end = istream_.tellg(); - size_t size = pos_end - pos_start; + auto size = static_cast(pos_end - pos_start); string_temp_.resize(size, '\0'); istream_.seekg(pos_start); istream_.read(&string_temp_[0], size); diff --git a/libpandabase/utils/leb128.h b/libpandabase/utils/leb128.h index e7af4806050ecf700ad57ea0bbd5e34642fa5879..bdcbaa481c66a2f411e024a5ad038357127f0cb0 100644 --- a/libpandabase/utils/leb128.h +++ b/libpandabase/utils/leb128.h @@ -121,8 +121,7 @@ inline size_t EncodeSigned(T data, uint8_t *out) bool more = true; while (more) { - // NOLINTNEXTLINE(hicpp-signed-bitwise) - uint8_t byte = data & PAYLOAD_MASK; + auto byte = static_cast(static_cast(data) & PAYLOAD_MASK); // NOLINTNEXTLINE(hicpp-signed-bitwise) data >>= PAYLOAD_WIDTH; more = !((data == 0 && (byte & SIGN_BIT) == 0) || (data == -1 && (byte & SIGN_BIT) != 0)); diff --git a/libpandabase/utils/murmur3_hash.h b/libpandabase/utils/murmur3_hash.h index 774e480da17509dba6820331f4025c2c695ffcac..91b48efcc1546a38eb1d534a36c3330579401225 100644 --- a/libpandabase/utils/murmur3_hash.h +++ b/libpandabase/utils/murmur3_hash.h @@ -121,7 +121,7 @@ private: // Get ((uint8_t*)tail)[i - 1]: uintptr_t block_pointer = tail + sizeof(uint8_t) * (i - 1); uint8_t block = *reinterpret_cast(block_pointer); - uint32_t temp = (block << (TAIL_SHIFT * (i - 1U))); + uint32_t temp = static_cast(block) << (TAIL_SHIFT * (i - 1U)); k1 ^= temp; if (i == 1) { k1 = Rotl(k1, TAIL_LAST_SHIFT); @@ -180,7 +180,7 @@ private: uint32_t k1 = 0; for (size_t i = tail_len; i > 0; i--) { uint8_t block = memblock[i - 1U]; - uint32_t temp = (block << (TAIL_SHIFT * (i - 1U))); + uint32_t temp = static_cast(block) << (TAIL_SHIFT * (i - 1U)); k1 ^= temp; if (i == 1) { k1 = Rotl(k1, TAIL_LAST_SHIFT); diff --git a/libpandabase/utils/type_converter.cpp b/libpandabase/utils/type_converter.cpp index addce3f6054d6ad0398bd83acf0c2819563463dc..2e567d1cb2d731006752c4d706362a17ffd30cf5 100644 --- a/libpandabase/utils/type_converter.cpp +++ b/libpandabase/utils/type_converter.cpp @@ -84,7 +84,7 @@ bool operator!=(const ValueUnit &lhs, const ValueUnit &rhs) std::ostream &operator<<(std::ostream &os, const ValueUnit &element) { if (element.GetValue().index() == 0U) { - os << std::fixed << std::setprecision(static_cast(element.GetPrecision())) << element.GetDoubleValue() + os << std::fixed << std::setprecision(static_cast(element.GetPrecision())) << element.GetDoubleValue() << std::setprecision(-1); } else { os << element.GetUint64Value(); diff --git a/libpandabase/utils/utf.cpp b/libpandabase/utils/utf.cpp index 8214beb39bf7aef6200a50315f089cfc1c7b1a19..2f98d4319c263b8453300ced8b889af46fe3de4b 100644 --- a/libpandabase/utils/utf.cpp +++ b/libpandabase/utils/utf.cpp @@ -261,7 +261,7 @@ int CompareMUtf8ToMUtf8(const uint8_t *mutf8_1, const uint8_t *mutf8_2) auto [c1p1, c1p2] = SplitUtf16Pair(c1); auto [c2p1, c2p2] = SplitUtf16Pair(c2); - int result = c1p1 - c2p1; + auto result = static_cast(c1p1 - c2p1); if (result != 0) { return result; } @@ -308,7 +308,7 @@ int CompareUtf8ToUtf8(const uint8_t *utf8_1, size_t utf8_1_length, const uint8_t auto [c1p1, c1p2] = SplitUtf16Pair(c1); auto [c2p1, c2p2] = SplitUtf16Pair(c2); - int result = c1p1 - c2p1; + auto result = static_cast(c1p1 - c2p1); if (result != 0) { return result; } diff --git a/libpandafile/annotation_data_accessor.cpp b/libpandafile/annotation_data_accessor.cpp index 36fe1766342dd2b84b75274f6fca6518fe7a8165..9a9465f78de83bae3dadd7b668941867b12ef26a 100644 --- a/libpandafile/annotation_data_accessor.cpp +++ b/libpandafile/annotation_data_accessor.cpp @@ -44,7 +44,7 @@ AnnotationDataAccessor::Tag AnnotationDataAccessor::GetTag(size_t i) const { ASSERT(i < count_); auto sp = elements_tags_.SubSpan(i * TYPE_TAG_SIZE); - char item = helpers::Read(&sp); + auto item = static_cast(helpers::Read(&sp)); return AnnotationDataAccessor::Tag(item); } diff --git a/libpandafile/bytecode_emitter.cpp b/libpandafile/bytecode_emitter.cpp index 1c6afb4031d1a88feaebdcbdbcd21286191b917c..1bfe191477a305b25b941734696aef31cace98f9 100644 --- a/libpandafile/bytecode_emitter.cpp +++ b/libpandafile/bytecode_emitter.cpp @@ -245,11 +245,11 @@ void BytecodeEmitter::Jcmpz(BytecodeInstruction::Opcode opcode, const Label &lab */ BytecodeEmitter::ErrorCode BytecodeEmitter::ReserveSpaceForOffsets() { - int32_t bias = 0; + uint32_t bias = 0; std::map new_branches; auto it = branches_.begin(); while (it != branches_.end()) { - uint32_t insn_pc = it->first + bias; + auto insn_pc = static_cast(it->first + bias); auto label = it->second; auto opcode = static_cast(bytecode_[insn_pc]); @@ -375,7 +375,7 @@ BytecodeEmitter::ErrorCode BytecodeEmitter::UpdateBranches() return ErrorCode::SUCCESS; } -void BytecodeEmitter::UpdateLabelTargets(uint32_t pc, int32_t bias) +void BytecodeEmitter::UpdateLabelTargets(uint32_t pc, size_t bias) { pc_list_.push_front(pc); Label fake(pc_list_.begin()); diff --git a/libpandafile/bytecode_emitter.h b/libpandafile/bytecode_emitter.h index 3a2b535c9847ba94618df2d72e2bffab67de192a..d2f8a68169eba6b96dafe8c1113ffd1a7a5b9996 100644 --- a/libpandafile/bytecode_emitter.h +++ b/libpandafile/bytecode_emitter.h @@ -109,7 +109,7 @@ private: ErrorCode DoReserveSpaceForOffset(BytecodeInstruction::Opcode opcode, uint32_t insn_pc, BitImmSize expected_imm_size, size_t *extra_bytes_ptr, uint32_t *target_ptr); ErrorCode UpdateBranches(); - void UpdateLabelTargets(uint32_t pc, int32_t bias); + void UpdateLabelTargets(uint32_t pc, size_t bias); int32_t EstimateMaxDistance(uint32_t insn_pc, uint32_t target_pc, uint32_t bias) const; ErrorCode CheckLabels() const; diff --git a/libpandafile/debug_info_extractor.cpp b/libpandafile/debug_info_extractor.cpp index 6afd595c1baf8cb197a6c317081419a352eb4fb9..74a25390e47a4c6a11b03544a017aced44d80f97 100644 --- a/libpandafile/debug_info_extractor.cpp +++ b/libpandafile/debug_info_extractor.cpp @@ -222,8 +222,8 @@ private: { ASSERT(static_cast(opcode) >= LineNumberProgramItem::OPCODE_BASE); - auto adjust_opcode = static_cast(opcode) - LineNumberProgramItem::OPCODE_BASE; - uint32_t pc_offset = adjust_opcode / LineNumberProgramItem::LINE_RANGE; + auto adjust_opcode = static_cast(opcode - LineNumberProgramItem::OPCODE_BASE); + auto pc_offset = static_cast(adjust_opcode / LineNumberProgramItem::LINE_RANGE); int32_t line_offset = adjust_opcode % LineNumberProgramItem::LINE_RANGE + LineNumberProgramItem::LINE_BASE; state_.AdvancePc(pc_offset); state_.AdvanceLine(line_offset); diff --git a/libpandafile/line_program_state.h b/libpandafile/line_program_state.h index 1dc9fe33ef10eb70413a668e7ec825e15b137966..63214f4c0ee29b49993477e8dc8138e7ebc749a4 100644 --- a/libpandafile/line_program_state.h +++ b/libpandafile/line_program_state.h @@ -34,7 +34,7 @@ public: void AdvanceLine(int32_t v) { - line_ += v; + line_ += static_cast(v); } void AdvancePc(uint32_t v) @@ -44,7 +44,7 @@ public: void SetColumn(int32_t c) { - column_ = c; + column_ = static_cast(c); } size_t GetColumn() const diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index eef472101927ba6bfe6dcaad262d677f542829c5..6106d910a453834337dfc1a267642f0efdd07e4d 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -138,8 +138,6 @@ ohos_static_library("libarkruntime_static") { "object_accessor.cpp", "object_header.cpp", "panda_vm.cpp", - "profilesaver/profile_dump_info.cpp", - "profilesaver/profile_saver.cpp", "runtime.cpp", "runtime_helpers.cpp", "signal_handler.cpp", diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index ad8b7a4f099735c3bbfeb7dd221f6cb6e5acfa34..ae03cce3506bf102c4526159038ff335e2dfe78b 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -128,8 +128,6 @@ set(SOURCES object_accessor.cpp arch/asm_support.cpp signal_handler.cpp - profilesaver/profile_saver.cpp - profilesaver/profile_dump_info.cpp runtime_helpers.cpp handle_scope.cpp file_manager.cpp diff --git a/runtime/include/runtime_options.h b/runtime/include/runtime_options.h index 69eb18a83f96a053c1ff85aa51b613ac2f68919a..b581969845bea31335fe9dcdfa57a008d7004839 100644 --- a/runtime/include/runtime_options.h +++ b/runtime/include/runtime_options.h @@ -38,7 +38,6 @@ class CFrameTest; class StackWalkerTest; class PandaRunner; class CompilerQueueTest; -class ProfileSaverTest; class DynObjectsTest; class JSObjectTest; class JSFunctionTest; @@ -312,7 +311,6 @@ private: friend class panda::test::PandaRunner; friend class verifier::test::VerifierTest; friend class panda::Logger; - friend class test::ProfileSaverTest; friend class panda::test::DynObjectsTest; friend class panda::test::JSObjectTest; friend class panda::test::JSFunctionTest; diff --git a/runtime/profilesaver/profile_dump_info.cpp b/runtime/profilesaver/profile_dump_info.cpp deleted file mode 100644 index 9b70c7a644da9fc05fc1bb6ad9b042dfe6956a59..0000000000000000000000000000000000000000 --- a/runtime/profilesaver/profile_dump_info.cpp +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "runtime/profilesaver/profile_dump_info.h" - -#include -#include -#include - -#include -#include -#include - -#include "libpandabase/os/unix/failure_retry.h" -#include "trace/trace.h" - -#ifndef PATH_MAX -#define PATH_MAX 1024 -#endif - -namespace panda { -static constexpr size_t K_BITS_PER_BYTE = 8; - -static constexpr size_t K_LINE_HEADER_SIZE = 3 * sizeof(uint32_t) + sizeof(uint16_t); -static constexpr size_t K_METHOD_BYTES = 4; -static constexpr size_t K_CLASS_BYTES = 4; - -const uint8_t ProfileDumpInfo::kProfileMagic[] = {'p', 'r', 'o', 'f', '\0'}; // NOLINT -const uint8_t ProfileDumpInfo::kProfileVersion[] = {'0', '1', '\0'}; // NOLINT - -static constexpr uint16_t K_MAX_FILE_KEY_LENGTH = PATH_MAX; // NOLINT - -static bool WriteBuffer(int fd, const uint8_t *buffer, size_t byte_count) -{ // NOLINT - while (byte_count > 0) { - int bytes_written = write(fd, buffer, byte_count); // real place to write - if (bytes_written == -1) { - return false; - } - byte_count -= bytes_written; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - buffer += bytes_written; - } - return true; -} - -static void AddStringToBuffer(PandaVector *buffer, const PandaString &value) -{ // NOLINT - buffer->insert(buffer->end(), value.begin(), value.end()); -} - -template -static void AddUintToBuffer(PandaVector *buffer, T value) -{ - for (size_t i = 0; i < sizeof(T); i++) { - buffer->push_back((value >> (i * K_BITS_PER_BYTE)) & 0xff); // NOLINT - } -} - -/* - * Tests for EOF by trying to read 1 byte from the descriptor. - * Returns: - * 0 if the descriptor is at the EOF, - * -1 if there was an IO error - * 1 if the descriptor has more content to read - */ -// NOLINTNEXTLINE(readability-identifier-naming) -static int testEOF(int fd) -{ - // NOLINTNEXTLINE(modernize-avoid-c-arrays) - uint8_t buffer[1]; - return read(fd, buffer, 1); -} - -int64_t GetFileSizeBytes(const PandaString &filename) -{ - struct stat stat_buf { - }; - int rc = stat(filename.c_str(), &stat_buf); - return rc == 0 ? stat_buf.st_size : -1; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::SerializerBuffer::FillFromFd(int fd, const PandaString &source, - PandaString *error) -{ - size_t byte_count = ptr_end_ - ptr_current_; - uint8_t *buffer = ptr_current_; - while (byte_count > 0) { - int bytes_read = read(fd, buffer, byte_count); - if (bytes_read == 0) { // NOLINT - *error += "Profile EOF reached prematurely for " + source; - return PROFILE_LOAD_BAD_DATA; - } else if (bytes_read < 0) { // NOLINT - *error += "Profile IO error for " + source + ConvertToString(os::Error(errno).ToString()); - return PROFILE_LOAD_IO_ERROR; - } - byte_count -= bytes_read; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - buffer += bytes_read; - } - return PROFILE_LOAD_SUCCESS; -} - -template -T ProfileDumpInfo::SerializerBuffer::ReadUintAndAdvance() -{ - static_assert(std::is_unsigned::value, "Type is not unsigned"); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - ASSERT(ptr_current_ + sizeof(T) <= ptr_end_); - T value = 0; - for (size_t i = 0; i < sizeof(T); i++) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - value += ptr_current_[i] << (i * K_BITS_PER_BYTE); - } - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - ptr_current_ += sizeof(T); - return value; -} - -bool ProfileDumpInfo::SerializerBuffer::CompareAndAdvance(const uint8_t *data, size_t data_size) -{ - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (ptr_current_ + data_size > ptr_end_) { - return false; - } - if (memcmp(ptr_current_, data, data_size) == 0) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - ptr_current_ += data_size; - return true; - } - return false; -} - -bool ProfileDumpInfo::MergeWith(const ProfileDumpInfo &other) -{ - for (const auto &other_it : other.dump_info_) { - auto info_it = dump_info_.find(other_it.first); - if ((info_it != dump_info_.end()) && (info_it->second.checksum != other_it.second.checksum)) { - LOG(INFO, RUNTIME) << "info_it->second.checksum" << info_it->second.checksum; - LOG(INFO, RUNTIME) << "other_it->second.checksum" << other_it.second.checksum; - LOG(INFO, RUNTIME) << "Checksum mismatch" << other_it.first; - return false; - } - } - LOG(INFO, RUNTIME) << "All checksums match"; - - for (const auto &other_it : other.dump_info_) { - const PandaString &other_profile_location = other_it.first; - const ProfileLineData &other_profile_data = other_it.second; - auto info_it = dump_info_.find(other_profile_location); - if (info_it == dump_info_.end()) { - auto ret = - dump_info_.insert(std::make_pair(other_profile_location, ProfileLineData(other_profile_data.checksum))); - ASSERT(ret.second); - info_it = ret.first; - } - info_it->second.method_wrapper_set.insert(other_profile_data.method_wrapper_set.begin(), - other_profile_data.method_wrapper_set.end()); - info_it->second.class_wrapper_set.insert(other_profile_data.class_wrapper_set.begin(), - other_profile_data.class_wrapper_set.end()); - } - return true; -} - -bool ProfileDumpInfo::AddMethodsAndClasses(const PandaVector &methods, - const PandaSet &resolved_classes) -{ - for (const ExtractedMethod &method : methods) { - if (!AddMethodWrapper(ConvertToString(method.panda_file_->GetFilename()), - method.panda_file_->GetHeader()->checksum, MethodWrapper(method.file_id_.GetOffset()))) { - return false; - } - } - - for (const ExtractedResolvedClasses &class_resolved : resolved_classes) { - if (!AddResolvedClasses(class_resolved)) { - return false; - } - } - return true; -} - -uint64_t ProfileDumpInfo::GetNumberOfMethods() const -{ - uint64_t total = 0; - for (const auto &it : dump_info_) { - total += it.second.method_wrapper_set.size(); - } - return total; -} - -uint64_t ProfileDumpInfo::GetNumberOfResolvedClasses() const -{ - uint64_t total = 0; - for (const auto &it : dump_info_) { - total += it.second.class_wrapper_set.size(); - } - return total; -} - -bool ProfileDumpInfo::ContainsMethod(const ExtractedMethod &method_ref) const -{ - auto info_it = dump_info_.find(ConvertToString(method_ref.panda_file_->GetFilename())); - if (info_it != dump_info_.end()) { - if (method_ref.panda_file_->GetHeader()->checksum != info_it->second.checksum) { - return false; - } - const PandaSet &methods = info_it->second.method_wrapper_set; - return methods.find(MethodWrapper(method_ref.file_id_.GetOffset())) != methods.end(); - } - return false; -} - -bool ProfileDumpInfo::ContainsClass(const panda_file::File &pandafile, uint32_t class_def_idx) const -{ - auto info_it = dump_info_.find(ConvertToString(pandafile.GetFilename())); - if (info_it != dump_info_.end()) { - if (pandafile.GetHeader()->checksum != info_it->second.checksum) { - return false; - } - const PandaSet &classes = info_it->second.class_wrapper_set; - return classes.find(ClassWrapper(class_def_idx)) != classes.end(); - } - return false; -} - -bool ProfileDumpInfo::AddMethodWrapper(const PandaString &panda_file_location, uint32_t checksum, - const ProfileDumpInfo::MethodWrapper &method_to_add) -{ - ProfileLineData *const DATA = GetOrAddProfileLineData(panda_file_location, checksum); - if (DATA == nullptr) { - return false; - } - DATA->method_wrapper_set.insert(method_to_add); - return true; -} - -bool ProfileDumpInfo::AddClassWrapper(const PandaString &panda_file_location, uint32_t checksum, - const ProfileDumpInfo::ClassWrapper &class_to_add) -{ - ProfileLineData *const DATA = GetOrAddProfileLineData(panda_file_location, checksum); - if (DATA == nullptr) { - return false; - } - DATA->class_wrapper_set.insert(class_to_add); - return true; -} - -bool ProfileDumpInfo::AddResolvedClasses(const ExtractedResolvedClasses &classes) -{ // NOLINT(readability-identifier-naming) - const PandaString panda_file_location = classes.GetPandaFileLocation(); // NOLINT(readability-identifier-naming) - const uint32_t checksum = classes.GetPandaFileChecksum(); // NOLINT(readability-identifier-naming) - ProfileLineData *const DATA = GetOrAddProfileLineData(panda_file_location, checksum); - if (DATA == nullptr) { - return false; - } - for (auto const &i : classes.GetClasses()) { - DATA->class_wrapper_set.insert(ClassWrapper(i)); - } - return true; -} - -ProfileDumpInfo::ProfileLineData *ProfileDumpInfo::GetOrAddProfileLineData(const PandaString &panda_file_location, - uint32_t checksum) -{ - auto info_it = dump_info_.find(panda_file_location); - if (info_it == dump_info_.end()) { - auto ret = dump_info_.insert(std::make_pair(panda_file_location, ProfileLineData(checksum))); - ASSERT(ret.second); - info_it = ret.first; - } - if (info_it->second.checksum != checksum) { - LOG(INFO, RUNTIME) << "Checksum mismatch" << panda_file_location; - return nullptr; - } - return &(info_it->second); -} - -bool ProfileDumpInfo::Save(int fd) -{ - ASSERT(fd >= 0); - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - - static constexpr size_t K_MAX_BUFFER_SIZE = 8 * 1024; - PandaVector buffer; // each element 1 byte - - WriteBuffer(fd, kProfileMagic, sizeof(kProfileMagic)); - WriteBuffer(fd, kProfileVersion, sizeof(kProfileVersion)); - AddUintToBuffer(&buffer, static_cast(dump_info_.size())); - - for (const auto &it : dump_info_) { - if (buffer.size() > K_MAX_BUFFER_SIZE) { - if (!WriteBuffer(fd, buffer.data(), buffer.size())) { - return false; - } - buffer.clear(); - } - const PandaString &file_location = it.first; - const ProfileLineData &file_data = it.second; - - if (file_location.size() >= K_MAX_FILE_KEY_LENGTH) { - LOG(INFO, RUNTIME) << "PandaFileKey exceeds allocated limit"; - return false; - } - - size_t required_capacity = buffer.size() + K_LINE_HEADER_SIZE + file_location.size() + - K_METHOD_BYTES * file_data.method_wrapper_set.size() + - K_CLASS_BYTES * file_data.class_wrapper_set.size(); - buffer.reserve(required_capacity); - - ASSERT(file_location.size() <= std::numeric_limits::max()); - ASSERT(file_data.method_wrapper_set.size() <= std::numeric_limits::max()); - ASSERT(file_data.class_wrapper_set.size() <= std::numeric_limits::max()); - - AddUintToBuffer(&buffer, static_cast(file_location.size())); - AddUintToBuffer(&buffer, static_cast(file_data.method_wrapper_set.size())); - AddUintToBuffer(&buffer, static_cast(file_data.class_wrapper_set.size())); - AddUintToBuffer(&buffer, file_data.checksum); - AddStringToBuffer(&buffer, file_location); - - if (UNLIKELY(file_data.empty())) { - LOG(INFO, RUNTIME) << "EMPTY FILE DATA, WERIED!"; - } - - for (auto method_it : file_data.method_wrapper_set) { - AddUintToBuffer(&buffer, method_it.method_id_); - } - for (auto class_it : file_data.class_wrapper_set) { - AddUintToBuffer(&buffer, class_it.class_id_); - } - ASSERT(required_capacity == buffer.size()); - } - return WriteBuffer(fd, buffer.data(), buffer.size()); -} - -bool ProfileDumpInfo::Load(int fd) -{ - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - PandaString error; - ProfileLoadSatus status = LoadInternal(fd, &error); - - if (status == PROFILE_LOAD_SUCCESS) { - return true; - } - LOG(INFO, RUNTIME) << "Error when reading profile " << error; - return false; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::LoadInternal(int fd, PandaString *error) -{ - ASSERT(fd >= 0); - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - - struct stat stat_buffer { - }; - if (fstat(fd, &stat_buffer) != 0) { - return PROFILE_LOAD_IO_ERROR; - } - - if (stat_buffer.st_size == 0) { - LOG(INFO, RUNTIME) << "empty file"; - return PROFILE_LOAD_EMPTYFILE; - } - - uint32_t number_of_lines; - ProfileLoadSatus status = ReadProfileHeader(fd, &number_of_lines, error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - LOG(INFO, RUNTIME) << "number of profile items = " << number_of_lines; - - while (number_of_lines > 0) { - ProfileLineHeader line_header; - status = ReadProfileLineHeader(fd, &line_header, error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - - status = ReadProfileLine(fd, line_header, error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - number_of_lines--; - } - - int result = testEOF(fd); - if (result == 0) { - return PROFILE_LOAD_SUCCESS; - } - - if (result < 0) { - return PROFILE_LOAD_IO_ERROR; - } - - *error = "Unexpected content in the profile file"; - return PROFILE_LOAD_BAD_DATA; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::ReadProfileHeader(int fd, uint32_t *number_of_lines, - PandaString *error) -{ - const size_t K_MAGIC_VERSION_SIZE = sizeof(kProfileMagic) + sizeof(kProfileVersion) + sizeof(uint32_t); - - SerializerBuffer safe_buffer(K_MAGIC_VERSION_SIZE); - - ProfileLoadSatus status = safe_buffer.FillFromFd(fd, "ReadProfileHeader", error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - - if (!safe_buffer.CompareAndAdvance(kProfileMagic, sizeof(kProfileMagic))) { - *error = "Profile missing magic"; - return PROFILE_LOAD_VERSION_MISMATCH; - } - if (!safe_buffer.CompareAndAdvance(kProfileVersion, sizeof(kProfileVersion))) { - *error = "Profile version mismatch"; - return PROFILE_LOAD_VERSION_MISMATCH; - } - - *number_of_lines = safe_buffer.ReadUintAndAdvance(); - return PROFILE_LOAD_SUCCESS; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::ReadProfileLineHeader(int fd, ProfileLineHeader *line_header, - PandaString *error) -{ - SerializerBuffer header_buffer(K_LINE_HEADER_SIZE); - ProfileLoadSatus status = header_buffer.FillFromFd(fd, "ReadProfileLineHeader", error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - - auto panda_location_size = header_buffer.ReadUintAndAdvance(); // max chars in location, 4096 = 2 ^ 12 - line_header->method_set_size = header_buffer.ReadUintAndAdvance(); - line_header->class_set_size = header_buffer.ReadUintAndAdvance(); - line_header->checksum = header_buffer.ReadUintAndAdvance(); - - if (panda_location_size == 0 || panda_location_size > K_MAX_FILE_KEY_LENGTH) { - *error = "PandaFileKey has an invalid size: " + std::to_string(panda_location_size); - return PROFILE_LOAD_BAD_DATA; - } - - SerializerBuffer location_buffer(panda_location_size); - // Read the binary data: location string - status = location_buffer.FillFromFd(fd, "ReadProfileLineHeader", error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - line_header->panda_file_location.assign(reinterpret_cast(location_buffer.Get()), panda_location_size); - return PROFILE_LOAD_SUCCESS; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::ReadProfileLine(int fd, const ProfileLineHeader &line_header, - PandaString *error) -{ - static constexpr uint32_t K_MAX_NUMBER_OF_ENTRIES_TO_READ = 8000; // ~8 kb - uint32_t methods_left_to_read = line_header.method_set_size; - uint32_t classes_left_to_read = line_header.class_set_size; - - while ((methods_left_to_read > 0) || (classes_left_to_read > 0)) { - uint32_t methods_to_read = std::min(K_MAX_NUMBER_OF_ENTRIES_TO_READ, methods_left_to_read); - uint32_t max_classes_to_read = K_MAX_NUMBER_OF_ENTRIES_TO_READ - methods_to_read; // >=0 - uint32_t classes_to_read = std::min(max_classes_to_read, classes_left_to_read); - - size_t line_size = K_METHOD_BYTES * methods_to_read + K_CLASS_BYTES * classes_to_read; - SerializerBuffer line_buffer(line_size); - - ProfileLoadSatus status = line_buffer.FillFromFd(fd, "ReadProfileLine", error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - if (!ProcessLine(line_buffer, methods_to_read, classes_to_read, line_header.checksum, - line_header.panda_file_location)) { - *error = "Error when reading profile file line"; - return PROFILE_LOAD_BAD_DATA; - } - - methods_left_to_read -= methods_to_read; - classes_left_to_read -= classes_to_read; - } - return PROFILE_LOAD_SUCCESS; -} - -// NOLINTNEXTLINE(google-runtime-references) -bool ProfileDumpInfo::ProcessLine(SerializerBuffer &line_buffer, uint32_t method_set_size, uint32_t class_set_size, - uint32_t checksum, const PandaString &panda_file_location) -{ - for (uint32_t i = 0; i < method_set_size; i++) { - // NB! Read the method info from buffer... - auto method_idx = line_buffer.ReadUintAndAdvance(); - if (!AddMethodWrapper(panda_file_location, checksum, MethodWrapper(method_idx))) { - return false; - } - } - - for (uint32_t i = 0; i < class_set_size; i++) { - auto class_def_idx = line_buffer.ReadUintAndAdvance(); - if (!AddClassWrapper(panda_file_location, checksum, ClassWrapper(class_def_idx))) { - return false; - } - } - return true; -} - -bool ProfileDumpInfo::MergeAndSave(const PandaString &filename, uint64_t *bytes_written, bool force) -{ - // NB! we using READWRITE mode to leave the creation job to framework layer. - panda::os::unix::file::File myfile = panda::os::file::Open(filename, panda::os::file::Mode::READWRITE); - if (!myfile.IsValid()) { - LOG(ERROR, RUNTIME) << "Cannot open the profile file" << filename; - return false; - } - panda::os::file::FileHolder fholder(myfile); - int fd = myfile.GetFd(); - - LOG(INFO, RUNTIME) << " Step3.2: starting merging ***"; - PandaString error; - ProfileDumpInfo file_dump_info; - ProfileLoadSatus status = file_dump_info.LoadInternal(fd, &error); - if (status == PROFILE_LOAD_SUCCESS || status == PROFILE_LOAD_EMPTYFILE) { - if (MergeWith(file_dump_info)) { - if (dump_info_ == file_dump_info.dump_info_) { - if (bytes_written != nullptr) { - *bytes_written = 0; - } - LOG(INFO, RUNTIME) << " No Saving as no change byte_written = 0"; - if (status != PROFILE_LOAD_EMPTYFILE) { - return true; - } - } - } else { - LOG(INFO, RUNTIME) << " No Saving as Could not merge previous profile data from file " << filename; - if (!force) { - return false; - } - } - } else if (force && ((status == PROFILE_LOAD_VERSION_MISMATCH) || (status == PROFILE_LOAD_BAD_DATA))) { - LOG(INFO, RUNTIME) << " Clearing bad or mismatch version profile data from file " << filename << ": " << error; - } else { - LOG(INFO, RUNTIME) << " No Saving as Could not load profile data from file " << filename << ": " << error; - return false; - } - - LOG(INFO, RUNTIME) << " Step3.3: starting Saving ***"; - LOG(INFO, RUNTIME) << " clear file data firstly"; - if (!myfile.ClearData()) { - LOG(INFO, RUNTIME) << "Could not clear profile file: " << filename; - return false; - } - - bool result = Save(fd); - if (result) { - if (bytes_written != nullptr) { - LOG(INFO, RUNTIME) << " Profile Saver Bingo! and bytes written = " << bytes_written; - *bytes_written = GetFileSizeBytes(filename); - } - } else { - LOG(ERROR, RUNTIME) << "Failed to save profile info to " << filename; - } - return result; -} - -} // namespace panda diff --git a/runtime/profilesaver/profile_dump_info.h b/runtime/profilesaver/profile_dump_info.h deleted file mode 100644 index 61f244718859d7acdfa37fdc07a4f9d1e5c7e8fb..0000000000000000000000000000000000000000 --- a/runtime/profilesaver/profile_dump_info.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PANDA_RUNTIME_PROFILESAVER_PROFILE_DUMP_INFO_H_ -#define PANDA_RUNTIME_PROFILESAVER_PROFILE_DUMP_INFO_H_ - -#include -#include -#include -#include -#include - -#include "libpandabase/utils/logger.h" -#include "libpandafile/file.h" -#include "runtime/include/mem/panda_containers.h" -#include "runtime/include/mem/panda_smart_pointers.h" -#include "runtime/include/mem/panda_string.h" - -// NB! suppose that, panda file can always provide such profile file format data! -// NB! we use serializer saving way which means the profile file is just binary file! -// profile header -// magic -// version -// checksum?(ommit) -// #lines -// Line1: -// profileline header -// file location -// #method -// #class -// checksum -// methods index/id(#method) -// class index/id(#class) -// LineN: -// ... - -namespace panda { - -/* - * Any newly added information, we have to change the following info naturely, especially - * ExtractedResolvedClasses - */ -struct ExtractedMethod { - ExtractedMethod(const panda_file::File *file, panda_file::File::EntityId file_id) - : panda_file_(file), file_id_(file_id) - { - } - const panda_file::File *panda_file_; // NOLINT(misc-non-private-member-variables-in-classes) - panda_file::File::EntityId file_id_; // NOLINT(misc-non-private-member-variables-in-classes) -}; - -struct ExtractedResolvedClasses { -public: - // NOLINTNEXTLINE(modernize-pass-by-value) - ExtractedResolvedClasses(const PandaString &location, uint32_t checksum) - : panda_file_location_(location), panda_file_checksum_(checksum) - { - } - - int Compare(const ExtractedResolvedClasses &other) const - { - if (panda_file_checksum_ != other.panda_file_checksum_) { - return static_cast(panda_file_checksum_ - other.panda_file_checksum_); - } - return panda_file_location_.compare(other.panda_file_location_); - } - - template - void AddClasses(InputIt begin, InputIt end) const - { - classes_.insert(begin, end); - } - - void AddClass(uint32_t classindex) const - { - classes_.insert(classindex); - } - - // NOLINTNEXTLINE(readability-const-return-type) - const PandaString GetPandaFileLocation() const - { - return panda_file_location_; - } - - uint32_t GetPandaFileChecksum() const - { - return panda_file_checksum_; - } - - const PandaUnorderedSet &GetClasses() const - { - return classes_; - } - -private: - const PandaString panda_file_location_; // NOLINT(readability-identifier-naming) - const uint32_t panda_file_checksum_; // NOLINT(readability-identifier-naming) - // Array of resolved class def indexes. we leave this as extention - mutable PandaUnorderedSet classes_; -}; - -// we define this for PandaSet find() function -inline bool operator<(const ExtractedResolvedClasses &a, const ExtractedResolvedClasses &b) -{ - return a.Compare(b) < 0; -} - -class ProfileDumpInfo { -public: - // Content of profile header - static const uint8_t kProfileMagic[]; // NOLINT(modernize-avoid-c-arrays, readability-identifier-naming) - static const uint8_t kProfileVersion[]; // NOLINT(modernize-avoid-c-arrays, readability-identifier-naming) - - /* - * Saves the profile data to the given file descriptor. - */ - bool Save(int fd); - - /* - * Loads profile information from the given file descriptor. - */ - bool Load(int fd); - - /* - * Merge the data from another ProfileDumpInfo into the current object. - */ - bool MergeWith(const ProfileDumpInfo &other); - - /* - * Add the given methods and classes to the current profile object - */ - bool AddMethodsAndClasses(const PandaVector &methods, - const PandaSet &resolved_classes); - - /* - * Loads and merges profile information from the given file into the current cache - * object and tries to save it back to disk. - * - * If `force` is true then the save will be forced regardless of bad data or mismatched version. - */ - bool MergeAndSave(const PandaString &filename, uint64_t *bytes_written, bool force); - - /* - * Returns the number of methods that were profiled. - */ - uint64_t GetNumberOfMethods() const; - - /* - * Returns the number of resolved classes that were profiled. - */ - uint64_t GetNumberOfResolvedClasses() const; - - /* - * Returns true if the method reference is present in the profiling info. - */ - bool ContainsMethod(const ExtractedMethod &method_ref) const; - - /* - * Returns true if the class is present in the profiling info. - */ - bool ContainsClass(const panda_file::File &pandafile, uint32_t class_def_idx) const; - -private: - enum ProfileLoadSatus { - PROFILE_LOAD_IO_ERROR, - PROFILE_LOAD_VERSION_MISMATCH, - PROFILE_LOAD_BAD_DATA, - PROFILE_LOAD_EMPTYFILE, - PROFILE_LOAD_SUCCESS - }; - - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) - struct ProfileLineHeader { - PandaString panda_file_location; - uint32_t method_set_size; - uint32_t class_set_size; - uint32_t checksum; - }; - - // A helper structure to make sure we don't read past our buffers in the loops. - struct SerializerBuffer { - public: - explicit SerializerBuffer(size_t size) - { - // NOLINTNEXTLINE(modernize-avoid-c-arrays) - storage_ = MakePandaUnique(size); - ptr_current_ = storage_.get(); - ptr_end_ = ptr_current_ + size; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic - } - - ProfileLoadSatus FillFromFd(int fd, const PandaString &source, PandaString *error); - - template - T ReadUintAndAdvance(); - - bool CompareAndAdvance(const uint8_t *data, size_t data_size); - - uint8_t *Get() - { - return storage_.get(); - } - - private: - PandaUniquePtr storage_; // NOLINT(modernize-avoid-c-arrays) - uint8_t *ptr_current_; - uint8_t *ptr_end_; - }; - - struct MethodWrapper { - explicit MethodWrapper(uint32_t index) : method_id_(index) {} - uint32_t method_id_; // NOLINT(misc-non-private-member-variables-in-classes) - - bool operator==(const MethodWrapper &other) const - { - return method_id_ == other.method_id_; - } - - bool operator<(const MethodWrapper &other) const - { - return method_id_ < other.method_id_; - } - }; - - struct ClassWrapper { - explicit ClassWrapper(uint32_t index) : class_id_(index) {} - uint32_t class_id_; // NOLINT(misc-non-private-member-variables-in-classes) - - bool operator==(const ClassWrapper &other) const - { - return class_id_ == other.class_id_; - } - - bool operator<(const ClassWrapper &other) const - { - return class_id_ < other.class_id_; - } - }; - - struct ProfileLineData { - explicit ProfileLineData(uint32_t file_checksum) : checksum(file_checksum) {} - uint32_t checksum; // NOLINT(misc-non-private-member-variables-in-classes) - PandaSet method_wrapper_set; // NOLINT(misc-non-private-member-variables-in-classes) - PandaSet class_wrapper_set; // NOLINT(misc-non-private-member-variables-in-classes) - - bool operator==(const ProfileLineData &other) const - { - return checksum == other.checksum && method_wrapper_set == other.method_wrapper_set && - class_wrapper_set == other.class_wrapper_set; - } - - // NOLINTNEXTLINE(readability-identifier-naming) - bool empty() const - { - return method_wrapper_set.empty() && class_wrapper_set.empty(); - } - }; - - ProfileLoadSatus LoadInternal(int fd, PandaString *error); - ProfileLoadSatus ReadProfileHeader(int fd, uint32_t *number_of_lines, PandaString *error); - ProfileLoadSatus ReadProfileLineHeader(int fd, ProfileLineHeader *line_header, PandaString *error); - ProfileLoadSatus ReadProfileLine(int fd, const ProfileLineHeader &line_header, PandaString *error); - // NOLINTNEXTLINE(google-runtime-references) - bool ProcessLine(SerializerBuffer &line_buffer, uint32_t method_set_size, uint32_t class_set_size, - uint32_t checksum, const PandaString &panda_file_location); - - bool AddMethodWrapper(const PandaString &panda_file_location, uint32_t checksum, - const MethodWrapper &method_to_add); - bool AddClassWrapper(const PandaString &panda_file_location, uint32_t checksum, const ClassWrapper &class_to_add); - bool AddResolvedClasses(const ExtractedResolvedClasses &classes); - ProfileLineData *GetOrAddProfileLineData(const PandaString &panda_file_location, uint32_t checksum); - - PandaMap dump_info_; -}; - -} // namespace panda - -#endif // PANDA_RUNTIME_PROFILESAVER_PROFILE_DUMP_INFO_H_ diff --git a/runtime/profilesaver/profile_saver.cpp b/runtime/profilesaver/profile_saver.cpp deleted file mode 100644 index 97c02313580e7c7a0fd6e63177f05b6c5247de3b..0000000000000000000000000000000000000000 --- a/runtime/profilesaver/profile_saver.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "runtime/profilesaver/profile_saver.h" - -#include -#include -#include - -#include "runtime/include/class_linker.h" -#include "runtime/include/runtime.h" -#include "runtime/jit/jit.h" -#include "trace/trace.h" - -namespace panda { - -ProfileSaver *ProfileSaver::instance = nullptr; -// NOLINTNEXTLINE(fuchsia-statically-constructed-objects) -std::thread ProfileSaver::profiler_saver_daemon_thread; - -static bool CheckLocationForCompilation(const PandaString &location) -{ - return !location.empty(); -} - -// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -ProfileSaver::ProfileSaver(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_dir) - : shutting_down_(false) -{ - AddTrackedLocations(output_filename, code_paths, app_dir); -} - -// NB! it is the caller's responsibility to pass suitable output_filename, code_paths as well as app_data_dir. -void ProfileSaver::AddTrackedLocations(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_data_dir) -{ - auto it = tracked_pandafile_base_locations_.find(output_filename); - if (it == tracked_pandafile_base_locations_.end()) { - tracked_pandafile_base_locations_.insert( - std::make_pair(output_filename, PandaSet(code_paths.begin(), code_paths.end()))); - if (!app_data_dir.empty()) { - app_data_dirs_.insert(app_data_dir); - } - } else { - if (UNLIKELY(app_data_dirs_.count(app_data_dir) <= 0)) { - LOG(INFO, RUNTIME) << "Cannot find app dir, bad output filename"; - return; - } - it->second.insert(code_paths.begin(), code_paths.end()); - } -} - -void ProfileSaver::Start(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_data_dir) -{ - if (Runtime::GetCurrent() == nullptr) { - LOG(ERROR, RUNTIME) << "Runtime is nullptr"; - return; - } - - if (!Runtime::GetCurrent()->SaveProfileInfo()) { - LOG(ERROR, RUNTIME) << "ProfileSaver is forbidden"; - return; - } - - if (output_filename.empty()) { - LOG(ERROR, RUNTIME) << "Invalid output filename"; - return; - } - - PandaVector code_paths_to_profile; - for (const PandaString &location : code_paths) { - if (CheckLocationForCompilation(location)) { - code_paths_to_profile.push_back(location); - } - } - - if (code_paths_to_profile.empty()) { - LOG(INFO, RUNTIME) << "No code paths should be profiled."; - return; - } - - if (UNLIKELY(instance != nullptr)) { - LOG(INFO, RUNTIME) << "Profile Saver Singleton already exists"; - instance->AddTrackedLocations(output_filename, code_paths_to_profile, app_data_dir); - return; - } - - LOG(INFO, RUNTIME) << "Starting dumping profile saver output file" << output_filename; - - instance = new ProfileSaver(output_filename, code_paths_to_profile, app_data_dir); - profiler_saver_daemon_thread = std::thread(ProfileSaver::RunProfileSaverThread, reinterpret_cast(instance)); -} - -void ProfileSaver::Stop(bool dump_info) -{ - { - os::memory::LockHolder lock(profile_saver_lock_); - - if (instance == nullptr) { - LOG(ERROR, RUNTIME) << "Tried to stop a profile saver which was not started"; - return; - } - - if (instance->shutting_down_) { - LOG(ERROR, RUNTIME) << "Tried to stop the profile saver twice"; - return; - } - - instance->shutting_down_ = true; - - if (dump_info) { - instance->DumpInfo(); - } - } - - // Wait for the saver thread to stop. - // NB! we must release profile_saver_lock_ here. - profiler_saver_daemon_thread.join(); - - // Kill the singleton ... - delete instance; - instance = nullptr; -} - -bool ProfileSaver::IsStarted() -{ - return instance != nullptr; -} - -void ProfileSaver::DumpInfo() -{ - LOG(INFO, RUNTIME) << "ProfileSaver stopped" << '\n'; -} - -void *ProfileSaver::RunProfileSaverThread(void *arg) -{ - // NOLINTNEXTLINE(hicpp-use-auto, modernize-use-auto) - ProfileSaver *profile_saver = reinterpret_cast(arg); - profile_saver->Run(); - - LOG(INFO, RUNTIME) << "Profile saver shutdown"; - return nullptr; -} - -void ProfileSaver::Run() -{ - while (!ShuttingDown()) { - LOG(INFO, RUNTIME) << "Step1: Time Sleeping >>>>>>> "; - uint32_t sleepytime = Runtime::GetOptions().GetProfilesaverSleepingTimeMs(); - constexpr uint32_t TIME_SECONDS_IN_MS = 1000; - for (int i = 0; i < static_cast(sleepytime / TIME_SECONDS_IN_MS); ++i) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - if (ShuttingDown()) { - break; - } - } - - LOG(INFO, RUNTIME) << "Step2: tranverse the resolved class and methods >>>>>>> "; - TranverseAndCacheResolvedClassAndMethods(); - - LOG(INFO, RUNTIME) << "Step3: merge current profile file and save it back >>>>>>> "; - MergeAndDumpProfileData(); - } -} - -bool ProfileSaver::ShuttingDown() -{ - os::memory::LockHolder lock(profile_saver_lock_); - return shutting_down_; -} - -void ProfileSaver::TranverseAndCacheResolvedClassAndMethods() -{ - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - PandaSet resolved_classes; - PandaVector methods; - auto call_back = [&resolved_classes, &methods](Class *klass) -> bool { - const panda_file::File *pandafile = klass->GetPandaFile(); - panda_file::File::EntityId classfieldid = klass->GetFileId(); - - if (pandafile == nullptr) { - LOG(INFO, RUNTIME) << "panda file is nullptr"; - return false; - } - LOG(INFO, RUNTIME) << " pandafile name = " << pandafile->GetFilename() - << " classname = " << klass->GetName(); - - Span tmp_methods = klass->GetMethods(); - LOG(INFO, RUNTIME) << " methods size = " << tmp_methods.size(); - for (int i = 0; i < static_cast(tmp_methods.Size()); ++i) { - Method &method = tmp_methods[i]; - if (!method.IsNative()) { - if (method.GetHotnessCounter() >= K_MIN_PROFILE_THRESHOLD) { - ASSERT(method.GetPandaFile() != nullptr); - LOG(INFO, RUNTIME) << " method pandafile name = " << method.GetPandaFile()->GetFilename(); - methods.emplace_back(ExtractedMethod(method.GetPandaFile(), method.GetFileId())); - } - } - } - - ExtractedResolvedClasses tmp_resolved_classes(ConvertToString(pandafile->GetFilename()), - pandafile->GetHeader()->checksum); - LOG(INFO, RUNTIME) << " Add class " << klass->GetName(); - auto it = resolved_classes.find(tmp_resolved_classes); - if (it != resolved_classes.end()) { - it->AddClass(classfieldid.GetOffset()); - } else { - tmp_resolved_classes.AddClass(classfieldid.GetOffset()); - resolved_classes.insert(tmp_resolved_classes); - } - - return true; - }; - - // NB: classliner == nullptr - if (Runtime::GetCurrent()->GetClassLinker() == nullptr) { - LOG(INFO, RUNTIME) << "classliner is nullptr"; - return; - } - - LOG(INFO, RUNTIME) << " Step2.1: tranverse the resolved class and methods"; - Runtime::GetCurrent()->GetClassLinker()->EnumerateClasses(call_back); - LOG(INFO, RUNTIME) << " Step2.2: starting tracking all the pandafile locations and flush the cache"; - - for (const auto &it : tracked_pandafile_base_locations_) { - const PandaString &filename = it.first; - const PandaSet &locations = it.second; - - PandaSet resolved_classes_for_location; - PandaVector methods_for_location; - - LOG(INFO, RUNTIME) << " all the locations are:"; - for (auto const &iter : locations) { - LOG(INFO, RUNTIME) << iter << " "; - } - - LOG(INFO, RUNTIME) << " Methods name : "; - for (const ExtractedMethod &ref : methods) { - LOG(INFO, RUNTIME) << " " << ref.panda_file_->GetFilename(); - if (locations.find(ConvertToString(ref.panda_file_->GetFilename())) != locations.end()) { - LOG(INFO, RUNTIME) << " bingo method!"; - methods_for_location.push_back(ref); - } - } - LOG(INFO, RUNTIME) << std::endl; - LOG(INFO, RUNTIME) << " Classes name"; - - for (const ExtractedResolvedClasses &classes : resolved_classes) { - LOG(INFO, RUNTIME) << " " << classes.GetPandaFileLocation(); - if (locations.find(classes.GetPandaFileLocation()) != locations.end()) { - LOG(INFO, RUNTIME) << " bingo class!"; - resolved_classes_for_location.insert(classes); - } - } - - ProfileDumpInfo *info = GetOrAddCachedProfiledInfo(filename); - LOG(INFO, RUNTIME) << " Adding Bingo Methods and Classes"; - info->AddMethodsAndClasses(methods_for_location, resolved_classes_for_location); - } -} - -ProfileDumpInfo *ProfileSaver::GetOrAddCachedProfiledInfo(const PandaString &filename) -{ - auto info_it = profile_cache_.find(filename); - if (info_it == profile_cache_.end()) { - LOG(INFO, RUNTIME) << " bingo profile_cache_!"; - auto ret = profile_cache_.insert(std::make_pair(filename, ProfileDumpInfo())); - ASSERT(ret.second); - info_it = ret.first; - } - return &(info_it->second); -} - -ProfileSaver::CntStats *ProfileSaver::GetOrAddCachedProfiledStatsInfo(const PandaString &filename) -{ - auto info_it = statcache.find(filename); - if (info_it == statcache.end()) { - LOG(INFO, RUNTIME) << " bingo StatsInfo_cache_!"; - auto ret = statcache.insert(std::make_pair(filename, CntStats())); - ASSERT(ret.second); - info_it = ret.first; - } - return &(info_it->second); -} - -void ProfileSaver::MergeAndDumpProfileData() -{ - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - for (const auto &it : tracked_pandafile_base_locations_) { - if (ShuttingDown()) { - return; - } - const PandaString &filename = it.first; - LOG(INFO, RUNTIME) << " Step3.1 starting merging and save the following file ***"; - LOG(INFO, RUNTIME) << " filename = " << filename; - - ProfileDumpInfo *cached_info = GetOrAddCachedProfiledInfo(filename); - CntStats *cached_stat = GetOrAddCachedProfiledStatsInfo(filename); - ASSERT(cached_info->GetNumberOfMethods() >= cached_stat->GetMethodCount()); - ASSERT(cached_info->GetNumberOfResolvedClasses() >= cached_stat->GetClassCount()); - uint64_t delta_number_of_methods = cached_info->GetNumberOfMethods() - cached_stat->GetMethodCount(); - uint64_t delta_number_of_classes = cached_info->GetNumberOfResolvedClasses() - cached_stat->GetClassCount(); - uint64_t numthreshold = Runtime::GetOptions().GetProfilesaverDeltaNumberThreshold(); - if (delta_number_of_methods < numthreshold && delta_number_of_classes < numthreshold) { - LOG(INFO, RUNTIME) << " number of delta number/class not enough"; - continue; - } - - uint64_t bytes_written; - if (cached_info->MergeAndSave(filename, &bytes_written, true)) { - cached_stat->SetMethodCount(cached_info->GetNumberOfMethods()); - cached_stat->SetClassCount(cached_info->GetNumberOfResolvedClasses()); - } else { - LOG(INFO, RUNTIME) << "Could not save profiling info to " << filename; - } - } -} - -} // namespace panda diff --git a/runtime/profilesaver/profile_saver.h b/runtime/profilesaver/profile_saver.h deleted file mode 100644 index b3f38ee8344757b39e0979a479ecbc5ecf023e1c..0000000000000000000000000000000000000000 --- a/runtime/profilesaver/profile_saver.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PANDA_RUNTIME_PROFILESAVER_PROFILE_SAVER_H_ -#define PANDA_RUNTIME_PROFILESAVER_PROFILE_SAVER_H_ - -#include - -#include -#include -#include -#include -#include - -#include "libpandabase/macros.h" -#include "libpandabase/os/mutex.h" -#include "libpandabase/utils/logger.h" -#include "runtime/include/mem/panda_containers.h" -#include "runtime/include/mem/panda_string.h" -#include "runtime/profilesaver/profile_dump_info.h" - -namespace panda { - -// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, readability-identifier-naming) -static os::memory::Mutex profile_saver_lock_; - -/* - * Note well! we take singleton pattern, multi-threading scenario should be taken more serious considerations. - * - * e.g. Global Mutex Management or corresponding alternatives should better than - * global mutex profile_saver_lock_. - * - */ - -// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions) -class ProfileSaver { -public: - /* - * start the profile saver deamon thread - * - * output_filename records the profile name, code_paths stores all the locations contain pandafile(aka *.aex) - * app_data_dir contains the location of application package - */ - static void Start(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_data_dir); - - /* - * stop the profile saver deamon thread. - * - * if dump_info == true, dumps the debug information - */ - static void Stop(bool dump_info); - - /* - * whether profile saver instance exists. - */ - static bool IsStarted(); - - ~ProfileSaver() = default; - -private: - ProfileSaver(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_dir); - - void AddTrackedLocations(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_data_dir); - - /* - * Callback for pthread_create, we attach/detach this thread to Runtime here - */ - static void *RunProfileSaverThread(void *arg); - - /* - * Run loop for the saver. - */ - void Run(); - - /* - * Returns true if the saver is shutting down (ProfileSaver::Stop() has been called, will set this flag). - */ - bool ShuttingDown(); - - /* - * Dump functions, we leave it stub and for test until now. - */ - void DumpInfo(); - - /* - * Fetches the current resolved classes and methods from the ClassLinker and stores them in the profile_cache_. - */ - void TranverseAndCacheResolvedClassAndMethods(); - - /* - * Retrieves the cached ProfileDumpInfo for the given profile filename. - * If no entry exists, a new empty one will be created, added to the cache and then returned. - */ - ProfileDumpInfo *GetOrAddCachedProfiledInfo(const PandaString &filename); - - /* - * Processes the existing profiling info from the jit code cache(if exists) and returns - * true if it needed to be saved back to disk. - */ - void MergeAndDumpProfileData(); - - static ProfileSaver *instance; - - static std::thread profiler_saver_daemon_thread; - - PandaMap> tracked_pandafile_base_locations_; - - PandaMap profile_cache_; - - PandaSet app_data_dirs_; - - bool shutting_down_ GUARDED_BY(profile_saver_lock_); - - struct CntStats { - public: - uint64_t GetMethodCount() - { - return last_save_number_of_methods_; - } - - void SetMethodCount(uint64_t methodcnt) - { - last_save_number_of_methods_ = methodcnt; - } - - uint64_t GetClassCount() - { - return last_save_number_of_classes_; - } - - void SetClassCount(uint64_t classcnt) - { - last_save_number_of_classes_ = classcnt; - } - - private: - uint64_t last_save_number_of_methods_ {0}; - uint64_t last_save_number_of_classes_ {0}; - }; - - PandaMap statcache; // NOLINT(readability-identifier-naming) - - /* - * Retrieves the cached CntStats for the given profile filename. - * If no entry exists, a new empty one will be created, added to the cache and then returned. - */ - CntStats *GetOrAddCachedProfiledStatsInfo(const PandaString &filename); - - NO_COPY_SEMANTIC(ProfileSaver); - NO_MOVE_SEMANTIC(ProfileSaver); -}; - -} // namespace panda - -#endif // PANDA_RUNTIME_PROFILESAVER_PROFILE_SAVER_H_ diff --git a/runtime/runtime.cpp b/runtime/runtime.cpp index 95385690d55ed28628c573b2bcc6d615d8369b41..a96346064f2f0cc12a1b11aa18e062ec3dc3cd9c 100644 --- a/runtime/runtime.cpp +++ b/runtime/runtime.cpp @@ -58,7 +58,6 @@ #include "runtime/mem/internal_allocator-inl.h" #include "runtime/core/core_class_linker_extension.h" #include "runtime/include/panda_vm.h" -#include "runtime/profilesaver/profile_saver.h" #include "runtime/tooling/debugger.h" #include "runtime/tooling/pt_lang_ext_private.h" #include "runtime/include/file_manager.h" @@ -307,12 +306,6 @@ bool Runtime::Destroy() trace::ScopedTrace scoped_trace("Runtime shutdown"); instance->GetPandaVM()->StopGC(); - // NB! stop the profile saver thread before deleting the thread list to avoid dead loop here. - // the following WaitForThreadStop makes sure profile saver can be shut down. - if (instance->SaveProfileInfo()) { - ProfileSaver::Stop(false); - } - instance->GetPandaVM()->UninitializeThreads(); verifier::JobQueue::Stop(instance->GetVerificationOptions().Mode.OnlyVerify); @@ -883,9 +876,6 @@ void Runtime::RegisterAppInfo(const PandaVector &code_paths, const }(profile_output_filename); StartDProfiler(app_name); - - // this is exactly the place where start the profile saver - ProfileSaver::Start(profile_output_filename, code_paths, PandaString(app_name)); } int Runtime::StartDProfiler(std::string_view app_name)