summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-09-24 18:17:04 -0700
committerIan Rogers <irogers@google.com>2013-09-24 21:17:06 -0700
commitd0fbd85a82a266c21d6b72c61d6dc098ec362de7 (patch)
tree14f431e4bd889b6c7ec6b29322594786828d3bb1 /runtime
parentfc0e94bed3f88ed7e50854fd8dfaf5dcb345250f (diff)
downloadart-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.h3
-rw-r--r--runtime/verifier/method_verifier.cc22
-rw-r--r--runtime/verifier/method_verifier.h18
-rw-r--r--runtime/verifier/register_line.cc3
-rw-r--r--runtime/verifier/register_line.h32
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);