Merge "Port the "abstract methods are not implementations" fix to art." into dalvik-dev
diff --git a/build/Android.common.mk b/build/Android.common.mk
index f35458c..65cb75d 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -258,6 +258,7 @@
src/utils.cc \
src/vector_output_stream.cc \
src/verifier/dex_gc_map.cc \
+ src/verifier/instruction_flags.cc \
src/verifier/method_verifier.cc \
src/verifier/reg_type.cc \
src/verifier/reg_type_cache.cc \
diff --git a/src/base/histogram-inl.h b/src/base/histogram-inl.h
index 3ffb9a0..9e3de9f 100644
--- a/src/base/histogram-inl.h
+++ b/src/base/histogram-inl.h
@@ -169,7 +169,7 @@
double per_1 = per_0 + interval;
os << Name() << ":\t";
TimeUnit unit = GetAppropriateTimeUnit(Mean() * kAdjust);
- os << interval << "% C.I. "
+ os << (interval * 100) << "% C.I. "
<< FormatDuration(Percentile(per_0) * kAdjust, unit);
os << "-" << FormatDuration(Percentile(per_1) * kAdjust, unit) << " ";
os << "Avg: " << FormatDuration(Mean() * kAdjust, unit) << " Max: ";
@@ -240,6 +240,13 @@
double value = lower_value + (upper_value - lower_value) *
(per - lower_perc) / (upper_perc - lower_perc);
+
+ if (value < min_value_added_) {
+ value = min_value_added_;
+ } else if (value > max_value_added_) {
+ value = max_value_added_;
+ }
+
return value;
}
diff --git a/src/base/histogram_test.cc b/src/base/histogram_test.cc
index 28812fd..7a6c235 100644
--- a/src/base/histogram_test.cc
+++ b/src/base/histogram_test.cc
@@ -29,7 +29,7 @@
hist->AddValue(28);
hist->AddValue(28);
mean = hist->Mean();
- EXPECT_EQ(mean, 20.5);
+ EXPECT_EQ(20.5, mean);
}
TEST(Histtest, VarianceTest) {
@@ -42,7 +42,7 @@
hist->AddValue(28);
hist->CreateHistogram();
variance = hist->Variance();
- EXPECT_EQ(variance, 64.25);
+ EXPECT_EQ(64.25, variance);
delete hist;
}
@@ -69,7 +69,7 @@
hist->CreateHistogram();
PerValue = hist->Percentile(0.50);
- EXPECT_EQ(static_cast<int>(PerValue * 10), 875);
+ EXPECT_EQ(875, static_cast<int>(PerValue * 10));
delete hist;
}
@@ -106,7 +106,7 @@
std::string text;
std::stringstream stream;
std::string expected =
- "UpdateRange:\t0.99% C.I. 1.050us-214.475us Avg: 126.380us Max: 212us\n";
+ "UpdateRange:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n";
hist->PrintConfidenceIntervals(stream, 0.99);
EXPECT_EQ(expected, stream.str());
@@ -152,7 +152,7 @@
std::string text;
std::stringstream stream;
std::string expected =
- "Reset:\t0.99% C.I. 1.050us-214.475us Avg: 126.380us Max: 212us\n";
+ "Reset:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n";
hist->PrintConfidenceIntervals(stream, 0.99);
EXPECT_EQ(expected, stream.str());
@@ -192,10 +192,9 @@
hist->AddValue(212);
hist->CreateHistogram();
PerValue = hist->Percentile(0.50);
-
std::stringstream stream;
std::string expected =
- "MultipleCreateHist:\t0.99% C.I. 1.050us-214.475us Avg: 126.380us Max: 212us\n";
+ "MultipleCreateHist:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n";
hist->PrintConfidenceIntervals(stream, 0.99);
EXPECT_EQ(expected, stream.str());
@@ -208,16 +207,38 @@
TEST(Histtest, SingleValue) {
Histogram<uint64_t> *hist = new Histogram<uint64_t>("SingleValue");
-
hist->AddValue(1);
hist->CreateHistogram();
-
std::stringstream stream;
- std::string expected =
- "SingleValue:\t0.99% C.I. 0.025us-4.975us Avg: 1us Max: 1us\n";
+ std::string expected = "SingleValue:\t99% C.I. 1us-1us Avg: 1us Max: 1us\n";
hist->PrintConfidenceIntervals(stream, 0.99);
- EXPECT_EQ(stream.str(), expected);
+ EXPECT_EQ(expected, stream.str());
+ delete hist;
+}
+TEST(Histtest, CappingPercentiles) {
+
+ double per_995;
+ double per_005;
+ Histogram<uint64_t> *hist = new Histogram<uint64_t>("CappingPercentiles");
+ // All values are similar.
+ for (uint64_t idx = 0ull; idx < 150ull; idx++) {
+ hist->AddValue(0);
+ }
+ hist->CreateHistogram();
+ per_995 = hist->Percentile(0.995);
+ EXPECT_EQ(per_995, 0);
+ hist->Reset();
+ for (size_t idx = 0; idx < 200; idx++) {
+ for (uint64_t val = 1ull; val <= 4ull; val++) {
+ hist->AddValue(val);
+ }
+ }
+ hist->CreateHistogram();
+ per_005 = hist->Percentile(0.005);
+ per_995 = hist->Percentile(0.995);
+ EXPECT_EQ(1, per_005);
+ EXPECT_EQ(4, per_995);
delete hist;
}
@@ -230,15 +251,13 @@
hist->AddValue(idx * idx_inner);
}
}
-
hist->AddValue(10000);
hist->CreateHistogram();
-
std::stringstream stream;
std::string expected =
- "SpikyValues:\t0.99% C.I. 0.089us-2541.825us Avg: 95.033us Max: 10000us\n";
+ "SpikyValues:\t99% C.I. 0.089us-2541.825us Avg: 95.033us Max: 10000us\n";
hist->PrintConfidenceIntervals(stream, 0.99);
- EXPECT_EQ(stream.str(), expected);
+ EXPECT_EQ(expected, stream.str());
delete hist;
}
diff --git a/src/compiler_llvm/ir_builder.h b/src/compiler_llvm/ir_builder.h
index 4a58515..60a0f2a 100644
--- a/src/compiler_llvm/ir_builder.h
+++ b/src/compiler_llvm/ir_builder.h
@@ -65,6 +65,15 @@
return inst;
}
+ llvm::AtomicCmpXchgInst*
+ CreateAtomicCmpXchgInst(llvm::Value* ptr, llvm::Value* cmp, llvm::Value* val,
+ llvm::MDNode* tbaa_info) {
+ llvm::AtomicCmpXchgInst* inst =
+ LLVMIRBuilder::CreateAtomicCmpXchg(ptr, cmp, val, llvm::Acquire);
+ inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_info);
+ return inst;
+ }
+
//--------------------------------------------------------------------------
// TBAA
@@ -120,6 +129,17 @@
StoreToObjectOffset(object_addr, offset, new_value, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
}
+ llvm::AtomicCmpXchgInst*
+ CompareExchangeObjectOffset(llvm::Value* object_addr,
+ int64_t offset,
+ llvm::Value* cmp_value,
+ llvm::Value* new_value,
+ TBAASpecialType special_ty) {
+ DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
+ return CompareExchangeObjectOffset(object_addr, offset, cmp_value, new_value,
+ mdb_.GetTBAASpecialType(special_ty));
+ }
+
void SetTBAA(llvm::Instruction* inst, TBAASpecialType special_ty) {
inst->setMetadata(llvm::LLVMContext::MD_tbaa, mdb_.GetTBAASpecialType(special_ty));
}
@@ -210,6 +230,21 @@
CreateStore(new_value, value_addr, tbaa_info);
}
+ llvm::AtomicCmpXchgInst* CompareExchangeObjectOffset(llvm::Value* object_addr,
+ int64_t offset,
+ llvm::Value* cmp_value,
+ llvm::Value* new_value,
+ llvm::MDNode* tbaa_info) {
+ // Convert offset to llvm::value
+ llvm::Value* llvm_offset = getPtrEquivInt(offset);
+ // Calculate the value's address
+ llvm::Value* value_addr = CreatePtrDisp(object_addr,
+ llvm_offset,
+ new_value->getType()->getPointerTo());
+ // Atomic compare and exchange
+ return CreateAtomicCmpXchgInst(value_addr, cmp_value, new_value, tbaa_info);
+ }
+
//--------------------------------------------------------------------------
// Runtime Helper Function
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index 36b5fa1..e661ec4 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -167,9 +167,49 @@
/* Monitor */
void RuntimeSupportBuilder::EmitLockObject(llvm::Value* object) {
- // TODO: Implement a fast path.
+ Value* monitor =
+ irb_.LoadFromObjectOffset(object,
+ mirror::Object::MonitorOffset().Int32Value(),
+ irb_.getJIntTy(),
+ kTBAARuntimeInfo);
+
+ Value* real_monitor =
+ irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
+
+ // Is thin lock, unheld and not recursively acquired.
+ Value* unheld = irb_.CreateICmpEQ(real_monitor, irb_.getInt32(0));
+
+ Function* parent_func = irb_.GetInsertBlock()->getParent();
+ BasicBlock* bb_fast = BasicBlock::Create(context_, "lock_fast", parent_func);
+ BasicBlock* bb_slow = BasicBlock::Create(context_, "lock_slow", parent_func);
+ BasicBlock* bb_cont = BasicBlock::Create(context_, "lock_cont", parent_func);
+ irb_.CreateCondBr(unheld, bb_fast, bb_slow, kLikely);
+
+ irb_.SetInsertPoint(bb_fast);
+
+ // Calculate new monitor: new = old | (lock_id << LW_LOCK_OWNER_SHIFT)
+ Value* lock_id =
+ EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
+ irb_.getInt32Ty(), kTBAARuntimeInfo);
+
+ Value* owner = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
+ Value* new_monitor = irb_.CreateOr(monitor, owner);
+
+ // Atomically update monitor.
+ Value* old_monitor =
+ irb_.CompareExchangeObjectOffset(object,
+ mirror::Object::MonitorOffset().Int32Value(),
+ monitor, new_monitor, kTBAARuntimeInfo);
+
+ Value* retry_slow_path = irb_.CreateICmpEQ(old_monitor, monitor);
+ irb_.CreateCondBr(retry_slow_path, bb_cont, bb_slow, kLikely);
+
+ irb_.SetInsertPoint(bb_slow);
Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
+ irb_.CreateBr(bb_cont);
+
+ irb_.SetInsertPoint(bb_cont);
}
void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) {
diff --git a/src/disassembler_x86.cc b/src/disassembler_x86.cc
index 38171f6..bda162a 100644
--- a/src/disassembler_x86.cc
+++ b/src/disassembler_x86.cc
@@ -480,6 +480,7 @@
break;
case 0xAE:
if (prefix[0] == 0xF3) {
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
static const char* xAE_opcodes[] = {"rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE"};
modrm_opcodes = xAE_opcodes;
reg_is_opcode = true;
@@ -731,7 +732,18 @@
for (size_t i = 0; begin_instr + i < instr; ++i) {
hex << StringPrintf("%02X", begin_instr[i]);
}
- os << StringPrintf("%p: %22s \t%-7s ", begin_instr, hex.str().c_str(), opcode.str().c_str()) << args.str() << '\n';
+ std::stringstream prefixed_opcode;
+ switch (prefix[0]) {
+ case 0xF0: prefixed_opcode << "lock "; break;
+ case 0xF2: prefixed_opcode << "repne "; break;
+ case 0xF3: prefixed_opcode << "repe "; break;
+ case 0: break;
+ default: LOG(FATAL) << "Unreachable";
+ }
+ prefixed_opcode << opcode.str();
+ os << StringPrintf("%p: %22s \t%-7s ", begin_instr, hex.str().c_str(),
+ prefixed_opcode.str().c_str())
+ << args.str() << '\n';
return instr - begin_instr;
}
diff --git a/src/oat/runtime/support_deoptimize.cc b/src/oat/runtime/support_deoptimize.cc
index 0d88c52..c77d034 100644
--- a/src/oat/runtime/support_deoptimize.cc
+++ b/src/oat/runtime/support_deoptimize.cc
@@ -51,11 +51,10 @@
CHECK(code_item != NULL);
uint16_t num_regs = code_item->registers_size_;
shadow_frame_ = ShadowFrame::Create(num_regs, NULL, m, GetDexPc());
- std::vector<int32_t> kinds =
- verifier::MethodVerifier::DescribeVRegs(m->GetDexMethodIndex(), &mh.GetDexFile(),
- mh.GetDexCache(), mh.GetClassLoader(),
- mh.GetClassDefIndex(), code_item, m,
- m->GetAccessFlags(), GetDexPc());
+ std::vector<int32_t> kinds = DescribeVRegs(m->GetDexMethodIndex(), &mh.GetDexFile(),
+ mh.GetDexCache(), mh.GetClassLoader(),
+ mh.GetClassDefIndex(), code_item, m,
+ m->GetAccessFlags(), GetDexPc());
for(uint16_t reg = 0; reg < num_regs; reg++) {
VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
switch (kind) {
@@ -72,6 +71,22 @@
}
return false; // Stop now we have built the shadow frame.
}
+
+ std::vector<int32_t> DescribeVRegs(uint32_t dex_method_idx,
+ const DexFile* dex_file,
+ mirror::DexCache* dex_cache,
+ mirror::ClassLoader* class_loader,
+ uint32_t class_def_idx,
+ const DexFile::CodeItem* code_item,
+ mirror::AbstractMethod* method,
+ uint32_t method_access_flags, uint32_t dex_pc)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ verifier::MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item,
+ dex_method_idx, method, method_access_flags, true);
+ verifier.Verify();
+ return verifier.DescribeVRegs(dex_pc);
+ }
+
ShadowFrame* shadow_frame_;
uint32_t runtime_frames_;
} visitor(self, self->GetLongJumpContext());
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 3fe62bc..4063d70 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -585,14 +585,22 @@
uint32_t dex_method_idx, const DexFile* dex_file,
uint32_t class_def_idx, const DexFile::CodeItem* code_item,
uint32_t method_access_flags, uint32_t dex_pc) {
+ static UniquePtr<verifier::MethodVerifier> verifier;
+ static const DexFile* verified_dex_file = NULL;
+ static uint32_t verified_dex_method_idx = DexFile::kDexNoIndex;
+ if (dex_file != verified_dex_file || verified_dex_method_idx != dex_method_idx) {
+ ScopedObjectAccess soa(Thread::Current());
+ mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file);
+ mirror::ClassLoader* class_loader = NULL;
+ verifier.reset(new verifier::MethodVerifier(dex_file, dex_cache, class_loader, class_def_idx,
+ code_item, dex_method_idx, NULL,
+ method_access_flags, true));
+ verifier->Verify();
+ verified_dex_file = dex_file;
+ verified_dex_method_idx = dex_method_idx;
+ }
+ std::vector<int32_t> kinds = verifier->DescribeVRegs(dex_pc);
bool first = true;
- ScopedObjectAccess soa(Thread::Current());
- mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file);
- mirror::ClassLoader* class_loader = NULL;
- std::vector<int32_t> kinds =
- verifier::MethodVerifier::DescribeVRegs(dex_method_idx, dex_file, dex_cache,
- class_loader, class_def_idx, code_item, NULL,
- method_access_flags, dex_pc);
for (size_t reg = 0; reg < code_item->registers_size_; reg++) {
VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
if (kind != kUndefined) {
diff --git a/src/verifier/instruction_flags.cc b/src/verifier/instruction_flags.cc
new file mode 100644
index 0000000..823edde
--- /dev/null
+++ b/src/verifier/instruction_flags.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * 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 "instruction_flags.h"
+
+#include <string.h>
+
+namespace art {
+namespace verifier {
+
+std::string InstructionFlags::ToString() const {
+ char encoding[6];
+ if (!IsOpcode()) {
+ strncpy(encoding, "XXXXX", sizeof(encoding));
+ } else {
+ strncpy(encoding, "-----", sizeof(encoding));
+ if (IsInTry()) encoding[kInTry] = 'T';
+ if (IsBranchTarget()) encoding[kBranchTarget] = 'B';
+ if (IsGcPoint()) encoding[kGcPoint] = 'G';
+ if (IsVisited()) encoding[kVisited] = 'V';
+ if (IsChanged()) encoding[kChanged] = 'C';
+ }
+ return encoding;
+}
+
+} // namespace verifier
+} // namespace art
diff --git a/src/verifier/instruction_flags.h b/src/verifier/instruction_flags.h
new file mode 100644
index 0000000..7f0d240
--- /dev/null
+++ b/src/verifier/instruction_flags.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * 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 ART_SRC_VERIFIER_METHOD_INSTRUCTION_FLAGS_H_
+#define ART_SRC_VERIFIER_METHOD_INSTRUCTION_FLAGS_H_
+
+#include "base/logging.h"
+
+#include <stdint.h>
+#include <string>
+
+namespace art {
+namespace verifier {
+
+class InstructionFlags {
+ public:
+ InstructionFlags() : length_(0), flags_(0) {}
+
+ void SetLengthInCodeUnits(size_t length) {
+ DCHECK_LT(length, 65536u);
+ length_ = length;
+ }
+ size_t GetLengthInCodeUnits() {
+ return length_;
+ }
+ bool IsOpcode() const {
+ return length_ != 0;
+ }
+
+ void SetInTry() {
+ flags_ |= 1 << kInTry;
+ }
+ void ClearInTry() {
+ flags_ &= ~(1 << kInTry);
+ }
+ bool IsInTry() const {
+ return (flags_ & (1 << kInTry)) != 0;
+ }
+
+ void SetBranchTarget() {
+ flags_ |= 1 << kBranchTarget;
+ }
+ void ClearBranchTarget() {
+ flags_ &= ~(1 << kBranchTarget);
+ }
+ bool IsBranchTarget() const {
+ return (flags_ & (1 << kBranchTarget)) != 0;
+ }
+
+ void SetGcPoint() {
+ flags_ |= 1 << kGcPoint;
+ }
+ void ClearGcPoint() {
+ flags_ &= ~(1 << kGcPoint);
+ }
+ bool IsGcPoint() const {
+ return (flags_ & (1 << kGcPoint)) != 0;
+ }
+
+ void SetVisited() {
+ flags_ |= 1 << kVisited;
+ }
+ void ClearVisited() {
+ flags_ &= ~(1 << kVisited);
+ }
+ bool IsVisited() const {
+ return (flags_ & (1 << kVisited)) != 0;
+ }
+
+ void SetChanged() {
+ flags_ |= 1 << kChanged;
+ }
+ void ClearChanged() {
+ flags_ &= ~(1 << kChanged);
+ }
+ bool IsChanged() const {
+ return (flags_ & (1 << kChanged)) != 0;
+ }
+
+ bool IsVisitedOrChanged() const {
+ return IsVisited() || IsChanged();
+ }
+
+ std::string ToString() const;
+
+ private:
+ enum {
+ kInTry,
+ kBranchTarget,
+ kGcPoint,
+ kVisited,
+ kChanged,
+ };
+
+ // Size of instruction in code units.
+ uint16_t length_;
+ uint8_t flags_;
+};
+
+} // namespace verifier
+} // namespace art
+
+#endif // ART_SRC_VERIFIER_METHOD_INSTRUCTION_FLAGS_H_
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index bcac374..56344cf 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -50,105 +50,7 @@
static const bool gDebugVerify = false;
-class InsnFlags {
- public:
- InsnFlags() : length_(0), flags_(0) {}
-
- void SetLengthInCodeUnits(size_t length) {
- CHECK_LT(length, 65536u);
- length_ = length;
- }
- size_t GetLengthInCodeUnits() {
- return length_;
- }
- bool IsOpcode() const {
- return length_ != 0;
- }
-
- void SetInTry() {
- flags_ |= 1 << kInTry;
- }
- void ClearInTry() {
- flags_ &= ~(1 << kInTry);
- }
- bool IsInTry() const {
- return (flags_ & (1 << kInTry)) != 0;
- }
-
- void SetBranchTarget() {
- flags_ |= 1 << kBranchTarget;
- }
- void ClearBranchTarget() {
- flags_ &= ~(1 << kBranchTarget);
- }
- bool IsBranchTarget() const {
- return (flags_ & (1 << kBranchTarget)) != 0;
- }
-
- void SetGcPoint() {
- flags_ |= 1 << kGcPoint;
- }
- void ClearGcPoint() {
- flags_ &= ~(1 << kGcPoint);
- }
- bool IsGcPoint() const {
- return (flags_ & (1 << kGcPoint)) != 0;
- }
-
- void SetVisited() {
- flags_ |= 1 << kVisited;
- }
- void ClearVisited() {
- flags_ &= ~(1 << kVisited);
- }
- bool IsVisited() const {
- return (flags_ & (1 << kVisited)) != 0;
- }
-
- void SetChanged() {
- flags_ |= 1 << kChanged;
- }
- void ClearChanged() {
- flags_ &= ~(1 << kChanged);
- }
- bool IsChanged() const {
- return (flags_ & (1 << kChanged)) != 0;
- }
-
- bool IsVisitedOrChanged() const {
- return IsVisited() || IsChanged();
- }
-
- std::string Dump() {
- char encoding[6];
- if (!IsOpcode()) {
- strncpy(encoding, "XXXXX", sizeof(encoding));
- } else {
- strncpy(encoding, "-----", sizeof(encoding));
- if (IsInTry()) encoding[kInTry] = 'T';
- if (IsBranchTarget()) encoding[kBranchTarget] = 'B';
- if (IsGcPoint()) encoding[kGcPoint] = 'G';
- if (IsVisited()) encoding[kVisited] = 'V';
- if (IsChanged()) encoding[kChanged] = 'C';
- }
- return std::string(encoding);
- }
-
- private:
- enum {
- kInTry,
- kBranchTarget,
- kGcPoint,
- kVisited,
- kChanged,
- };
-
- // Size of instruction in code units
- uint16_t length_;
- uint8_t flags_;
-};
-
-void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InsnFlags* flags,
+void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InstructionFlags* flags,
uint32_t insns_size, uint16_t registers_size,
MethodVerifier* verifier) {
DCHECK_GT(insns_size, 0U);
@@ -357,20 +259,6 @@
verifier.Dump(os);
}
-std::vector<int32_t> MethodVerifier::DescribeVRegs(uint32_t dex_method_idx,
- const DexFile* dex_file,
- mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader,
- uint32_t class_def_idx,
- const DexFile::CodeItem* code_item,
- mirror::AbstractMethod* method,
- uint32_t method_access_flags, uint32_t dex_pc) {
- MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item,
- dex_method_idx, method, method_access_flags, true);
- verifier.Verify();
- return verifier.DescribeVRegs(dex_pc);
-}
-
MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache,
mirror::ClassLoader* class_loader, uint32_t class_def_idx,
const DexFile::CodeItem* code_item,
@@ -435,7 +323,7 @@
return false;
}
// Allocate and initialize an array to hold instruction data.
- insn_flags_.reset(new InsnFlags[code_item_->insns_size_in_code_units_]());
+ insn_flags_.reset(new InstructionFlags[code_item_->insns_size_in_code_units_]());
// Run through the instructions and see if the width checks out.
bool result = ComputeWidthsAndCountOps();
// Flag instructions guarded by a "try" block and check exception handlers.
@@ -1109,7 +997,7 @@
if (reg_line != NULL) {
indent_os << reg_line->Dump() << "\n";
}
- indent_os << StringPrintf("0x%04zx", dex_pc) << ": " << insn_flags_[dex_pc].Dump() << " ";
+ indent_os << StringPrintf("0x%04zx", dex_pc) << ": " << insn_flags_[dex_pc].ToString() << " ";
const bool kDumpHexOfInstruction = false;
if (kDumpHexOfInstruction) {
indent_os << inst->DumpHex(5) << " ";
@@ -3228,7 +3116,7 @@
return true;
}
-InsnFlags* MethodVerifier::CurrentInsnFlags() {
+InstructionFlags* MethodVerifier::CurrentInsnFlags() {
return &insn_flags_[work_insn_idx_];
}
@@ -3421,7 +3309,7 @@
result.push_back(kUndefined);
result.push_back(0);
} else {
- CHECK(type.IsNonZeroReferenceTypes()) << type;
+ CHECK(type.IsNonZeroReferenceTypes());
result.push_back(kReferenceVReg);
result.push_back(0);
}
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index a36a1f9..4939217 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -17,8 +17,6 @@
#ifndef ART_SRC_VERIFIER_METHOD_VERIFIER_H_
#define ART_SRC_VERIFIER_METHOD_VERIFIER_H_
-#include <deque>
-#include <limits>
#include <set>
#include <vector>
@@ -28,6 +26,7 @@
#include "compiler.h"
#include "dex_file.h"
#include "dex_instruction.h"
+#include "instruction_flags.h"
#include "mirror/object.h"
#include "reg_type.h"
#include "reg_type_cache.h"
@@ -48,7 +47,6 @@
namespace verifier {
class MethodVerifier;
-class InsnFlags;
class DexPcToReferenceMap;
/*
@@ -125,7 +123,7 @@
// 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
// branch target addresses (because we merge into that).
- void Init(RegisterTrackingMode mode, InsnFlags* flags, uint32_t insns_size,
+ void Init(RegisterTrackingMode mode, InstructionFlags* flags, uint32_t insns_size,
uint16_t registers_size, MethodVerifier* verifier);
RegisterLine* GetLine(size_t idx) {
@@ -147,7 +145,6 @@
#if defined(ART_USE_LLVM_COMPILER)
typedef greenland::InferredRegCategoryMap InferredRegCategoryMap;
#endif
-
public:
enum FailureKind {
kNoFailure,
@@ -169,15 +166,6 @@
mirror::AbstractMethod* method, uint32_t method_access_flags)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static std::vector<int32_t> DescribeVRegs(uint32_t dex_method_idx,
- const DexFile* dex_file, mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader,
- uint32_t class_def_idx,
- const DexFile::CodeItem* code_item,
- mirror::AbstractMethod* method,
- uint32_t method_access_flags, uint32_t dex_pc)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
uint8_t EncodePcToReferenceMapData() const;
uint32_t DexFileVersion() const {
@@ -228,14 +216,21 @@
return can_load_classes_;
}
- private:
- explicit MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader, uint32_t class_def_idx,
- const DexFile::CodeItem* code_item,
- uint32_t method_idx, mirror::AbstractMethod* method, uint32_t access_flags,
- bool can_load_classes)
+ MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache,
+ mirror::ClassLoader* class_loader, uint32_t class_def_idx,
+ const DexFile::CodeItem* code_item,
+ uint32_t method_idx, mirror::AbstractMethod* method,
+ uint32_t access_flags, bool can_load_classes)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Run verification on the method. Returns true if verification completes and false if the input
+ // has an irrecoverable corruption.
+ bool Verify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Describe VRegs at the given dex pc.
+ std::vector<int32_t> DescribeVRegs(uint32_t dex_pc);
+
+ private:
// Adds the given string to the beginning of the last failure message.
void PrependToLastFailMessage(std::string);
@@ -260,10 +255,6 @@
mirror::AbstractMethod* method, uint32_t method_access_flags)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- // Run verification on the method. Returns true if verification completes and false if the input
- // has an irrecoverable corruption.
- bool Verify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
void FindLocksAtDexPc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/*
@@ -597,10 +588,7 @@
// Compute sizes for GC map data
void ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);
- // Describe VRegs at the given dex pc.
- std::vector<int32_t> DescribeVRegs(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- InsnFlags* CurrentInsnFlags();
+ InstructionFlags* CurrentInsnFlags();
// All the GC maps that the verifier has created
typedef SafeMap<const Compiler::MethodReference, const std::vector<uint8_t>*> DexGcMapTable;
@@ -652,7 +640,8 @@
mirror::ClassLoader* class_loader_ GUARDED_BY(Locks::mutator_lock_);
uint32_t class_def_idx_; // The class def index of the declaring class of the method.
const DexFile::CodeItem* code_item_; // The code item containing the code for the method.
- UniquePtr<InsnFlags[]> insn_flags_; // Instruction widths and flags, one entry per code unit.
+ // Instruction widths and flags, one entry per code unit.
+ UniquePtr<InstructionFlags[]> insn_flags_;
// The dex PC of a FindLocksAtDexPc request, -1 otherwise.
uint32_t interesting_dex_pc_;