ART: Fix RegTypeCache::FromUnresolvedMerge().
Do not assume that the BitVector memory is zero-initialized.
Also fix reg_type_test memory leaks reported by valgrind by
constructing ArenaStack and ScopedArenaAllocator in each
individual test.
Bug: 27500678
Change-Id: Ic6b2b6ebeab2c5c6e993a0232c5d4a0159aabea3
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 30f613c..b171b75 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -17,6 +17,7 @@
#include "reg_type_cache-inl.h"
#include "base/arena_bit_vector.h"
+#include "base/bit_vector-inl.h"
#include "base/casts.h"
#include "base/scoped_arena_allocator.h"
#include "base/stl_util.h"
@@ -351,9 +352,11 @@
types.Copy(&left_merge->GetUnresolvedTypes());
left_resolved = &left_merge->GetResolvedPart();
} else if (left.IsUnresolvedTypes()) {
+ types.ClearAllBits();
types.SetBit(left.GetId());
left_resolved = &Zero();
} else {
+ types.ClearAllBits();
left_resolved = &left;
}
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index 22ac7e4..42a74f8 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -30,23 +30,14 @@
namespace art {
namespace verifier {
-class BaseRegTypeTest : public CommonRuntimeTest {
- public:
- void PostRuntimeCreate() OVERRIDE {
- stack.reset(new ArenaStack(Runtime::Current()->GetArenaPool()));
- allocator.reset(new ScopedArenaAllocator(stack.get()));
- }
-
- std::unique_ptr<ArenaStack> stack;
- std::unique_ptr<ScopedArenaAllocator> allocator;
-};
-
-class RegTypeTest : public BaseRegTypeTest {};
+class RegTypeTest : public CommonRuntimeTest {};
TEST_F(RegTypeTest, ConstLoHi) {
// Tests creating primitive types types.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(true, *allocator);
+ RegTypeCache cache(true, allocator);
const RegType& ref_type_const_0 = cache.FromCat1Const(10, true);
const RegType& ref_type_const_1 = cache.FromCat1Const(10, true);
const RegType& ref_type_const_2 = cache.FromCat1Const(30, true);
@@ -67,8 +58,10 @@
}
TEST_F(RegTypeTest, Pairs) {
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(true, *allocator);
+ RegTypeCache cache(true, allocator);
int64_t val = static_cast<int32_t>(1234);
const RegType& precise_lo = cache.FromCat2ConstLo(static_cast<int32_t>(val), true);
const RegType& precise_hi = cache.FromCat2ConstHi(static_cast<int32_t>(val >> 32), true);
@@ -91,8 +84,10 @@
}
TEST_F(RegTypeTest, Primitives) {
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(true, *allocator);
+ RegTypeCache cache(true, allocator);
const RegType& bool_reg_type = cache.Boolean();
EXPECT_FALSE(bool_reg_type.IsUndefined());
@@ -359,13 +354,15 @@
EXPECT_TRUE(double_reg_type.HasClass());
}
-class RegTypeReferenceTest : public BaseRegTypeTest {};
+class RegTypeReferenceTest : public CommonRuntimeTest {};
TEST_F(RegTypeReferenceTest, JavalangObjectImprecise) {
// Tests matching precisions. A reference type that was created precise doesn't
// match the one that is imprecise.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(true, *allocator);
+ RegTypeCache cache(true, allocator);
const RegType& imprecise_obj = cache.JavaLangObject(false);
const RegType& precise_obj = cache.JavaLangObject(true);
const RegType& precise_obj_2 = cache.FromDescriptor(nullptr, "Ljava/lang/Object;", true);
@@ -379,8 +376,10 @@
TEST_F(RegTypeReferenceTest, UnresolvedType) {
// Tests creating unresolved types. Miss for the first time asking the cache and
// a hit second time.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(true, *allocator);
+ RegTypeCache cache(true, allocator);
const RegType& ref_type_0 = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
EXPECT_TRUE(ref_type_0.IsNonZeroReferenceTypes());
@@ -395,8 +394,10 @@
TEST_F(RegTypeReferenceTest, UnresolvedUnintializedType) {
// Tests creating types uninitialized types from unresolved types.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(true, *allocator);
+ RegTypeCache cache(true, allocator);
const RegType& ref_type_0 = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
EXPECT_TRUE(ref_type_0.IsUnresolvedReference());
const RegType& ref_type = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
@@ -417,8 +418,10 @@
TEST_F(RegTypeReferenceTest, Dump) {
// Tests types for proper Dump messages.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(true, *allocator);
+ RegTypeCache cache(true, allocator);
const RegType& unresolved_ref = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExist;", true);
const RegType& unresolved_ref_another = cache.FromDescriptor(nullptr, "Ljava/lang/DoesNotExistEither;", true);
const RegType& resolved_ref = cache.JavaLangString();
@@ -442,8 +445,10 @@
// Add a class to the cache then look for the same class and make sure it is a
// Hit the second time. Then check for the same effect when using
// The JavaLangObject method instead of FromDescriptor. String class is final.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(true, *allocator);
+ RegTypeCache cache(true, allocator);
const RegType& ref_type = cache.JavaLangString();
const RegType& ref_type_2 = cache.JavaLangString();
const RegType& ref_type_3 = cache.FromDescriptor(nullptr, "Ljava/lang/String;", true);
@@ -462,8 +467,10 @@
// Add a class to the cache then look for the same class and make sure it is a
// Hit the second time. Then I am checking for the same effect when using
// The JavaLangObject method instead of FromDescriptor. Object Class in not final.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache(true, *allocator);
+ RegTypeCache cache(true, allocator);
const RegType& ref_type = cache.JavaLangObject(true);
const RegType& ref_type_2 = cache.JavaLangObject(true);
const RegType& ref_type_3 = cache.FromDescriptor(nullptr, "Ljava/lang/Object;", true);
@@ -476,7 +483,9 @@
// Tests merging logic
// String and object , LUB is object.
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(true, *allocator);
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
+ RegTypeCache cache_new(true, allocator);
const RegType& string = cache_new.JavaLangString();
const RegType& Object = cache_new.JavaLangObject(true);
EXPECT_TRUE(string.Merge(Object, &cache_new).IsJavaLangObject());
@@ -498,8 +507,10 @@
TEST_F(RegTypeTest, MergingFloat) {
// Testing merging logic with float and float constants.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(true, *allocator);
+ RegTypeCache cache_new(true, allocator);
constexpr int32_t kTestConstantValue = 10;
const RegType& float_type = cache_new.Float();
@@ -529,8 +540,10 @@
TEST_F(RegTypeTest, MergingLong) {
// Testing merging logic with long and long constants.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(true, *allocator);
+ RegTypeCache cache_new(true, allocator);
constexpr int32_t kTestConstantValue = 10;
const RegType& long_lo_type = cache_new.LongLo();
@@ -583,8 +596,10 @@
TEST_F(RegTypeTest, MergingDouble) {
// Testing merging logic with double and double constants.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(true, *allocator);
+ RegTypeCache cache_new(true, allocator);
constexpr int32_t kTestConstantValue = 10;
const RegType& double_lo_type = cache_new.DoubleLo();
@@ -637,8 +652,10 @@
TEST_F(RegTypeTest, ConstPrecision) {
// Tests creating primitive types types.
+ ArenaStack stack(Runtime::Current()->GetArenaPool());
+ ScopedArenaAllocator allocator(&stack);
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache_new(true, *allocator);
+ RegTypeCache cache_new(true, allocator);
const RegType& imprecise_const = cache_new.FromCat1Const(10, false);
const RegType& precise_const = cache_new.FromCat1Const(10, true);