summaryrefslogtreecommitdiffstats
path: root/runtime/verifier
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2014-03-14 17:58:54 +0100
committerSebastien Hertz <shertz@google.com>2014-03-14 18:09:49 +0100
commitaa0c00c97bc1fe5c8def7c6cdebfd119e86d07e5 (patch)
tree2557e1aeb5a1830c72733797f86ea9bf72418228 /runtime/verifier
parent37d4c1db4d705f5a28001f65afdd68d0527948d8 (diff)
downloadart-aa0c00c97bc1fe5c8def7c6cdebfd119e86d07e5.zip
art-aa0c00c97bc1fe5c8def7c6cdebfd119e86d07e5.tar.gz
art-aa0c00c97bc1fe5c8def7c6cdebfd119e86d07e5.tar.bz2
Fix reg type merging in the verifier
Fixes bad merging of float, long and double reg types with constant types. Adds merging tests in reg_type_test. Bug: https://code.google.com/p/android/issues/detail?id=66434 Bug: 13464407 Change-Id: I56761f5f5562b742d0ef9cc66b58d55f7b668949
Diffstat (limited to 'runtime/verifier')
-rw-r--r--runtime/verifier/method_verifier.cc1
-rw-r--r--runtime/verifier/reg_type.cc2
-rw-r--r--runtime/verifier/reg_type_test.cc139
3 files changed, 140 insertions, 2 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index c4c3082..fb2d29f 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3905,6 +3905,7 @@ const RegType& MethodVerifier::GetDeclaringClass() {
std::vector<int32_t> MethodVerifier::DescribeVRegs(uint32_t dex_pc) {
RegisterLine* line = reg_table_.GetLine(dex_pc);
+ DCHECK(line != nullptr) << "No register line at DEX pc " << StringPrintf("0x%x", dex_pc);
std::vector<int32_t> result;
for (size_t i = 0; i < line->NumRegs(); ++i) {
const RegType& type = line->GetRegisterType(i);
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 63f0ff4..c6f3e5c 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -777,7 +777,7 @@ int32_t ConstantType::ConstantValueHi() const {
}
static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
- return a.IsConstant() ? b : a;
+ return a.IsConstantTypes() ? b : a;
}
const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index 1a64c00..1695fc5 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -335,7 +335,6 @@ TEST_F(RegTypeTest, Primitives) {
EXPECT_FALSE(double_reg_type.IsNonZeroReferenceTypes());
}
-
class RegTypeReferenceTest : public CommonRuntimeTest {};
TEST_F(RegTypeReferenceTest, JavalangObjectImprecise) {
@@ -472,6 +471,144 @@ TEST_F(RegTypeReferenceTest, Merging) {
EXPECT_EQ(ref_type_1.GetId(), *((++merged_ids.begin())));
}
+TEST_F(RegTypeReferenceTest, MergingFloat) {
+ // Testing merging logic with float and float constants.
+ ScopedObjectAccess soa(Thread::Current());
+ RegTypeCache cache_new(true);
+
+ constexpr int32_t kTestConstantValue = 10;
+ const RegType& float_type = cache_new.Float();
+ const RegType& precise_cst = cache_new.FromCat1Const(kTestConstantValue, true);
+ const RegType& imprecise_cst = cache_new.FromCat1Const(kTestConstantValue, false);
+ {
+ // float MERGE precise cst => float.
+ const RegType& merged = float_type.Merge(precise_cst, &cache_new);
+ EXPECT_TRUE(merged.IsFloat());
+ }
+ {
+ // precise cst MERGE float => float.
+ const RegType& merged = precise_cst.Merge(float_type, &cache_new);
+ EXPECT_TRUE(merged.IsFloat());
+ }
+ {
+ // float MERGE imprecise cst => float.
+ const RegType& merged = float_type.Merge(imprecise_cst, &cache_new);
+ EXPECT_TRUE(merged.IsFloat());
+ }
+ {
+ // imprecise cst MERGE float => float.
+ const RegType& merged = imprecise_cst.Merge(float_type, &cache_new);
+ EXPECT_TRUE(merged.IsFloat());
+ }
+}
+
+TEST_F(RegTypeReferenceTest, MergingLong) {
+ // Testing merging logic with long and long constants.
+ ScopedObjectAccess soa(Thread::Current());
+ RegTypeCache cache_new(true);
+
+ constexpr int32_t kTestConstantValue = 10;
+ const RegType& long_lo_type = cache_new.LongLo();
+ const RegType& long_hi_type = cache_new.LongHi();
+ const RegType& precise_cst_lo = cache_new.FromCat2ConstLo(kTestConstantValue, true);
+ const RegType& imprecise_cst_lo = cache_new.FromCat2ConstLo(kTestConstantValue, false);
+ const RegType& precise_cst_hi = cache_new.FromCat2ConstHi(kTestConstantValue, true);
+ const RegType& imprecise_cst_hi = cache_new.FromCat2ConstHi(kTestConstantValue, false);
+ {
+ // lo MERGE precise cst lo => lo.
+ const RegType& merged = long_lo_type.Merge(precise_cst_lo, &cache_new);
+ EXPECT_TRUE(merged.IsLongLo());
+ }
+ {
+ // precise cst lo MERGE lo => lo.
+ const RegType& merged = precise_cst_lo.Merge(long_lo_type, &cache_new);
+ EXPECT_TRUE(merged.IsLongLo());
+ }
+ {
+ // lo MERGE imprecise cst lo => lo.
+ const RegType& merged = long_lo_type.Merge(imprecise_cst_lo, &cache_new);
+ EXPECT_TRUE(merged.IsLongLo());
+ }
+ {
+ // imprecise cst lo MERGE lo => lo.
+ const RegType& merged = imprecise_cst_lo.Merge(long_lo_type, &cache_new);
+ EXPECT_TRUE(merged.IsLongLo());
+ }
+ {
+ // hi MERGE precise cst hi => hi.
+ const RegType& merged = long_hi_type.Merge(precise_cst_hi, &cache_new);
+ EXPECT_TRUE(merged.IsLongHi());
+ }
+ {
+ // precise cst hi MERGE hi => hi.
+ const RegType& merged = precise_cst_hi.Merge(long_hi_type, &cache_new);
+ EXPECT_TRUE(merged.IsLongHi());
+ }
+ {
+ // hi MERGE imprecise cst hi => hi.
+ const RegType& merged = long_hi_type.Merge(imprecise_cst_hi, &cache_new);
+ EXPECT_TRUE(merged.IsLongHi());
+ }
+ {
+ // imprecise cst hi MERGE hi => hi.
+ const RegType& merged = imprecise_cst_hi.Merge(long_hi_type, &cache_new);
+ EXPECT_TRUE(merged.IsLongHi());
+ }
+}
+
+TEST_F(RegTypeReferenceTest, MergingDouble) {
+ // Testing merging logic with double and double constants.
+ ScopedObjectAccess soa(Thread::Current());
+ RegTypeCache cache_new(true);
+
+ constexpr int32_t kTestConstantValue = 10;
+ const RegType& double_lo_type = cache_new.DoubleLo();
+ const RegType& double_hi_type = cache_new.DoubleHi();
+ const RegType& precise_cst_lo = cache_new.FromCat2ConstLo(kTestConstantValue, true);
+ const RegType& imprecise_cst_lo = cache_new.FromCat2ConstLo(kTestConstantValue, false);
+ const RegType& precise_cst_hi = cache_new.FromCat2ConstHi(kTestConstantValue, true);
+ const RegType& imprecise_cst_hi = cache_new.FromCat2ConstHi(kTestConstantValue, false);
+ {
+ // lo MERGE precise cst lo => lo.
+ const RegType& merged = double_lo_type.Merge(precise_cst_lo, &cache_new);
+ EXPECT_TRUE(merged.IsDoubleLo());
+ }
+ {
+ // precise cst lo MERGE lo => lo.
+ const RegType& merged = precise_cst_lo.Merge(double_lo_type, &cache_new);
+ EXPECT_TRUE(merged.IsDoubleLo());
+ }
+ {
+ // lo MERGE imprecise cst lo => lo.
+ const RegType& merged = double_lo_type.Merge(imprecise_cst_lo, &cache_new);
+ EXPECT_TRUE(merged.IsDoubleLo());
+ }
+ {
+ // imprecise cst lo MERGE lo => lo.
+ const RegType& merged = imprecise_cst_lo.Merge(double_lo_type, &cache_new);
+ EXPECT_TRUE(merged.IsDoubleLo());
+ }
+ {
+ // hi MERGE precise cst hi => hi.
+ const RegType& merged = double_hi_type.Merge(precise_cst_hi, &cache_new);
+ EXPECT_TRUE(merged.IsDoubleHi());
+ }
+ {
+ // precise cst hi MERGE hi => hi.
+ const RegType& merged = precise_cst_hi.Merge(double_hi_type, &cache_new);
+ EXPECT_TRUE(merged.IsDoubleHi());
+ }
+ {
+ // hi MERGE imprecise cst hi => hi.
+ const RegType& merged = double_hi_type.Merge(imprecise_cst_hi, &cache_new);
+ EXPECT_TRUE(merged.IsDoubleHi());
+ }
+ {
+ // imprecise cst hi MERGE hi => hi.
+ const RegType& merged = imprecise_cst_hi.Merge(double_hi_type, &cache_new);
+ EXPECT_TRUE(merged.IsDoubleHi());
+ }
+}
TEST_F(RegTypeTest, ConstPrecision) {
// Tests creating primitive types types.