summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sebastien Hertz <shertz@google.com> 2014-03-14 17:58:54 +0100
committer Sebastien Hertz <shertz@google.com> 2014-03-14 18:09:49 +0100
commitaa0c00c97bc1fe5c8def7c6cdebfd119e86d07e5 (patch)
tree2557e1aeb5a1830c72733797f86ea9bf72418228
parent37d4c1db4d705f5a28001f65afdd68d0527948d8 (diff)
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
-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 c4c3082918..fb2d29f865 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 63f0ff49a3..c6f3e5c5f4 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 1a64c0002e..1695fc56d3 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.