summaryrefslogtreecommitdiffstats
path: root/runtime/verifier/register_line.h
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-09-10 14:44:24 -0700
committerIan Rogers <irogers@google.com>2014-09-12 14:57:53 -0700
commit7b078e8c04f3e1451dbdd18543c8b9692b5b067e (patch)
tree414229c6b87eb20ea24c40780752da5a3999a49a /runtime/verifier/register_line.h
parentf79ba17defbd9342e44ab9f3de0807054673d3c9 (diff)
downloadart-7b078e8c04f3e1451dbdd18543c8b9692b5b067e.zip
art-7b078e8c04f3e1451dbdd18543c8b9692b5b067e.tar.gz
art-7b078e8c04f3e1451dbdd18543c8b9692b5b067e.tar.bz2
Compile time performance improvements focusing on interpret-only.
Reduce virtual method dispatch in the method verifier and make more code inline-able. Add a StringPiece with const char* equality operator to avoid redundant StringPieces and strlens. Remove back link from register line to verifier and pass as argument to reduce size of RegisterLine. Remove instruction length from instruction flags and compute from the instruction, again to reduce size. Add suspend checks to resolve and verify to allow for more easy monitor inflation and reduce contention on Locks::thread_list_suspend_thread_lock_. Change ThrowEarlierClassFailure to throw pre-allocated exception. Avoid calls to Thread::Current() by passing self. Template specialize IsValidClassName. Make ANR reporting with SIGQUIT run using checkpoints rather than suspending all threads. This makes the stack/lock analysis less lock error prone. Extra Barrier assertions and condition variable time out is now returned as a boolean both from Barrier and ConditionVariable::Wait. 2 threaded host x86-64 interpret-only numbers from 341 samples: Before change: Avg 176.137ms 99% CI 3.468ms to 1060.770ms After change: Avg 139.163% 99% CI 3.027ms to 838.257ms Reduction in average compile time after change is 20.9%. Slow-down without change is 26.5%. Bug: 17471626 - Fix bug where RegTypeCache::JavaLangObject/String/Class/Throwable could return unresolved type when class loading is disabled. Bug: 17398101 Change-Id: Id59ce3cc520701c6ecf612f7152498107bc40684
Diffstat (limited to 'runtime/verifier/register_line.h')
-rw-r--r--runtime/verifier/register_line.h92
1 files changed, 48 insertions, 44 deletions
diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h
index a9d0dbb..c7fd369 100644
--- a/runtime/verifier/register_line.h
+++ b/runtime/verifier/register_line.h
@@ -57,50 +57,54 @@ class RegisterLine {
}
// Implement category-1 "move" instructions. Copy a 32-bit value from "vsrc" to "vdst".
- void CopyRegister1(uint32_t vdst, uint32_t vsrc, TypeCategory cat)
+ void CopyRegister1(MethodVerifier* verifier, uint32_t vdst, uint32_t vsrc, TypeCategory cat)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Implement category-2 "move" instructions. Copy a 64-bit value from "vsrc" to "vdst". This
// copies both halves of the register.
- void CopyRegister2(uint32_t vdst, uint32_t vsrc)
+ void CopyRegister2(MethodVerifier* verifier, uint32_t vdst, uint32_t vsrc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Implement "move-result". Copy the category-1 value from the result register to another
// register, and reset the result register.
- void CopyResultRegister1(uint32_t vdst, bool is_reference)
+ void CopyResultRegister1(MethodVerifier* verifier, uint32_t vdst, bool is_reference)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Implement "move-result-wide". Copy the category-2 value from the result register to another
// register, and reset the result register.
- void CopyResultRegister2(uint32_t vdst)
+ void CopyResultRegister2(MethodVerifier* verifier, uint32_t vdst)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Set the invisible result register to unknown
- void SetResultTypeToUnknown() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetResultTypeToUnknown(MethodVerifier* verifier) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Set the type of register N, verifying that the register is valid. If "newType" is the "Lo"
// part of a 64-bit value, register N+1 will be set to "newType+1".
// The register index was validated during the static pass, so we don't need to check it here.
- bool SetRegisterType(uint32_t vdst, const RegType& new_type)
+ ALWAYS_INLINE bool SetRegisterType(MethodVerifier* verifier, uint32_t vdst,
+ const RegType& new_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool SetRegisterTypeWide(uint32_t vdst, const RegType& new_type1, const RegType& new_type2)
+ bool SetRegisterTypeWide(MethodVerifier* verifier, uint32_t vdst, const RegType& new_type1,
+ const RegType& new_type2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/* Set the type of the "result" register. */
- void SetResultRegisterType(const RegType& new_type)
+ void SetResultRegisterType(MethodVerifier* verifier, const RegType& new_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetResultRegisterTypeWide(const RegType& new_type1, const RegType& new_type2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get the type of register vsrc.
- const RegType& GetRegisterType(uint32_t vsrc) const;
+ const RegType& GetRegisterType(MethodVerifier* verifier, uint32_t vsrc) const;
- bool VerifyRegisterType(uint32_t vsrc, const RegType& check_type)
+ ALWAYS_INLINE bool VerifyRegisterType(MethodVerifier* verifier, uint32_t vsrc,
+ const RegType& check_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool VerifyRegisterTypeWide(uint32_t vsrc, const RegType& check_type1, const RegType& check_type2)
+ bool VerifyRegisterTypeWide(MethodVerifier* verifier, uint32_t vsrc, const RegType& check_type1,
+ const RegType& check_type2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CopyFromLine(const RegisterLine* src) {
@@ -110,7 +114,7 @@ class RegisterLine {
reg_to_lock_depths_ = src->reg_to_lock_depths_;
}
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ std::string Dump(MethodVerifier* verifier) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void FillWithGarbage() {
memset(&line_, 0xf1, num_regs_ * sizeof(uint16_t));
@@ -126,7 +130,7 @@ class RegisterLine {
* to prevent them from being used (otherwise, MarkRefsAsInitialized would mark the old ones and
* the new ones at the same time).
*/
- void MarkUninitRefsAsInvalid(const RegType& uninit_type)
+ void MarkUninitRefsAsInvalid(MethodVerifier* verifier, const RegType& uninit_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/*
@@ -134,15 +138,15 @@ class RegisterLine {
* reference type. This is called when an appropriate constructor is invoked -- all copies of
* the reference must be marked as initialized.
*/
- void MarkRefsAsInitialized(const RegType& uninit_type)
+ void MarkRefsAsInitialized(MethodVerifier* verifier, const RegType& uninit_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/*
* Update all registers to be Conflict except vsrc.
*/
- void MarkAllRegistersAsConflicts();
- void MarkAllRegistersAsConflictsExcept(uint32_t vsrc);
- void MarkAllRegistersAsConflictsExceptWide(uint32_t vsrc);
+ void MarkAllRegistersAsConflicts(MethodVerifier* verifier);
+ void MarkAllRegistersAsConflictsExcept(MethodVerifier* verifier, uint32_t vsrc);
+ void MarkAllRegistersAsConflictsExceptWide(MethodVerifier* verifier, uint32_t vsrc);
/*
* Check constraints on constructor return. Specifically, make sure that the "this" argument got
@@ -151,7 +155,7 @@ class RegisterLine {
* of the list in slot 0. If we see a register with an uninitialized slot 0 reference, we know it
* somehow didn't get initialized.
*/
- bool CheckConstructorReturn() const;
+ bool CheckConstructorReturn(MethodVerifier* verifier) const;
// Compare two register lines. Returns 0 if they match.
// Using this for a sort is unwise, since the value can change based on machine endianness.
@@ -173,28 +177,29 @@ class RegisterLine {
* The argument count is in vA, and the first argument is in vC, for both "simple" and "range"
* versions. We just need to make sure vA is >= 1 and then return vC.
*/
- const RegType& GetInvocationThis(const Instruction* inst, bool is_range)
+ const RegType& GetInvocationThis(MethodVerifier* verifier, const Instruction* inst,
+ bool is_range)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/*
* Verify types for a simple two-register instruction (e.g. "neg-int").
* "dst_type" is stored into vA, and "src_type" is verified against vB.
*/
- void CheckUnaryOp(const Instruction* inst, const RegType& dst_type,
+ void CheckUnaryOp(MethodVerifier* verifier, const Instruction* inst, const RegType& dst_type,
const RegType& src_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckUnaryOpWide(const Instruction* inst,
+ void CheckUnaryOpWide(MethodVerifier* verifier, const Instruction* inst,
const RegType& dst_type1, const RegType& dst_type2,
const RegType& src_type1, const RegType& src_type2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckUnaryOpToWide(const Instruction* inst,
+ void CheckUnaryOpToWide(MethodVerifier* verifier, const Instruction* inst,
const RegType& dst_type1, const RegType& dst_type2,
const RegType& src_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckUnaryOpFromWide(const Instruction* inst,
+ void CheckUnaryOpFromWide(MethodVerifier* verifier, const Instruction* inst,
const RegType& dst_type,
const RegType& src_type1, const RegType& src_type2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -204,18 +209,18 @@ class RegisterLine {
* "dst_type" is stored into vA, and "src_type1"/"src_type2" are verified
* against vB/vC.
*/
- void CheckBinaryOp(const Instruction* inst,
+ void CheckBinaryOp(MethodVerifier* verifier, const Instruction* inst,
const RegType& dst_type, const RegType& src_type1, const RegType& src_type2,
bool check_boolean_op)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckBinaryOpWide(const Instruction* inst,
+ void CheckBinaryOpWide(MethodVerifier* verifier, const Instruction* inst,
const RegType& dst_type1, const RegType& dst_type2,
const RegType& src_type1_1, const RegType& src_type1_2,
const RegType& src_type2_1, const RegType& src_type2_2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckBinaryOpWideShift(const Instruction* inst,
+ void CheckBinaryOpWideShift(MethodVerifier* verifier, const Instruction* inst,
const RegType& long_lo_type, const RegType& long_hi_type,
const RegType& int_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -224,19 +229,19 @@ class RegisterLine {
* Verify types for a binary "2addr" operation. "src_type1"/"src_type2"
* are verified against vA/vB, then "dst_type" is stored into vA.
*/
- void CheckBinaryOp2addr(const Instruction* inst,
+ void CheckBinaryOp2addr(MethodVerifier* verifier, const Instruction* inst,
const RegType& dst_type,
const RegType& src_type1, const RegType& src_type2,
bool check_boolean_op)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckBinaryOp2addrWide(const Instruction* inst,
+ void CheckBinaryOp2addrWide(MethodVerifier* verifier, const Instruction* inst,
const RegType& dst_type1, const RegType& dst_type2,
const RegType& src_type1_1, const RegType& src_type1_2,
const RegType& src_type2_1, const RegType& src_type2_2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CheckBinaryOp2addrWideShift(const Instruction* inst,
+ void CheckBinaryOp2addrWideShift(MethodVerifier* verifier, const Instruction* inst,
const RegType& long_lo_type, const RegType& long_hi_type,
const RegType& int_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -247,16 +252,18 @@ class RegisterLine {
*
* If "check_boolean_op" is set, we use the constant value in vC.
*/
- void CheckLiteralOp(const Instruction* inst,
+ void CheckLiteralOp(MethodVerifier* verifier, const Instruction* inst,
const RegType& dst_type, const RegType& src_type,
bool check_boolean_op, bool is_lit16)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Verify/push monitor onto the monitor stack, locking the value in reg_idx at location insn_idx.
- void PushMonitor(uint32_t reg_idx, int32_t insn_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void PushMonitor(MethodVerifier* verifier, uint32_t reg_idx, int32_t insn_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Verify/pop monitor from monitor stack ensuring that we believe the monitor is locked
- void PopMonitor(uint32_t reg_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void PopMonitor(MethodVerifier* verifier, uint32_t reg_idx)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Stack of currently held monitors and where they were locked
size_t MonitorStackDepth() const {
@@ -265,23 +272,23 @@ class RegisterLine {
// We expect no monitors to be held at certain points, such a method returns. Verify the stack
// is empty, failing and returning false if not.
- bool VerifyMonitorStackEmpty() const;
+ bool VerifyMonitorStackEmpty(MethodVerifier* verifier) const;
- bool MergeRegisters(const RegisterLine* incoming_line)
+ bool MergeRegisters(MethodVerifier* verifier, const RegisterLine* incoming_line)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- size_t GetMaxNonZeroReferenceReg(size_t max_ref_reg) {
+ size_t GetMaxNonZeroReferenceReg(MethodVerifier* verifier, size_t max_ref_reg) {
size_t i = static_cast<int>(max_ref_reg) < 0 ? 0 : max_ref_reg;
for (; i < num_regs_; i++) {
- if (GetRegisterType(i).IsNonZeroReferenceTypes()) {
+ if (GetRegisterType(verifier, i).IsNonZeroReferenceTypes()) {
max_ref_reg = i;
}
}
return max_ref_reg;
}
- // Write a bit at each register location that holds a reference
- void WriteReferenceBitMap(std::vector<uint8_t>& data, size_t max_bytes);
+ // Write a bit at each register location that holds a reference.
+ void WriteReferenceBitMap(MethodVerifier* verifier, std::vector<uint8_t>* data, size_t max_bytes);
size_t GetMonitorEnterCount() {
return monitors_.size();
@@ -337,19 +344,17 @@ class RegisterLine {
}
RegisterLine(size_t num_regs, MethodVerifier* verifier)
- : verifier_(verifier), num_regs_(num_regs) {
+ : num_regs_(num_regs) {
memset(&line_, 0, num_regs_ * sizeof(uint16_t));
- SetResultTypeToUnknown();
+ SetResultTypeToUnknown(verifier);
}
// Storage for the result register's type, valid after an invocation
uint16_t result_[2];
- // Back link to the verifier
- MethodVerifier* verifier_;
-
// Length of reg_types_
const uint32_t num_regs_;
+
// A stack of monitor enter locations
std::vector<uint32_t, TrackingAllocator<uint32_t, kAllocatorTagVerifier>> monitors_;
// A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor
@@ -360,7 +365,6 @@ class RegisterLine {
// An array of RegType Ids associated with each dex register.
uint16_t line_[0];
};
-std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs);
} // namespace verifier
} // namespace art