diff options
author | Ian Rogers <irogers@google.com> | 2013-09-24 18:17:04 -0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2013-09-24 21:17:06 -0700 |
commit | d0fbd85a82a266c21d6b72c61d6dc098ec362de7 (patch) | |
tree | 14f431e4bd889b6c7ec6b29322594786828d3bb1 /runtime | |
parent | fc0e94bed3f88ed7e50854fd8dfaf5dcb345250f (diff) | |
download | art-d0fbd85a82a266c21d6b72c61d6dc098ec362de7.zip art-d0fbd85a82a266c21d6b72c61d6dc098ec362de7.tar.gz art-d0fbd85a82a266c21d6b72c61d6dc098ec362de7.tar.bz2 |
Reduce memory allocation in verifier.
Remove the use of a map PcToRegisterLineTable for efficiency (matches Dalvik).
Place the register line register values inside the RegisterLine, saves a
secondary allocation and indirection.
Avoid the use of a deque in RegisterLine to avoid an allocation.
Simplify the SirtRef destructor in non-debug builds.
Saves >100ms from the two threaded compile time of ThinkFree on host.
Change-Id: I2dacba61dbaf284ca02d4c194413e1da221dcb76
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/sirt_ref.h | 3 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 22 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 18 | ||||
-rw-r--r-- | runtime/verifier/register_line.cc | 3 | ||||
-rw-r--r-- | runtime/verifier/register_line.h | 32 |
5 files changed, 43 insertions, 35 deletions
diff --git a/runtime/sirt_ref.h b/runtime/sirt_ref.h index 25d6fb3..a1f8a66 100644 --- a/runtime/sirt_ref.h +++ b/runtime/sirt_ref.h @@ -30,7 +30,8 @@ class SirtRef { self_->PushSirt(&sirt_); } ~SirtRef() { - CHECK_EQ(self_->PopSirt(), &sirt_); + StackIndirectReferenceTable* top_sirt = self_->PopSirt(); + DCHECK_EQ(top_sirt, &sirt_); } T& operator*() const { return *get(); } diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 4442ee1..6b13517 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -51,7 +51,8 @@ void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InstructionFlags* fl uint32_t insns_size, uint16_t registers_size, MethodVerifier* verifier) { DCHECK_GT(insns_size, 0U); - + register_lines_.reset(new RegisterLine*[insns_size]()); + size_ = insns_size; for (uint32_t i = 0; i < insns_size; i++) { bool interesting = false; switch (mode) { @@ -68,7 +69,16 @@ void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InstructionFlags* fl break; } if (interesting) { - pc_to_register_line_.Put(i, new RegisterLine(registers_size, verifier)); + register_lines_[i] = RegisterLine::Create(registers_size, verifier); + } + } +} + +PcToRegisterLineTable::~PcToRegisterLineTable() { + for (size_t i = 0; i < size_; i++) { + delete register_lines_[i]; + if (kIsDebugBuild) { + register_lines_[i] = nullptr; } } } @@ -1035,8 +1045,8 @@ bool MethodVerifier::VerifyCodeFlow() { this); - work_line_.reset(new RegisterLine(registers_size, this)); - saved_line_.reset(new RegisterLine(registers_size, this)); + work_line_.reset(RegisterLine::Create(registers_size, this)); + saved_line_.reset(RegisterLine::Create(registers_size, this)); /* Initialize register types of method arguments. */ if (!SetTypesFromSignature()) { @@ -1936,7 +1946,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { if (!cast_type.IsUnresolvedTypes() && !orig_type.IsUnresolvedTypes() && !cast_type.GetClass()->IsInterface() && !cast_type.IsAssignableFrom(orig_type)) { - RegisterLine* update_line = new RegisterLine(code_item_->registers_size_, this); + RegisterLine* update_line = RegisterLine::Create(code_item_->registers_size_, this); if (inst->Opcode() == Instruction::IF_EQZ) { fallthrough_line.reset(update_line); } else { @@ -3818,7 +3828,7 @@ bool MethodVerifier::UpdateRegisters(uint32_t next_insn, const RegisterLine* mer } } else { UniquePtr<RegisterLine> copy(gDebugVerify ? - new RegisterLine(target_line->NumRegs(), this) : + RegisterLine::Create(target_line->NumRegs(), this) : NULL); if (gDebugVerify) { copy->CopyFromLine(target_line); diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index f143751..7f33741 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -110,10 +110,8 @@ enum RegisterTrackingMode { // execution of that instruction. class PcToRegisterLineTable { public: - PcToRegisterLineTable() {} - ~PcToRegisterLineTable() { - STLDeleteValues(&pc_to_register_line_); - } + PcToRegisterLineTable() : size_(0) {} + ~PcToRegisterLineTable(); // Initialize the RegisterTable. Every instruction address can have a different set of information // about what's in which register, but for verification purposes we only need to store it at @@ -122,17 +120,13 @@ class PcToRegisterLineTable { uint16_t registers_size, MethodVerifier* verifier); RegisterLine* GetLine(size_t idx) { - auto result = pc_to_register_line_.find(idx); - if (result == pc_to_register_line_.end()) { - return NULL; - } else { - return result->second; - } + DCHECK_LT(idx, size_); + return register_lines_[idx]; } private: - typedef SafeMap<int32_t, RegisterLine*> Table; - Table pc_to_register_line_; + UniquePtr<RegisterLine*[]> register_lines_; + size_t size_; }; // The verifier diff --git a/runtime/verifier/register_line.cc b/runtime/verifier/register_line.cc index a615cc1..1a41657 100644 --- a/runtime/verifier/register_line.cc +++ b/runtime/verifier/register_line.cc @@ -456,8 +456,7 @@ bool RegisterLine::VerifyMonitorStackEmpty() const { bool RegisterLine::MergeRegisters(const RegisterLine* incoming_line) { bool changed = false; - CHECK(NULL != incoming_line); - CHECK(NULL != line_.get()); + DCHECK(incoming_line != nullptr); for (size_t idx = 0; idx < num_regs_; idx++) { if (line_[idx] != incoming_line->line_[idx]) { const RegType& incoming_reg_type = incoming_line->GetRegisterType(idx); diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h index f19dcca..8b2dadb 100644 --- a/runtime/verifier/register_line.h +++ b/runtime/verifier/register_line.h @@ -17,7 +17,6 @@ #ifndef ART_RUNTIME_VERIFIER_REGISTER_LINE_H_ #define ART_RUNTIME_VERIFIER_REGISTER_LINE_H_ -#include <deque> #include <vector> #include "dex_instruction.h" @@ -51,12 +50,10 @@ enum TypeCategory { // stack of entered monitors (identified by code unit offset). class RegisterLine { public: - RegisterLine(size_t num_regs, MethodVerifier* verifier) - : line_(new uint16_t[num_regs]), - verifier_(verifier), - num_regs_(num_regs) { - memset(line_.get(), 0, num_regs_ * sizeof(uint16_t)); - SetResultTypeToUnknown(); + static RegisterLine* Create(size_t num_regs, MethodVerifier* verifier) { + uint8_t* memory = new uint8_t[sizeof(RegisterLine) + (num_regs * sizeof(uint16_t))]; + RegisterLine* rl = new (memory) RegisterLine(num_regs, verifier); + return rl; } // Implement category-1 "move" instructions. Copy a 32-bit value from "vsrc" to "vdst". @@ -108,7 +105,7 @@ class RegisterLine { void CopyFromLine(const RegisterLine* src) { DCHECK_EQ(num_regs_, src->num_regs_); - memcpy(line_.get(), src->line_.get(), num_regs_ * sizeof(uint16_t)); + memcpy(&line_, &src->line_, num_regs_ * sizeof(uint16_t)); monitors_ = src->monitors_; reg_to_lock_depths_ = src->reg_to_lock_depths_; } @@ -116,7 +113,7 @@ class RegisterLine { std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void FillWithGarbage() { - memset(line_.get(), 0xf1, num_regs_ * sizeof(uint16_t)); + memset(&line_, 0xf1, num_regs_ * sizeof(uint16_t)); while (!monitors_.empty()) { monitors_.pop_back(); } @@ -161,7 +158,7 @@ class RegisterLine { int CompareLine(const RegisterLine* line2) const { DCHECK(monitors_ == line2->monitors_); // TODO: DCHECK(reg_to_lock_depths_ == line2->reg_to_lock_depths_); - return memcmp(line_.get(), line2->line_.get(), num_regs_ * sizeof(uint16_t)); + return memcmp(&line_, &line2->line_, num_regs_ * sizeof(uint16_t)); } size_t NumRegs() const { @@ -339,23 +336,30 @@ class RegisterLine { reg_to_lock_depths_.erase(reg); } + RegisterLine(size_t num_regs, MethodVerifier* verifier) + : verifier_(verifier), + num_regs_(num_regs) { + memset(&line_, 0, num_regs_ * sizeof(uint16_t)); + SetResultTypeToUnknown(); + } + // Storage for the result register's type, valid after an invocation uint16_t result_[2]; - // An array of RegType Ids associated with each dex register - UniquePtr<uint16_t[]> line_; - // Back link to the verifier MethodVerifier* verifier_; // Length of reg_types_ const uint32_t num_regs_; // A stack of monitor enter locations - std::deque<uint32_t> monitors_; + std::vector<uint32_t> monitors_; // A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor // stack we verify that monitor-enter/exit are correctly nested. That is, if there was a // monitor-enter on v5 and then on v6, we expect the monitor-exit to be on v6 then on v5 SafeMap<uint32_t, uint32_t> reg_to_lock_depths_; + + // An array of RegType Ids associated with each dex register. + uint16_t line_[0]; }; std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs); |