summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/dex_to_dex_compiler.cc4
-rw-r--r--compiler/dex/dex_to_dex_decompiler_test.cc7
-rw-r--r--compiler/driver/compiler_driver.cc20
-rw-r--r--compiler/exception_test.cc37
-rw-r--r--compiler/optimizing/intrinsics_arm_vixl.cc2
-rw-r--r--compiler/optimizing/stack_map_stream.cc101
-rw-r--r--compiler/optimizing/stack_map_stream.h12
-rw-r--r--compiler/optimizing/stack_map_test.cc4
-rw-r--r--compiler/verifier_deps_test.cc5
-rw-r--r--libdexfile/Android.bp1
-rw-r--r--libdexfile/dex/class_accessor-inl.h76
-rw-r--r--libdexfile/dex/class_accessor.h142
-rw-r--r--libdexfile/dex/class_accessor_test.cc79
-rw-r--r--libprofile/profile/profile_compilation_info_test.cc247
-rw-r--r--oatdump/oatdump.cc40
-rw-r--r--openjdkjvmti/ti_class.cc4
-rw-r--r--openjdkjvmti/ti_class_loader.h33
-rw-r--r--openjdkjvmti/ti_field.cc2
-rw-r--r--openjdkjvmti/ti_method.cc2
-rw-r--r--openjdkjvmti/ti_redefine.cc3
-rw-r--r--openjdkjvmti/ti_redefine.h18
-rw-r--r--profman/profman.cc4
-rw-r--r--runtime/Android.bp1
-rw-r--r--runtime/arch/stub_test.cc3
-rw-r--r--runtime/class_linker.cc59
-rw-r--r--runtime/class_linker.h4
-rw-r--r--runtime/dex/dex_file_annotations.cc68
-rw-r--r--runtime/dex/dex_file_annotations.h18
-rw-r--r--runtime/entrypoints/quick/quick_alloc_entrypoints.cc1
-rw-r--r--runtime/interpreter/interpreter_common.h3
-rw-r--r--runtime/interpreter/unstarted_runtime_test.cc14
-rw-r--r--runtime/jit/profiling_info_test.cc329
-rw-r--r--runtime/mirror/class.cc5
-rw-r--r--runtime/mirror/emulated_stack_frame.cc19
-rw-r--r--runtime/mirror/emulated_stack_frame.h10
-rw-r--r--runtime/mirror/object-inl.h2
-rw-r--r--runtime/mirror/stack_trace_element.cc21
-rw-r--r--runtime/mirror/stack_trace_element.h11
-rw-r--r--runtime/mirror/string-inl.h21
-rw-r--r--runtime/mirror/string.cc19
-rw-r--r--runtime/mirror/string.h28
-rw-r--r--runtime/mirror/throwable.cc21
-rw-r--r--runtime/mirror/throwable.h12
-rw-r--r--runtime/mirror/var_handle_test.cc28
-rw-r--r--runtime/native/java_lang_StringFactory.cc2
-rw-r--r--runtime/native/java_lang_VMClassLoader.cc1
-rw-r--r--runtime/oat.h4
-rw-r--r--runtime/quick_exception_handler.cc2
-rw-r--r--runtime/runtime.cc4
-rw-r--r--runtime/stack_map.cc2
-rw-r--r--runtime/stack_map.h39
-rw-r--r--runtime/thread.cc5
-rw-r--r--runtime/verifier/method_verifier.cc12
-rw-r--r--runtime/verifier/method_verifier.h2
-rw-r--r--runtime/verifier/reg_type.cc104
-rw-r--r--runtime/verifier/reg_type.h100
-rw-r--r--runtime/verifier/reg_type_cache-inl.h23
-rw-r--r--runtime/verifier/reg_type_cache.cc34
-rw-r--r--runtime/verifier/reg_type_cache.h18
-rw-r--r--runtime/verifier/verifier_deps.cc43
-rw-r--r--runtime/verifier/verifier_deps.h20
-rw-r--r--test/166-bad-interface-super/build13
-rw-r--r--test/166-bad-interface-super/smali/BadSuper1.smali (renamed from test/476-checker-ctor-fence-redun-elim/build)11
-rw-r--r--[-rwxr-xr-x]test/166-bad-interface-super/smali/BadSuper2.smali (renamed from test/450-checker-types/build)11
-rwxr-xr-xtest/dexdump/run-all-tests92
-rwxr-xr-xtest/etc/default-build3
-rwxr-xr-xtools/cleanup-buildbot-device.sh2
-rw-r--r--tools/dexanalyze/dexanalyze_experiments.cc4
-rwxr-xr-xtools/run-jdwp-tests.sh35
-rwxr-xr-xtools/run-libcore-tests.sh30
70 files changed, 1130 insertions, 1026 deletions
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 68155d844a..fb6a72b1c5 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -635,13 +635,13 @@ void DexToDexCompiler::SetDexFiles(const std::vector<const DexFile*>& dex_files)
std::unordered_set<const DexFile::CodeItem*> seen_code_items;
for (const DexFile* dex_file : dex_files) {
for (ClassAccessor accessor : dex_file->GetClasses()) {
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
const DexFile::CodeItem* code_item = method.GetCodeItem();
// Detect the shared code items.
if (!seen_code_items.insert(code_item).second) {
shared_code_items_.insert(code_item);
}
- });
+ }
}
}
VLOG(compiler) << "Shared code items " << shared_code_items_.size();
diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc
index 082e6091d2..75de238211 100644
--- a/compiler/dex/dex_to_dex_decompiler_test.cc
+++ b/compiler/dex/dex_to_dex_decompiler_test.cc
@@ -85,10 +85,9 @@ class DexToDexDecompilerTest : public CommonCompilerTest {
for (uint32_t i = 0; i < updated_dex_file->NumClassDefs(); ++i) {
// Unquicken each method.
ClassAccessor accessor(*updated_dex_file, updated_dex_file->GetClassDef(i));
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
CompiledMethod* compiled_method = compiler_driver_->GetCompiledMethod(
- MethodReference(updated_dex_file,
- method.GetIndex()));
+ method.GetReference());
ArrayRef<const uint8_t> table;
if (compiled_method != nullptr) {
table = compiled_method->GetVmapTable();
@@ -97,7 +96,7 @@ class DexToDexDecompilerTest : public CommonCompilerTest {
*accessor.GetCodeItem(method),
table,
/* decompile_return_instruction */ true);
- });
+ }
}
// Make sure after unquickening we go back to the same contents as the original dex file.
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index decb330f3b..16f2d0f2cc 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -790,8 +790,7 @@ static void ResolveConstStrings(CompilerDriver* driver,
// FIXME: Make sure that inlining honors this. b/26687569
continue;
}
- accessor.VisitMethods([&](const ClassAccessor::Method& method)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
// Resolve const-strings in the code. Done to have deterministic allocation behavior. Right
// now this is single-threaded for simplicity.
// TODO: Collect the relevant string indices in parallel, then allocate them sequentially
@@ -812,7 +811,7 @@ static void ResolveConstStrings(CompilerDriver* driver,
break;
}
}
- });
+ }
}
}
}
@@ -880,10 +879,9 @@ static void InitializeTypeCheckBitstrings(CompilerDriver* driver,
}
// Direct and virtual methods.
- accessor.VisitMethods([&](const ClassAccessor::Method& method)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
InitializeTypeCheckBitstrings(driver, class_linker, dex_cache, *dex_file, method);
- });
+ }
}
}
}
@@ -1949,9 +1947,9 @@ bool CompilerDriver::FastVerify(jobject jclass_loader,
// - We're only going to compile methods that did verify.
// - Quickening will not do checkcast ellision.
// TODO(ngeoffray): Reconsider this once we refactor compiler filters.
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
verification_results_->CreateVerifiedMethodFor(method.GetReference());
- });
+ }
}
} else if (!compiler_only_verifies) {
// Make sure later compilation stages know they should not try to verify
@@ -2747,12 +2745,12 @@ static void CompileDexFile(CompilerDriver* driver,
// Compile direct and virtual methods.
int64_t previous_method_idx = -1;
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
const uint32_t method_idx = method.GetIndex();
if (method_idx == previous_method_idx) {
// smali can create dex files with two encoded_methods sharing the same method_idx
// http://code.google.com/p/smali/issues/detail?id=119
- return;
+ continue;
}
previous_method_idx = method_idx;
compile_fn(soa.Self(),
@@ -2767,7 +2765,7 @@ static void CompileDexFile(CompilerDriver* driver,
dex_to_dex_compilation_level,
compilation_enabled,
dex_cache);
- });
+ }
};
context.ForAllLambda(0, dex_file.NumClassDefs(), compile, thread_count);
}
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index c139fcf1d8..da1db4593b 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -68,47 +68,38 @@ class ExceptionTest : public CommonRuntimeTest {
fake_code_.push_back(0x70 | i);
}
+ const uint32_t native_pc_offset = 4u;
+ CHECK_ALIGNED_PARAM(native_pc_offset, GetInstructionSetInstructionAlignment(kRuntimeISA));
+
MallocArenaPool pool;
ArenaStack arena_stack(&pool);
ScopedArenaAllocator allocator(&arena_stack);
StackMapStream stack_maps(&allocator, kRuntimeISA);
stack_maps.BeginStackMapEntry(kDexPc,
- /* native_pc_offset */ 3u,
+ native_pc_offset,
/* register_mask */ 0u,
/* sp_mask */ nullptr,
/* num_dex_registers */ 0u,
/* inlining_depth */ 0u);
stack_maps.EndStackMapEntry();
- size_t stack_maps_size = stack_maps.PrepareForFillIn();
- size_t stack_maps_offset = stack_maps_size + sizeof(OatQuickMethodHeader);
+ const size_t stack_maps_size = stack_maps.PrepareForFillIn();
+ const size_t header_size = sizeof(OatQuickMethodHeader);
+ const size_t code_alignment = GetInstructionSetAlignment(kRuntimeISA);
+ const size_t code_offset = RoundUp(stack_maps_size + header_size, code_alignment);
- fake_header_code_and_maps_.resize(stack_maps_offset + fake_code_.size());
+ fake_header_code_and_maps_.resize(code_offset + fake_code_.size());
MemoryRegion stack_maps_region(&fake_header_code_and_maps_[0], stack_maps_size);
stack_maps.FillInCodeInfo(stack_maps_region);
- OatQuickMethodHeader method_header(stack_maps_offset, 0u, 4 * sizeof(void*), 0u, 0u, code_size);
- memcpy(&fake_header_code_and_maps_[stack_maps_size], &method_header, sizeof(method_header));
+ OatQuickMethodHeader method_header(code_offset, 0u, 4 * sizeof(void*), 0u, 0u, code_size);
+ memcpy(&fake_header_code_and_maps_[code_offset - header_size], &method_header, header_size);
std::copy(fake_code_.begin(),
fake_code_.end(),
- fake_header_code_and_maps_.begin() + stack_maps_offset);
-
- // Align the code.
- const size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
- fake_header_code_and_maps_.reserve(fake_header_code_and_maps_.size() + alignment);
- const void* unaligned_code_ptr =
- fake_header_code_and_maps_.data() + (fake_header_code_and_maps_.size() - code_size);
- size_t offset = dchecked_integral_cast<size_t>(reinterpret_cast<uintptr_t>(unaligned_code_ptr));
- size_t padding = RoundUp(offset, alignment) - offset;
- // Make sure no resizing takes place.
- CHECK_GE(fake_header_code_and_maps_.capacity(), fake_header_code_and_maps_.size() + padding);
- fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(), padding, 0);
- const void* code_ptr = reinterpret_cast<const uint8_t*>(unaligned_code_ptr) + padding;
- CHECK_EQ(code_ptr,
- static_cast<const void*>(fake_header_code_and_maps_.data() +
- (fake_header_code_and_maps_.size() - code_size)));
+ fake_header_code_and_maps_.begin() + code_offset);
+ const void* code_ptr = fake_header_code_and_maps_.data() + code_offset;
if (kRuntimeISA == InstructionSet::kArm) {
// Check that the Thumb2 adjustment will be a NOP, see EntryPointToCodePointer().
- CHECK_ALIGNED(stack_maps_offset, 2);
+ CHECK_ALIGNED(code_ptr, 2);
}
method_f_ = my_klass_->FindClassMethod("f", "()I", kRuntimePointerSize);
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 5287b4b2fa..fecf1ccbfa 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -25,7 +25,7 @@
#include "mirror/array-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/reference.h"
-#include "mirror/string.h"
+#include "mirror/string-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index c6e375a1b2..b40ea3768a 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -48,10 +48,6 @@ void StackMapStream::BeginStackMapEntry(uint32_t dex_pc,
ArenaBitVector::Create(allocator_, num_dex_registers, true, kArenaAllocStackMapStream);
current_entry_.dex_register_entry.live_dex_registers_mask->ClearAllBits();
}
- if (sp_mask != nullptr) {
- stack_mask_max_ = std::max(stack_mask_max_, sp_mask->GetHighestBitSet());
- }
-
current_dex_register_ = 0;
}
@@ -217,11 +213,32 @@ size_t StackMapStream::PrepareForFillIn() {
PrepareMethodIndices();
// Dedup stack masks. Needs to be done first as it modifies the stack map entry.
- size_t stack_mask_bits = stack_mask_max_ + 1; // Need room for max element too.
- size_t num_stack_masks = PrepareStackMasks(stack_mask_bits);
+ BitmapTableBuilder stack_mask_builder(allocator_);
+ for (StackMapEntry& stack_map : stack_maps_) {
+ BitVector* mask = stack_map.sp_mask;
+ size_t num_bits = (mask != nullptr) ? mask->GetNumberOfBits() : 0;
+ if (num_bits != 0) {
+ stack_map.stack_mask_index = stack_mask_builder.Dedup(mask->GetRawStorage(), num_bits);
+ } else {
+ stack_map.stack_mask_index = StackMap::kNoValue;
+ }
+ }
// Dedup register masks. Needs to be done first as it modifies the stack map entry.
- size_t num_register_masks = PrepareRegisterMasks();
+ BitTableBuilder<std::array<uint32_t, RegisterMask::kCount>> register_mask_builder(allocator_);
+ for (StackMapEntry& stack_map : stack_maps_) {
+ uint32_t register_mask = stack_map.register_mask;
+ if (register_mask != 0) {
+ uint32_t shift = LeastSignificantBit(register_mask);
+ std::array<uint32_t, RegisterMask::kCount> entry = {
+ register_mask >> shift,
+ shift,
+ };
+ stack_map.register_mask_index = register_mask_builder.Dedup(&entry);
+ } else {
+ stack_map.register_mask_index = StackMap::kNoValue;
+ }
+ }
// Write dex register maps.
MemoryRegion dex_register_map_region =
@@ -301,31 +318,8 @@ size_t StackMapStream::PrepareForFillIn() {
stack_map_builder.Encode(&out_, &bit_offset);
invoke_info_builder.Encode(&out_, &bit_offset);
inline_info_builder.Encode(&out_, &bit_offset);
-
- // Write register masks table.
- BitTableBuilder<uint32_t> register_mask_builder(allocator_);
- for (size_t i = 0; i < num_register_masks; ++i) {
- register_mask_builder.Add(register_masks_[i]);
- }
register_mask_builder.Encode(&out_, &bit_offset);
-
- // Write stack masks table.
- EncodeVarintBits(&out_, &bit_offset, stack_mask_bits);
- out_.resize(BitsToBytesRoundUp(bit_offset + stack_mask_bits * num_stack_masks));
- BitMemoryRegion stack_mask_region(MemoryRegion(out_.data(), out_.size()),
- bit_offset,
- stack_mask_bits * num_stack_masks);
- if (stack_mask_bits > 0) {
- for (size_t i = 0; i < num_stack_masks; ++i) {
- size_t stack_mask_bytes = BitsToBytesRoundUp(stack_mask_bits);
- BitMemoryRegion src(MemoryRegion(&stack_masks_[i * stack_mask_bytes], stack_mask_bytes));
- BitMemoryRegion dst = stack_mask_region.Subregion(i * stack_mask_bits, stack_mask_bits);
- for (size_t bit_index = 0; bit_index < stack_mask_bits; bit_index += BitSizeOf<uint32_t>()) {
- size_t num_bits = std::min<size_t>(stack_mask_bits - bit_index, BitSizeOf<uint32_t>());
- dst.StoreBits(bit_index, src.LoadBits(bit_index, num_bits), num_bits);
- }
- }
- }
+ stack_mask_builder.Encode(&out_, &bit_offset);
return UnsignedLeb128Size(out_.size()) + out_.size();
}
@@ -448,17 +442,6 @@ void StackMapStream::CheckDexRegisterMap(const CodeInfo& code_info,
}
}
-size_t StackMapStream::PrepareRegisterMasks() {
- register_masks_.resize(stack_maps_.size(), 0u);
- ScopedArenaUnorderedMap<uint32_t, size_t> dedupe(allocator_->Adapter(kArenaAllocStackMapStream));
- for (StackMapEntry& stack_map : stack_maps_) {
- const size_t index = dedupe.size();
- stack_map.register_mask_index = dedupe.emplace(stack_map.register_mask, index).first->second;
- register_masks_[index] = stack_map.register_mask;
- }
- return dedupe.size();
-}
-
void StackMapStream::PrepareMethodIndices() {
CHECK(method_indices_.empty());
method_indices_.resize(stack_maps_.size() + inline_infos_.size());
@@ -481,35 +464,10 @@ void StackMapStream::PrepareMethodIndices() {
method_indices_.resize(dedupe.size());
}
-
-size_t StackMapStream::PrepareStackMasks(size_t entry_size_in_bits) {
- // Preallocate memory since we do not want it to move (the dedup map will point into it).
- const size_t byte_entry_size = RoundUp(entry_size_in_bits, kBitsPerByte) / kBitsPerByte;
- stack_masks_.resize(byte_entry_size * stack_maps_.size(), 0u);
- // For deduplicating we store the stack masks as byte packed for simplicity. We can bit pack later
- // when copying out from stack_masks_.
- ScopedArenaUnorderedMap<MemoryRegion,
- size_t,
- FNVHash<MemoryRegion>,
- MemoryRegion::ContentEquals> dedup(
- stack_maps_.size(), allocator_->Adapter(kArenaAllocStackMapStream));
- for (StackMapEntry& stack_map : stack_maps_) {
- size_t index = dedup.size();
- MemoryRegion stack_mask(stack_masks_.data() + index * byte_entry_size, byte_entry_size);
- BitMemoryRegion stack_mask_bits(stack_mask);
- for (size_t i = 0; i < entry_size_in_bits; i++) {
- stack_mask_bits.StoreBit(i, stack_map.sp_mask != nullptr && stack_map.sp_mask->IsBitSet(i));
- }
- stack_map.stack_mask_index = dedup.emplace(stack_mask, index).first->second;
- }
- return dedup.size();
-}
-
// Check that all StackMapStream inputs are correctly encoded by trying to read them back.
void StackMapStream::CheckCodeInfo(MemoryRegion region) const {
CodeInfo code_info(region);
DCHECK_EQ(code_info.GetNumberOfStackMaps(), stack_maps_.size());
- DCHECK_EQ(code_info.GetNumberOfStackMaskBits(), static_cast<uint32_t>(stack_mask_max_ + 1));
DCHECK_EQ(code_info.GetNumberOfLocationCatalogEntries(), location_catalog_entries_.size());
size_t invoke_info_index = 0;
for (size_t s = 0; s < stack_maps_.size(); ++s) {
@@ -522,18 +480,15 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const {
DCHECK_EQ(stack_map.GetDexPc(), entry.dex_pc);
DCHECK_EQ(stack_map.GetRegisterMaskIndex(), entry.register_mask_index);
DCHECK_EQ(code_info.GetRegisterMaskOf(stack_map), entry.register_mask);
- const size_t num_stack_mask_bits = code_info.GetNumberOfStackMaskBits();
DCHECK_EQ(stack_map.GetStackMaskIndex(), entry.stack_mask_index);
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
if (entry.sp_mask != nullptr) {
DCHECK_GE(stack_mask.size_in_bits(), entry.sp_mask->GetNumberOfBits());
- for (size_t b = 0; b < num_stack_mask_bits; b++) {
- DCHECK_EQ(stack_mask.LoadBit(b), entry.sp_mask->IsBitSet(b));
+ for (size_t b = 0; b < stack_mask.size_in_bits(); b++) {
+ DCHECK_EQ(stack_mask.LoadBit(b), entry.sp_mask->IsBitSet(b)) << b;
}
} else {
- for (size_t b = 0; b < num_stack_mask_bits; b++) {
- DCHECK_EQ(stack_mask.LoadBit(b), 0u);
- }
+ DCHECK_EQ(stack_mask.size_in_bits(), 0u);
}
if (entry.dex_method_index != dex::kDexNoIndex) {
InvokeInfo invoke_info = code_info.GetInvokeInfo(invoke_info_index);
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index ea97cf6530..19863d882a 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -68,11 +68,8 @@ class StackMapStream : public ValueObject {
location_catalog_entries_indices_(allocator->Adapter(kArenaAllocStackMapStream)),
dex_register_locations_(allocator->Adapter(kArenaAllocStackMapStream)),
inline_infos_(allocator->Adapter(kArenaAllocStackMapStream)),
- stack_masks_(allocator->Adapter(kArenaAllocStackMapStream)),
- register_masks_(allocator->Adapter(kArenaAllocStackMapStream)),
method_indices_(allocator->Adapter(kArenaAllocStackMapStream)),
dex_register_entries_(allocator->Adapter(kArenaAllocStackMapStream)),
- stack_mask_max_(-1),
out_(allocator->Adapter(kArenaAllocStackMapStream)),
dex_map_hash_to_stack_map_indices_(std::less<uint32_t>(),
allocator->Adapter(kArenaAllocStackMapStream)),
@@ -171,12 +168,6 @@ class StackMapStream : public ValueObject {
private:
size_t ComputeDexRegisterLocationCatalogSize() const;
- // Returns the number of unique stack masks.
- size_t PrepareStackMasks(size_t entry_size_in_bits);
-
- // Returns the number of unique register masks.
- size_t PrepareRegisterMasks();
-
// Prepare and deduplicate method indices.
void PrepareMethodIndices();
@@ -217,11 +208,8 @@ class StackMapStream : public ValueObject {
// A set of concatenated maps of Dex register locations indices to `location_catalog_entries_`.
ScopedArenaVector<size_t> dex_register_locations_;
ScopedArenaVector<InlineInfoEntry> inline_infos_;
- ScopedArenaVector<uint8_t> stack_masks_;
- ScopedArenaVector<uint32_t> register_masks_;
ScopedArenaVector<uint32_t> method_indices_;
ScopedArenaVector<DexRegisterMapEntry> dex_register_entries_;
- int stack_mask_max_;
ScopedArenaVector<uint8_t> out_;
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index 9db7588b3a..c372bb9b22 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -32,10 +32,10 @@ static bool CheckStackMask(
const StackMap& stack_map,
const BitVector& bit_vector) {
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
- if (bit_vector.GetNumberOfBits() > code_info.GetNumberOfStackMaskBits()) {
+ if (bit_vector.GetNumberOfBits() > stack_mask.size_in_bits()) {
return false;
}
- for (size_t i = 0; i < code_info.GetNumberOfStackMaskBits(); ++i) {
+ for (size_t i = 0; i < stack_mask.size_in_bits(); ++i) {
if (stack_mask.LoadBit(i) != bit_vector.IsBitSet(i)) {
return false;
}
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index 103862beff..c0892ff466 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -155,8 +155,7 @@ class VerifierDepsTest : public CommonCompilerTest {
bool has_failures = true;
bool found_method = false;
- accessor.VisitMethods([&](const ClassAccessor::Method& method)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
ArtMethod* resolved_method =
class_linker_->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
method.GetIndex(),
@@ -186,7 +185,7 @@ class VerifierDepsTest : public CommonCompilerTest {
has_failures = verifier.HasFailures();
found_method = true;
}
- });
+ }
CHECK(found_method) << "Expected to find method " << method_name;
return !has_failures;
}
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 3818624d7a..06fd19e2fe 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -112,6 +112,7 @@ art_cc_test {
],
srcs: [
"dex/art_dex_file_loader_test.cc",
+ "dex/class_accessor_test.cc",
"dex/code_item_accessors_test.cc",
"dex/compact_dex_file_test.cc",
"dex/compact_offset_table_test.cc",
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h
index a082142366..49ca98d47f 100644
--- a/libdexfile/dex/class_accessor-inl.h
+++ b/libdexfile/dex/class_accessor-inl.h
@@ -50,6 +50,19 @@ inline const uint8_t* ClassAccessor::Field::Read(const uint8_t* ptr) {
return ptr;
}
+template <typename DataType, typename Visitor>
+inline const uint8_t* ClassAccessor::VisitMembers(size_t count,
+ const Visitor& visitor,
+ const uint8_t* ptr,
+ DataType* data) const {
+ DCHECK(data != nullptr);
+ for ( ; count != 0; --count) {
+ ptr = data->Read(ptr);
+ visitor(*data);
+ }
+ return ptr;
+}
+
template <typename StaticFieldVisitor,
typename InstanceFieldVisitor,
typename DirectMethodVisitor,
@@ -59,35 +72,15 @@ inline void ClassAccessor::VisitFieldsAndMethods(
const InstanceFieldVisitor& instance_field_visitor,
const DirectMethodVisitor& direct_method_visitor,
const VirtualMethodVisitor& virtual_method_visitor) const {
- const uint8_t* ptr = ptr_pos_;
- {
- Field data;
- for (size_t i = 0; i < num_static_fields_; ++i) {
- ptr = data.Read(ptr);
- static_field_visitor(data);
- }
- }
- {
- Field data;
- for (size_t i = 0; i < num_instance_fields_; ++i) {
- ptr = data.Read(ptr);
- instance_field_visitor(data);
- }
- }
- {
- Method data(dex_file_, /*is_static_or_direct*/ true);
- for (size_t i = 0; i < num_direct_methods_; ++i) {
- ptr = data.Read(ptr);
- direct_method_visitor(data);
- }
- }
- {
- Method data(dex_file_, /*is_static_or_direct*/ false);
- for (size_t i = 0; i < num_virtual_methods_; ++i) {
- ptr = data.Read(ptr);
- virtual_method_visitor(data);
- }
- }
+ Field field(dex_file_);
+ const uint8_t* ptr = VisitMembers(num_static_fields_, static_field_visitor, ptr_pos_, &field);
+ field.NextSection();
+ ptr = VisitMembers(num_instance_fields_, instance_field_visitor, ptr, &field);
+
+ Method method(dex_file_, /*is_static_or_direct*/ true);
+ ptr = VisitMembers(num_direct_methods_, direct_method_visitor, ptr, &method);
+ method.NextSection();
+ ptr = VisitMembers(num_virtual_methods_, virtual_method_visitor, ptr, &method);
}
template <typename DirectMethodVisitor,
@@ -110,12 +103,6 @@ inline void ClassAccessor::VisitFields(const StaticFieldVisitor& static_field_vi
VoidFunctor());
}
-// Visit direct and virtual methods.
-template <typename MethodVisitor>
-inline void ClassAccessor::VisitMethods(const MethodVisitor& method_visitor) const {
- VisitMethods(method_visitor, method_visitor);
-}
-
inline const DexFile::CodeItem* ClassAccessor::GetCodeItem(const Method& method) const {
return dex_file_.GetCodeItem(method.GetCodeItemOffset());
}
@@ -132,6 +119,25 @@ inline const DexFile::CodeItem* ClassAccessor::Method::GetCodeItem() const {
return dex_file_.GetCodeItem(code_off_);
}
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields()
+ const {
+ const uint32_t limit = num_static_fields_ + num_instance_fields_;
+ return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, limit, ptr_pos_),
+ DataIterator<Field>(dex_file_, limit, num_static_fields_, limit, ptr_pos_) };
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+ ClassAccessor::GetMethods() const {
+ // Skip over the fields.
+ Field field(dex_file_);
+ const size_t skip_count = num_static_fields_ + num_instance_fields_;
+ const uint8_t* ptr_pos = VisitMembers(skip_count, VoidFunctor(), ptr_pos_, &field);
+ // Return the iterator pair for all the methods.
+ const uint32_t limit = num_direct_methods_ + num_virtual_methods_;
+ return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, limit, ptr_pos),
+ DataIterator<Method>(dex_file_, limit, num_direct_methods_, limit, ptr_pos) };
+}
+
} // namespace art
#endif // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index 72bc50b98c..dda6e1c1a6 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -45,7 +45,7 @@ class ClassAccessor {
return (GetAccessFlags() & kAccFinal) != 0;
}
- public:
+ protected:
uint32_t index_ = 0u;
uint32_t access_flags_ = 0u;
};
@@ -72,8 +72,13 @@ class ClassAccessor {
const DexFile::CodeItem* GetCodeItem() const;
+ bool IsStaticOrDirect() const {
+ return is_static_or_direct_;
+ }
+
private:
- explicit Method(const DexFile& dex_file, bool is_static_or_direct)
+ explicit Method(const DexFile& dex_file,
+ bool is_static_or_direct = true)
: dex_file_(dex_file),
is_static_or_direct_(is_static_or_direct) {}
@@ -94,8 +99,14 @@ class ClassAccessor {
}
}
+ void NextSection() {
+ DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
+ is_static_or_direct_ = false;
+ index_ = 0u;
+ }
+
const DexFile& dex_file_;
- const bool is_static_or_direct_;
+ bool is_static_or_direct_ = true;
uint32_t code_off_ = 0u;
friend class ClassAccessor;
@@ -103,12 +114,113 @@ class ClassAccessor {
// A decoded version of the field of a class_data_item.
class Field : public BaseItem {
+ public:
+ explicit Field(const DexFile& dex_file) : dex_file_(dex_file) {}
+
+ const DexFile& GetDexFile() const {
+ return dex_file_;
+ }
+
private:
const uint8_t* Read(const uint8_t* ptr);
+ void NextSection() {
+ index_ = 0u;
+ }
+
+ const DexFile& dex_file_;
friend class ClassAccessor;
};
+ template <typename DataType>
+ class DataIterator : public std::iterator<std::forward_iterator_tag, DataType> {
+ public:
+ using value_type = typename std::iterator<std::forward_iterator_tag, DataType>::value_type;
+ using difference_type =
+ typename std::iterator<std::forward_iterator_tag, value_type>::difference_type;
+
+ DataIterator(const DexFile& dex_file,
+ uint32_t position,
+ uint32_t partition_pos,
+ uint32_t iterator_end,
+ const uint8_t* ptr_pos)
+ : data_(dex_file),
+ position_(position),
+ partition_pos_(partition_pos),
+ iterator_end_(iterator_end),
+ ptr_pos_(ptr_pos) {
+ ReadData();
+ }
+
+ bool IsValid() const {
+ return position_ < iterator_end_;
+ }
+
+ // Value after modification.
+ DataIterator& operator++() {
+ ++position_;
+ ReadData();
+ return *this;
+ }
+
+ const value_type& operator*() const {
+ return data_;
+ }
+
+ const value_type* operator->() const {
+ return &data_;
+ }
+
+ bool operator==(const DataIterator& rhs) const {
+ DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
+ return position_ == rhs.position_;
+ }
+
+ bool operator!=(const DataIterator& rhs) const {
+ return !(*this == rhs);
+ }
+
+ bool operator<(const DataIterator& rhs) const {
+ DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
+ return position_ < rhs.position_;
+ }
+
+ bool operator>(const DataIterator& rhs) const {
+ return rhs < *this;
+ }
+
+ bool operator<=(const DataIterator& rhs) const {
+ return !(rhs < *this);
+ }
+
+ bool operator>=(const DataIterator& rhs) const {
+ return !(*this < rhs);
+ }
+
+ private:
+ // Read data at current position.
+ void ReadData() {
+ if (IsValid()) {
+ // At the end of the first section, go to the next section.
+ if (position_ == partition_pos_) {
+ data_.NextSection();
+ }
+ DCHECK(ptr_pos_ != nullptr);
+ ptr_pos_ = data_.Read(ptr_pos_);
+ }
+ }
+
+ DataType data_;
+ // Iterator position.
+ uint32_t position_;
+ // At partition_pos_, we go to the next section.
+ const uint32_t partition_pos_;
+ // At iterator_end_, the iterator is no longer valid.
+ const uint32_t iterator_end_;
+ // Internal data pointer.
+ const uint8_t* ptr_pos_;
+ };
+
// Not explicit specifically for range-based loops.
ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data);
@@ -118,7 +230,6 @@ class ClassAccessor {
const DexFile::CodeItem* GetCodeItem(const Method& method) const;
// Iterator data is not very iterator friendly, use visitors to get around this.
- // No thread safety analysis since the visitor may require capabilities.
template <typename StaticFieldVisitor,
typename InstanceFieldVisitor,
typename DirectMethodVisitor,
@@ -126,8 +237,7 @@ class ClassAccessor {
void VisitFieldsAndMethods(const StaticFieldVisitor& static_field_visitor,
const InstanceFieldVisitor& instance_field_visitor,
const DirectMethodVisitor& direct_method_visitor,
- const VirtualMethodVisitor& virtual_method_visitor) const
- NO_THREAD_SAFETY_ANALYSIS;
+ const VirtualMethodVisitor& virtual_method_visitor) const;
template <typename DirectMethodVisitor,
typename VirtualMethodVisitor>
@@ -139,9 +249,11 @@ class ClassAccessor {
void VisitFields(const StaticFieldVisitor& static_field_visitor,
const InstanceFieldVisitor& instance_field_visitor) const;
- // Visit direct and virtual methods.
- template <typename MethodVisitor>
- void VisitMethods(const MethodVisitor& method_visitor) const;
+ // Return the iteration range for all the fields.
+ IterationRange<DataIterator<Field>> GetFields() const;
+
+ // Return the iteration range for all the methods.
+ IterationRange<DataIterator<Method>> GetMethods() const;
uint32_t NumStaticFields() const {
return num_static_fields_;
@@ -159,6 +271,10 @@ class ClassAccessor {
return num_virtual_methods_;
}
+ uint32_t NumMethods() const {
+ return NumDirectMethods() + NumVirtualMethods();
+ }
+
const char* GetDescriptor() const;
dex::TypeIndex GetClassIdx() const {
@@ -170,6 +286,14 @@ class ClassAccessor {
}
protected:
+ // Template visitor to reduce copy paste for visiting elements.
+ // No thread safety analysis since the visitor may require capabilities.
+ template <typename DataType, typename Visitor>
+ const uint8_t* VisitMembers(size_t count,
+ const Visitor& visitor,
+ const uint8_t* ptr,
+ DataType* data) const NO_THREAD_SAFETY_ANALYSIS;
+
const DexFile& dex_file_;
const dex::TypeIndex descriptor_index_ = {};
const uint8_t* ptr_pos_ = nullptr; // Pointer into stream of class_data_item.
diff --git a/libdexfile/dex/class_accessor_test.cc b/libdexfile/dex/class_accessor_test.cc
new file mode 100644
index 0000000000..95380d8140
--- /dev/null
+++ b/libdexfile/dex/class_accessor_test.cc
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 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 "dex/class_accessor-inl.h"
+
+#include "base/common_art_test.h"
+
+namespace art {
+
+class ClassAccessorTest : public CommonArtTest {};
+
+TEST_F(ClassAccessorTest, TestVisiting) {
+ std::vector<std::unique_ptr<const DexFile>> dex_files(
+ OpenDexFiles(GetLibCoreDexFileNames()[0].c_str()));
+ ASSERT_GT(dex_files.size(), 0u);
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ uint32_t class_def_idx = 0u;
+ ASSERT_GT(dex_file->NumClassDefs(), 0u);
+ for (ClassAccessor accessor : dex_file->GetClasses()) {
+ const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx);
+ EXPECT_EQ(accessor.GetDescriptor(), dex_file->StringByTypeIdx(class_def.class_idx_));
+ ++class_def_idx;
+ // Check iterators against visitors.
+ auto methods = accessor.GetMethods();
+ auto fields = accessor.GetFields();
+ auto method_it = methods.begin();
+ auto field_it = fields.begin();
+ accessor.VisitFieldsAndMethods(
+ // Static fields.
+ [&](const ClassAccessor::Field& field) {
+ EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
+ EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
+ ++field_it;
+ },
+ // Instance fields.
+ [&](const ClassAccessor::Field& field) {
+ EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
+ EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
+ ++field_it;
+ },
+ // Direct methods.
+ [&](const ClassAccessor::Method& method) {
+ EXPECT_TRUE(method.IsStaticOrDirect());
+ EXPECT_EQ(method.IsStaticOrDirect(), method_it->IsStaticOrDirect());
+ EXPECT_EQ(method.GetIndex(), method_it->GetIndex());
+ EXPECT_EQ(method.GetAccessFlags(), method_it->GetAccessFlags());
+ EXPECT_EQ(method.GetCodeItem(), method_it->GetCodeItem());
+ ++method_it;
+ },
+ // Virtual methods.
+ [&](const ClassAccessor::Method& method) {
+ EXPECT_FALSE(method.IsStaticOrDirect());
+ EXPECT_EQ(method.IsStaticOrDirect(), method_it->IsStaticOrDirect());
+ EXPECT_EQ(method.GetIndex(), method_it->GetIndex());
+ EXPECT_EQ(method.GetAccessFlags(), method_it->GetAccessFlags());
+ EXPECT_EQ(method.GetCodeItem(), method_it->GetCodeItem());
+ ++method_it;
+ });
+ ASSERT_TRUE(field_it == fields.end());
+ ASSERT_TRUE(method_it == methods.end());
+ }
+ EXPECT_EQ(class_def_idx, dex_file->NumClassDefs());
+ }
+}
+
+} // namespace art
diff --git a/libprofile/profile/profile_compilation_info_test.cc b/libprofile/profile/profile_compilation_info_test.cc
index ead7cba60b..42c3320ea5 100644
--- a/libprofile/profile/profile_compilation_info_test.cc
+++ b/libprofile/profile/profile_compilation_info_test.cc
@@ -17,20 +17,14 @@
#include <gtest/gtest.h>
#include <stdio.h>
-#include "art_method-inl.h"
+#include "base/arena_allocator.h"
+#include "base/common_art_test.h"
#include "base/unix_file/fd_file.h"
-#include "class_linker-inl.h"
-#include "common_runtime_test.h"
#include "dex/dex_file.h"
#include "dex/dex_file_loader.h"
#include "dex/method_reference.h"
#include "dex/type_reference.h"
-#include "handle_scope-inl.h"
-#include "linear_alloc.h"
-#include "mirror/class-inl.h"
-#include "mirror/class_loader.h"
#include "profile/profile_compilation_info.h"
-#include "scoped_thread_state_change-inl.h"
#include "ziparchive/zip_writer.h"
namespace art {
@@ -39,31 +33,14 @@ using Hotness = ProfileCompilationInfo::MethodHotness;
static constexpr size_t kMaxMethodIds = 65535;
-class ProfileCompilationInfoTest : public CommonRuntimeTest {
+class ProfileCompilationInfoTest : public CommonArtTest {
public:
- void PostRuntimeCreate() OVERRIDE {
- allocator_.reset(new ArenaAllocator(Runtime::Current()->GetArenaPool()));
+ void SetUp() OVERRIDE {
+ CommonArtTest::SetUp();
+ allocator_.reset(new ArenaAllocator(&pool_));
}
protected:
- std::vector<ArtMethod*> GetVirtualMethods(jobject class_loader,
- const std::string& clazz) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Thread* self = Thread::Current();
- ScopedObjectAccess soa(self);
- StackHandleScope<1> hs(self);
- Handle<mirror::ClassLoader> h_loader(
- hs.NewHandle(self->DecodeJObject(class_loader)->AsClassLoader()));
- ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
-
- const auto pointer_size = class_linker->GetImagePointerSize();
- std::vector<ArtMethod*> methods;
- for (auto& m : klass->GetVirtualMethods(pointer_size)) {
- methods.push_back(&m);
- }
- return methods;
- }
-
bool AddMethod(const std::string& dex_location,
uint32_t checksum,
uint16_t method_index,
@@ -97,89 +74,6 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
return static_cast<uint32_t>(file.GetFd());
}
- bool SaveProfilingInfo(
- const std::string& filename,
- const std::vector<ArtMethod*>& methods,
- const std::set<DexCacheResolvedClasses>& resolved_classes,
- Hotness::Flag flags) {
- ProfileCompilationInfo info;
- std::vector<ProfileMethodInfo> profile_methods;
- ScopedObjectAccess soa(Thread::Current());
- for (ArtMethod* method : methods) {
- profile_methods.emplace_back(
- MethodReference(method->GetDexFile(), method->GetDexMethodIndex()));
- }
- if (!info.AddMethods(profile_methods, flags) || !info.AddClasses(resolved_classes)) {
- return false;
- }
- if (info.GetNumberOfMethods() != profile_methods.size()) {
- return false;
- }
- ProfileCompilationInfo file_profile;
- if (!file_profile.Load(filename, false)) {
- return false;
- }
- if (!info.MergeWith(file_profile)) {
- return false;
- }
-
- return info.Save(filename, nullptr);
- }
-
- // Saves the given art methods to a profile backed by 'filename' and adds
- // some fake inline caches to it. The added inline caches are returned in
- // the out map `profile_methods_map`.
- bool SaveProfilingInfoWithFakeInlineCaches(
- const std::string& filename,
- const std::vector<ArtMethod*>& methods,
- Hotness::Flag flags,
- /*out*/ SafeMap<ArtMethod*, ProfileMethodInfo>* profile_methods_map) {
- ProfileCompilationInfo info;
- std::vector<ProfileMethodInfo> profile_methods;
- ScopedObjectAccess soa(Thread::Current());
- for (ArtMethod* method : methods) {
- std::vector<ProfileMethodInfo::ProfileInlineCache> caches;
- // Monomorphic
- for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) {
- std::vector<TypeReference> classes;
- classes.emplace_back(method->GetDexFile(), dex::TypeIndex(0));
- caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
- }
- // Polymorphic
- for (uint16_t dex_pc = 11; dex_pc < 22; dex_pc++) {
- std::vector<TypeReference> classes;
- for (uint16_t k = 0; k < InlineCache::kIndividualCacheSize / 2; k++) {
- classes.emplace_back(method->GetDexFile(), dex::TypeIndex(k));
- }
- caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
- }
- // Megamorphic
- for (uint16_t dex_pc = 22; dex_pc < 33; dex_pc++) {
- std::vector<TypeReference> classes;
- for (uint16_t k = 0; k < 2 * InlineCache::kIndividualCacheSize; k++) {
- classes.emplace_back(method->GetDexFile(), dex::TypeIndex(k));
- }
- caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
- }
- // Missing types
- for (uint16_t dex_pc = 33; dex_pc < 44; dex_pc++) {
- std::vector<TypeReference> classes;
- caches.emplace_back(dex_pc, /*is_missing_types*/true, classes);
- }
- ProfileMethodInfo pmi(MethodReference(method->GetDexFile(),
- method->GetDexMethodIndex()),
- caches);
- profile_methods.push_back(pmi);
- profile_methods_map->Put(method, pmi);
- }
-
- if (!info.AddMethods(profile_methods, flags)
- || info.GetNumberOfMethods() != profile_methods.size()) {
- return false;
- }
- return info.Save(filename, nullptr);
- }
-
// Creates an inline cache which will be destructed at the end of the test.
ProfileCompilationInfo::InlineCacheMap* CreateInlineCacheMap() {
used_inline_caches.emplace_back(new ProfileCompilationInfo::InlineCacheMap(
@@ -187,35 +81,6 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
return used_inline_caches.back().get();
}
- ProfileCompilationInfo::OfflineProfileMethodInfo ConvertProfileMethodInfo(
- const ProfileMethodInfo& pmi) {
- ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap();
- ProfileCompilationInfo::OfflineProfileMethodInfo offline_pmi(ic_map);
- SafeMap<DexFile*, uint8_t> dex_map; // dex files to profile index
- for (const auto& inline_cache : pmi.inline_caches) {
- ProfileCompilationInfo::DexPcData& dex_pc_data =
- ic_map->FindOrAdd(
- inline_cache.dex_pc, ProfileCompilationInfo::DexPcData(allocator_.get()))->second;
- if (inline_cache.is_missing_types) {
- dex_pc_data.SetIsMissingTypes();
- }
- for (const auto& class_ref : inline_cache.classes) {
- uint8_t dex_profile_index = dex_map.FindOrAdd(const_cast<DexFile*>(class_ref.dex_file),
- static_cast<uint8_t>(dex_map.size()))->second;
- dex_pc_data.AddClass(dex_profile_index, class_ref.TypeIndex());
- if (dex_profile_index >= offline_pmi.dex_references.size()) {
- // This is a new dex.
- const std::string& dex_key = ProfileCompilationInfo::GetProfileDexFileKey(
- class_ref.dex_file->GetLocation());
- offline_pmi.dex_references.emplace_back(dex_key,
- class_ref.dex_file->GetLocationChecksum(),
- class_ref.dex_file->NumMethodIds());
- }
- }
- }
- return offline_pmi;
- }
-
// Creates an offline profile used for testing inline caches.
ProfileCompilationInfo::OfflineProfileMethodInfo GetOfflineProfileMethodInfo() {
ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap();
@@ -261,7 +126,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
ProfileCompilationInfo::InlineCacheMap* ic_map =
const_cast<ProfileCompilationInfo::InlineCacheMap*>(pmi->inline_caches);
for (auto it : *ic_map) {
- for (uint16_t k = 0; k <= 2 * InlineCache::kIndividualCacheSize; k++) {
+ for (uint16_t k = 0; k <= 2 * ProfileCompilationInfo::kIndividualInlineCacheSize; k++) {
it.second.AddClass(0, dex::TypeIndex(k));
}
}
@@ -327,6 +192,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
static constexpr int kProfileMagicSize = 4;
static constexpr int kProfileVersionSize = 4;
+ MallocArenaPool pool_;
std::unique_ptr<ArenaAllocator> allocator_;
// Cache of inline caches generated during tests.
@@ -335,61 +201,6 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest {
std::vector<std::unique_ptr<ProfileCompilationInfo::InlineCacheMap>> used_inline_caches;
};
-TEST_F(ProfileCompilationInfoTest, SaveArtMethods) {
- ScratchFile profile;
-
- Thread* self = Thread::Current();
- jobject class_loader;
- {
- ScopedObjectAccess soa(self);
- class_loader = LoadDex("ProfileTestMultiDex");
- }
- ASSERT_NE(class_loader, nullptr);
-
- // Save virtual methods from Main.
- std::set<DexCacheResolvedClasses> resolved_classes;
- std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
- ASSERT_TRUE(SaveProfilingInfo(
- profile.GetFilename(), main_methods, resolved_classes, Hotness::kFlagPostStartup));
-
- // Check that what we saved is in the profile.
- ProfileCompilationInfo info1;
- ASSERT_TRUE(info1.Load(GetFd(profile)));
- ASSERT_EQ(info1.GetNumberOfMethods(), main_methods.size());
- {
- ScopedObjectAccess soa(self);
- for (ArtMethod* m : main_methods) {
- Hotness h = info1.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
- ASSERT_TRUE(h.IsHot());
- ASSERT_TRUE(h.IsPostStartup());
- }
- }
-
- // Save virtual methods from Second.
- std::vector<ArtMethod*> second_methods = GetVirtualMethods(class_loader, "LSecond;");
- ASSERT_TRUE(SaveProfilingInfo(
- profile.GetFilename(), second_methods, resolved_classes, Hotness::kFlagStartup));
-
- // Check that what we saved is in the profile (methods form Main and Second).
- ProfileCompilationInfo info2;
- ASSERT_TRUE(profile.GetFile()->ResetOffset());
- ASSERT_TRUE(info2.Load(GetFd(profile)));
- ASSERT_EQ(info2.GetNumberOfMethods(), main_methods.size() + second_methods.size());
- {
- ScopedObjectAccess soa(self);
- for (ArtMethod* m : main_methods) {
- Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
- ASSERT_TRUE(h.IsHot());
- ASSERT_TRUE(h.IsPostStartup());
- }
- for (ArtMethod* m : second_methods) {
- Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
- ASSERT_TRUE(h.IsHot());
- ASSERT_TRUE(h.IsStartup());
- }
- }
-}
-
TEST_F(ProfileCompilationInfoTest, SaveFd) {
ScratchFile profile;
@@ -722,48 +533,6 @@ TEST_F(ProfileCompilationInfoTest, MissingTypesInlineCaches) {
ASSERT_TRUE(*loaded_pmi1 == pmi_extra);
}
-TEST_F(ProfileCompilationInfoTest, SaveArtMethodsWithInlineCaches) {
- ScratchFile profile;
-
- Thread* self = Thread::Current();
- jobject class_loader;
- {
- ScopedObjectAccess soa(self);
- class_loader = LoadDex("ProfileTestMultiDex");
- }
- ASSERT_NE(class_loader, nullptr);
-
- // Save virtual methods from Main.
- std::set<DexCacheResolvedClasses> resolved_classes;
- std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
-
- SafeMap<ArtMethod*, ProfileMethodInfo> profile_methods_map;
- ASSERT_TRUE(SaveProfilingInfoWithFakeInlineCaches(
- profile.GetFilename(), main_methods, Hotness::kFlagStartup, &profile_methods_map));
-
- // Check that what we saved is in the profile.
- ProfileCompilationInfo info;
- ASSERT_TRUE(info.Load(GetFd(profile)));
- ASSERT_EQ(info.GetNumberOfMethods(), main_methods.size());
- {
- ScopedObjectAccess soa(self);
- for (ArtMethod* m : main_methods) {
- Hotness h = info.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
- ASSERT_TRUE(h.IsHot());
- ASSERT_TRUE(h.IsStartup());
- const ProfileMethodInfo& pmi = profile_methods_map.find(m)->second;
- std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_pmi =
- info.GetMethod(m->GetDexFile()->GetLocation(),
- m->GetDexFile()->GetLocationChecksum(),
- m->GetDexMethodIndex());
- ASSERT_TRUE(offline_pmi != nullptr);
- ProfileCompilationInfo::OfflineProfileMethodInfo converted_pmi =
- ConvertProfileMethodInfo(pmi);
- ASSERT_EQ(converted_pmi, *offline_pmi);
- }
- }
-}
-
TEST_F(ProfileCompilationInfoTest, InvalidChecksumInInlineCache) {
ScratchFile profile;
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index fcd6bfd46c..6688cc1bb9 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -45,6 +45,7 @@
#include "debug/debug_info.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
+#include "dex/class_accessor-inl.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
@@ -268,25 +269,18 @@ class OatSymbolizer FINAL {
void WalkOatClass(const OatFile::OatClass& oat_class,
const DexFile& dex_file,
uint32_t class_def_index) {
- const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
- const uint8_t* class_data = dex_file.GetClassData(class_def);
- if (class_data == nullptr) { // empty class such as a marker interface?
- return;
- }
+ ClassAccessor accessor(dex_file, dex_file.GetClassDef(class_def_index));
// Note: even if this is an interface or a native class, we still have to walk it, as there
// might be a static initializer.
- ClassDataItemIterator it(dex_file, class_data);
uint32_t class_method_idx = 0;
- it.SkipAllFields();
- for (; it.HasNextMethod(); it.Next()) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
WalkOatMethod(oat_class.GetOatMethod(class_method_idx++),
dex_file,
class_def_index,
- it.GetMemberIndex(),
- it.GetMethodCodeItem(),
- it.GetMethodAccessFlags());
+ method.GetIndex(),
+ method.GetCodeItem(),
+ method.GetAccessFlags());
}
- DCHECK(!it.HasNext());
}
void WalkOatMethod(const OatFile::OatMethod& oat_method,
@@ -904,21 +898,15 @@ class OatDumper {
continue;
}
offsets_.insert(reinterpret_cast<uintptr_t>(&dex_file->GetHeader()));
- for (size_t class_def_index = 0;
- class_def_index < dex_file->NumClassDefs();
- class_def_index++) {
- const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
+ uint32_t class_def_index = 0u;
+ for (ClassAccessor accessor : dex_file->GetClasses()) {
const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
- const uint8_t* class_data = dex_file->GetClassData(class_def);
- if (class_data != nullptr) {
- ClassDataItemIterator it(*dex_file, class_data);
- it.SkipAllFields();
- uint32_t class_method_index = 0;
- while (it.HasNextMethod()) {
- AddOffsets(oat_class.GetOatMethod(class_method_index++));
- it.Next();
- }
+ for (uint32_t class_method_index = 0;
+ class_method_index < accessor.NumMethods();
+ ++class_method_index) {
+ AddOffsets(oat_class.GetOatMethod(class_method_index));
}
+ ++class_def_index;
}
}
@@ -1731,7 +1719,7 @@ class OatDumper {
// Stack masks
stats_.AddBits(
Stats::kByteKindCodeInfoStackMasks,
- code_info.stack_masks_.size_in_bits());
+ code_info.stack_masks_.DataBitSize());
// Register masks
stats_.AddBits(
diff --git a/openjdkjvmti/ti_class.cc b/openjdkjvmti/ti_class.cc
index 726e47ed5f..9bea18a763 100644
--- a/openjdkjvmti/ti_class.cc
+++ b/openjdkjvmti/ti_class.cc
@@ -71,9 +71,11 @@
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"
#include "thread_list.h"
+#include "ti_class_definition.h"
#include "ti_class_loader-inl.h"
#include "ti_phase.h"
#include "ti_redefine.h"
+#include "transform.h"
#include "well_known_classes.h"
namespace openjdkjvmti {
@@ -713,7 +715,7 @@ jvmtiError ClassUtil::GetClassSignature(jvmtiEnv* env,
if (!klass->IsProxyClass() && klass->GetDexCache() != nullptr) {
art::StackHandleScope<1> hs(soa.Self());
art::Handle<art::mirror::Class> h_klass = hs.NewHandle(klass);
- art::mirror::ObjectArray<art::mirror::String>* str_array =
+ art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
art::annotations::GetSignatureAnnotationForClass(h_klass);
if (str_array != nullptr) {
std::ostringstream oss;
diff --git a/openjdkjvmti/ti_class_loader.h b/openjdkjvmti/ti_class_loader.h
index a3857e595a..577c28585e 100644
--- a/openjdkjvmti/ti_class_loader.h
+++ b/openjdkjvmti/ti_class_loader.h
@@ -36,32 +36,19 @@
#include <jni.h>
-#include "art_jvmti.h"
-#include "art_method.h"
-#include "base/array_slice.h"
#include "base/globals.h"
-#include "base/mem_map.h"
-#include "class_linker.h"
-#include "dex/dex_file.h"
-#include "dex/utf.h"
-#include "gc_root-inl.h"
-#include "jni/jni_env_ext-inl.h"
+#include "base/mutex.h"
#include "jvmti.h"
-#include "linear_alloc.h"
-#include "mirror/array-inl.h"
#include "mirror/array.h"
-#include "mirror/class-inl.h"
-#include "mirror/class.h"
-#include "mirror/class_loader-inl.h"
-#include "mirror/string-inl.h"
-#include "oat_file.h"
-#include "obj_ptr.h"
-#include "scoped_thread_state_change-inl.h"
-#include "stack.h"
-#include "thread_list.h"
-#include "ti_class_definition.h"
-#include "transform.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
+
+namespace art {
+
+class DexFile;
+template <class MirrorType> class Handle;
+template <class MirrorType> class ObjPtr;
+class Thread;
+
+} // namespace art
namespace openjdkjvmti {
diff --git a/openjdkjvmti/ti_field.cc b/openjdkjvmti/ti_field.cc
index 328e2a1e40..2a860d9f43 100644
--- a/openjdkjvmti/ti_field.cc
+++ b/openjdkjvmti/ti_field.cc
@@ -91,7 +91,7 @@ jvmtiError FieldUtil::GetFieldName(jvmtiEnv* env,
if (generic_ptr != nullptr) {
*generic_ptr = nullptr;
if (!art_field->GetDeclaringClass()->IsProxyClass()) {
- art::mirror::ObjectArray<art::mirror::String>* str_array =
+ art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
art::annotations::GetSignatureAnnotationForField(art_field);
if (str_array != nullptr) {
std::ostringstream oss;
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index c0c312c490..d0b7224f93 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -345,7 +345,7 @@ jvmtiError MethodUtil::GetMethodName(jvmtiEnv* env,
if (generic_ptr != nullptr) {
*generic_ptr = nullptr;
if (!art_method->GetDeclaringClass()->IsProxyClass()) {
- art::mirror::ObjectArray<art::mirror::String>* str_array =
+ art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
art::annotations::GetSignatureAnnotationForMethod(art_method);
if (str_array != nullptr) {
std::ostringstream oss;
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 48e2958773..73e37199ed 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -61,6 +61,7 @@
#include "jit/jit_code_cache.h"
#include "jni/jni_env_ext-inl.h"
#include "jvmti_allocator.h"
+#include "linear_alloc.h"
#include "mirror/class-inl.h"
#include "mirror/class_ext.h"
#include "mirror/object.h"
@@ -68,6 +69,8 @@
#include "non_debuggable_classes.h"
#include "object_lock.h"
#include "runtime.h"
+#include "stack.h"
+#include "thread_list.h"
#include "ti_breakpoint.h"
#include "ti_class_loader.h"
#include "transform.h"
diff --git a/openjdkjvmti/ti_redefine.h b/openjdkjvmti/ti_redefine.h
index 227eacd180..e337491ae3 100644
--- a/openjdkjvmti/ti_redefine.h
+++ b/openjdkjvmti/ti_redefine.h
@@ -37,34 +37,18 @@
#include <jni.h>
#include "art_jvmti.h"
-#include "art_method.h"
#include "base/array_ref.h"
#include "base/globals.h"
-#include "base/mem_map.h"
-#include "class_linker.h"
#include "dex/dex_file.h"
-#include "dex/utf.h"
-#include "gc_root-inl.h"
#include "jni/jni_env_ext-inl.h"
#include "jvmti.h"
-#include "linear_alloc.h"
-#include "mirror/array-inl.h"
#include "mirror/array.h"
-#include "mirror/class-inl.h"
#include "mirror/class.h"
-#include "mirror/class_loader-inl.h"
-#include "mirror/string-inl.h"
-#include "oat_file.h"
#include "obj_ptr.h"
-#include "scoped_thread_state_change-inl.h"
-#include "stack.h"
-#include "thread_list.h"
-#include "ti_class_definition.h"
-#include "transform.h"
-#include "utils/dex_cache_arrays_layout-inl.h"
namespace openjdkjvmti {
+class ArtClassDefinition;
class RedefinitionDataHolder;
class RedefinitionDataIter;
diff --git a/profman/profman.cc b/profman/profman.cc
index 661132d94f..096e5dc3bd 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -931,12 +931,12 @@ class ProfMan FINAL {
std::vector<ProfileMethodInfo> methods;
if (method_str == kClassAllMethods) {
ClassAccessor accessor(*dex_file, *dex_file->FindClassDef(class_ref.TypeIndex()));
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
if (method.GetCodeItemOffset() != 0) {
// Add all of the methods that have code to the profile.
methods.push_back(ProfileMethodInfo(method.GetReference()));
}
- });
+ }
}
// TODO: Check return values?
profile->AddMethods(methods, static_cast<ProfileCompilationInfo::MethodHotness::Flag>(flags));
diff --git a/runtime/Android.bp b/runtime/Android.bp
index b276c81d5a..777a1fc5ee 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -574,6 +574,7 @@ art_cc_test {
"interpreter/safe_math_test.cc",
"interpreter/unstarted_runtime_test.cc",
"jdwp/jdwp_options_test.cc",
+ "jit/profiling_info_test.cc",
"jni/java_vm_ext_test.cc",
"method_handles_test.cc",
"mirror/dex_cache_test.cc",
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 78516e3aeb..b0c0e43e35 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -21,6 +21,7 @@
#include "base/callee_save_type.h"
#include "base/enums.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "common_runtime_test.h"
#include "entrypoints/quick/quick_entrypoints_enum.h"
#include "imt_conflict_table.h"
@@ -2096,7 +2097,7 @@ TEST_F(StubTest, ReadBarrierForRoot) {
EXPECT_FALSE(self->IsExceptionPending());
- GcRoot<mirror::Class>& root = mirror::String::java_lang_String_;
+ GcRoot<mirror::Class> root(GetClassRoot<mirror::String>());
size_t result = Invoke3(reinterpret_cast<size_t>(&root), 0U, 0U, readBarrierForRootSlow, self);
EXPECT_FALSE(self->IsExceptionPending());
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index a2e26866d1..095272394a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -484,27 +484,10 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
mirror::ObjectArray<mirror::Object>::ClassSize(image_pointer_size_))));
object_array_class->SetComponentType(java_lang_Object.Get());
- // Setup the char (primitive) class to be used for char[].
- Handle<mirror::Class> char_class(hs.NewHandle(
- AllocClass(self, java_lang_Class.Get(),
- mirror::Class::PrimitiveClassSize(image_pointer_size_))));
- // The primitive char class won't be initialized by
- // InitializePrimitiveClass until line 459, but strings (and
- // internal char arrays) will be allocated before that and the
- // component size, which is computed from the primitive type, needs
- // to be set here.
- char_class->SetPrimitiveType(Primitive::kPrimChar);
-
- // Setup the char[] class to be used for String.
- Handle<mirror::Class> char_array_class(hs.NewHandle(
- AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
- char_array_class->SetComponentType(char_class.Get());
-
// Setup String.
Handle<mirror::Class> java_lang_String(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_))));
java_lang_String->SetStringClass();
- mirror::String::SetClass(java_lang_String.Get());
mirror::Class::SetStatus(java_lang_String, ClassStatus::kResolved, self);
// Setup java.lang.ref.Reference.
@@ -523,7 +506,6 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
SetClassRoot(ClassRoot::kJavaLangObject, java_lang_Object.Get());
SetClassRoot(ClassRoot::kClassArrayClass, class_array_class.Get());
SetClassRoot(ClassRoot::kObjectArrayClass, object_array_class.Get());
- SetClassRoot(ClassRoot::kCharArrayClass, char_array_class.Get());
SetClassRoot(ClassRoot::kJavaLangString, java_lang_String.Get());
SetClassRoot(ClassRoot::kJavaLangRefReference, java_lang_ref_Reference.Get());
@@ -533,6 +515,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// Setup the primitive type classes.
SetClassRoot(ClassRoot::kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean));
SetClassRoot(ClassRoot::kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte));
+ SetClassRoot(ClassRoot::kPrimitiveChar, CreatePrimitiveClass(self, Primitive::kPrimChar));
SetClassRoot(ClassRoot::kPrimitiveShort, CreatePrimitiveClass(self, Primitive::kPrimShort));
SetClassRoot(ClassRoot::kPrimitiveInt, CreatePrimitiveClass(self, Primitive::kPrimInt));
SetClassRoot(ClassRoot::kPrimitiveLong, CreatePrimitiveClass(self, Primitive::kPrimLong));
@@ -543,13 +526,13 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// Create array interface entries to populate once we can load system classes.
array_iftable_ = GcRoot<mirror::IfTable>(AllocIfTable(self, 2));
- // Create int array type for AllocDexCache (done in AppendToBootClassPath).
+ // Create int array type for native pointer arrays (for example vtables) on 32-bit archs.
Handle<mirror::Class> int_array_class(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
int_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveInt, this));
SetClassRoot(ClassRoot::kIntArrayClass, int_array_class.Get());
- // Create long array type for AllocDexCache (done in AppendToBootClassPath).
+ // Create long array type for native pointer arrays (for example vtables) on 64-bit archs.
Handle<mirror::Class> long_array_class(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
long_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveLong, this));
@@ -604,10 +587,6 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// now we can use FindSystemClass
- // run char class through InitializePrimitiveClass to finish init
- InitializePrimitiveClass(char_class.Get(), Primitive::kPrimChar);
- SetClassRoot(ClassRoot::kPrimitiveChar, char_class.Get()); // needs descriptor
-
// Set up GenericJNI entrypoint. That is mainly a hack for common_compiler_test.h so that
// we do not need friend classes or a publicly exposed setter.
quick_generic_jni_trampoline_ = GetQuickGenericJniStub();
@@ -636,7 +615,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
SetClassRoot(ClassRoot::kByteArrayClass, FindSystemClass(self, "[B"));
- CheckSystemClass(self, char_array_class, "[C");
+ SetClassRoot(ClassRoot::kCharArrayClass, FindSystemClass(self, "[C"));
SetClassRoot(ClassRoot::kShortArrayClass, FindSystemClass(self, "[S"));
@@ -685,7 +664,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
FindSystemClass(self, "Ljava/lang/reflect/Proxy;"));
// Create java.lang.reflect.Field.class root.
- auto* class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;");
+ ObjPtr<mirror::Class> class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;");
CHECK(class_root != nullptr);
SetClassRoot(ClassRoot::kJavaLangReflectField, class_root);
@@ -759,7 +738,6 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
class_root = FindSystemClass(self, "Ldalvik/system/EmulatedStackFrame;");
CHECK(class_root != nullptr);
SetClassRoot(ClassRoot::kDalvikSystemEmulatedStackFrame, class_root);
- mirror::EmulatedStackFrame::SetClass(class_root);
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
// finish initializing Reference class
@@ -790,14 +768,12 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// Set up java.lang.Throwable, java.lang.ClassNotFoundException, and
// java.lang.StackTraceElement as a convenience.
SetClassRoot(ClassRoot::kJavaLangThrowable, FindSystemClass(self, "Ljava/lang/Throwable;"));
- mirror::Throwable::SetClass(GetClassRoot(ClassRoot::kJavaLangThrowable, this));
SetClassRoot(ClassRoot::kJavaLangClassNotFoundException,
FindSystemClass(self, "Ljava/lang/ClassNotFoundException;"));
SetClassRoot(ClassRoot::kJavaLangStackTraceElement,
FindSystemClass(self, "Ljava/lang/StackTraceElement;"));
SetClassRoot(ClassRoot::kJavaLangStackTraceElementArrayClass,
FindSystemClass(self, "[Ljava/lang/StackTraceElement;"));
- mirror::StackTraceElement::SetClass(GetClassRoot(ClassRoot::kJavaLangStackTraceElement, this));
// Create conflict tables that depend on the class linker.
runtime->FixupConflictTables();
@@ -1017,10 +993,6 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) {
spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)));
mirror::Class::SetClassClass(GetClassRoot(ClassRoot::kJavaLangClass, this));
- // Special case of setting up the String class early so that we can test arbitrary objects
- // as being Strings or not
- mirror::String::SetClass(GetClassRoot<mirror::String>(this));
-
ObjPtr<mirror::Class> java_lang_Object = GetClassRoot<mirror::Object>(this);
java_lang_Object->SetObjectSize(sizeof(mirror::Object));
// Allocate in non-movable so that it's possible to check if a JNI weak global ref has been
@@ -1033,10 +1005,6 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) {
GcRoot<mirror::IfTable>(GetClassRoot(ClassRoot::kObjectArrayClass, this)->GetIfTable());
DCHECK_EQ(array_iftable_.Read(), GetClassRoot(ClassRoot::kBooleanArrayClass, this)->GetIfTable());
// String class root was set above
- mirror::Throwable::SetClass(GetClassRoot(ClassRoot::kJavaLangThrowable, this));
- mirror::StackTraceElement::SetClass(GetClassRoot(ClassRoot::kJavaLangStackTraceElement, this));
- mirror::EmulatedStackFrame::SetClass(
- GetClassRoot(ClassRoot::kDalvikSystemEmulatedStackFrame, this).Ptr());
mirror::ClassExt::SetClass(GetClassRoot(ClassRoot::kDalvikSystemClassExt, this));
for (gc::space::ImageSpace* image_space : spaces) {
@@ -2116,10 +2084,6 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) {
ClassLinker::~ClassLinker() {
mirror::Class::ResetClass();
- mirror::StackTraceElement::ResetClass();
- mirror::String::ResetClass();
- mirror::Throwable::ResetClass();
- mirror::EmulatedStackFrame::ResetClass();
Thread* const self = Thread::Current();
for (const ClassLoaderData& data : class_loaders_) {
// CHA unloading analysis is not needed. No negative consequences are expected because
@@ -3571,20 +3535,13 @@ ClassLinker::DexCacheData ClassLinker::FindDexCacheDataLocked(const DexFile& dex
}
mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) {
- ObjPtr<mirror::Class> klass =
+ ObjPtr<mirror::Class> primitive_class =
AllocClass(self, mirror::Class::PrimitiveClassSize(image_pointer_size_));
- if (UNLIKELY(klass == nullptr)) {
+ if (UNLIKELY(primitive_class == nullptr)) {
self->AssertPendingOOMException();
return nullptr;
}
- return InitializePrimitiveClass(klass, type);
-}
-
-mirror::Class* ClassLinker::InitializePrimitiveClass(ObjPtr<mirror::Class> primitive_class,
- Primitive::Type type) {
- CHECK(primitive_class != nullptr);
// Must hold lock on object when initializing.
- Thread* self = Thread::Current();
StackHandleScope<1> hs(self);
Handle<mirror::Class> h_class(hs.NewHandle(primitive_class));
ObjectLock<mirror::Class> lock(self, h_class);
@@ -3678,8 +3635,6 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto
new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::Object>>(this));
} else if (strcmp(descriptor, "[Ljava/lang/String;") == 0) {
new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::String>>(this));
- } else if (strcmp(descriptor, "[C") == 0) {
- new_class.Assign(GetClassRoot<mirror::CharArray>(this));
} else if (strcmp(descriptor, "[I") == 0) {
new_class.Assign(GetClassRoot<mirror::IntArray>(this));
} else if (strcmp(descriptor, "[J") == 0) {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index afe5c99990..1f94c43408 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -793,10 +793,6 @@ class ClassLinker {
mirror::Class* CreatePrimitiveClass(Thread* self, Primitive::Type type)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- mirror::Class* InitializePrimitiveClass(ObjPtr<mirror::Class> primitive_class,
- Primitive::Type type)
- REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Roles::uninterruptible_);
mirror::Class* CreateArrayClass(Thread* self,
const char* descriptor,
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc
index ffa0a9065a..5cb08dc278 100644
--- a/runtime/dex/dex_file_annotations.cc
+++ b/runtime/dex/dex_file_annotations.cc
@@ -849,7 +849,8 @@ ObjPtr<mirror::Object> GetAnnotationValue(const ClassData& klass,
return annotation_value.value_.GetL();
}
-mirror::ObjectArray<mirror::String>* GetSignatureValue(const ClassData& klass,
+static ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureValue(
+ const ClassData& klass,
const DexFile::AnnotationSetItem* annotation_set)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile& dex_file = klass.GetDexFile();
@@ -860,12 +861,9 @@ mirror::ObjectArray<mirror::String>* GetSignatureValue(const ClassData& klass,
if (annotation_item == nullptr) {
return nullptr;
}
- ObjPtr<mirror::Class> string_class = mirror::String::GetJavaLangString();
- Handle<mirror::Class> string_array_class(hs.NewHandle(
- Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &string_class)));
- if (string_array_class == nullptr) {
- return nullptr;
- }
+ Handle<mirror::Class> string_array_class =
+ hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::String>>());
+ DCHECK(string_array_class != nullptr);
ObjPtr<mirror::Object> obj =
GetAnnotationValue(klass, annotation_item, "value", string_array_class,
DexFile::kDexAnnotationArray);
@@ -880,19 +878,16 @@ ObjPtr<mirror::ObjectArray<mirror::Class>> GetThrowsValue(
const DexFile::AnnotationSetItem* annotation_set)
REQUIRES_SHARED(Locks::mutator_lock_) {
const DexFile& dex_file = klass.GetDexFile();
- StackHandleScope<1> hs(Thread::Current());
const DexFile::AnnotationItem* annotation_item =
SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/Throws;",
DexFile::kDexVisibilitySystem);
if (annotation_item == nullptr) {
return nullptr;
}
- ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
- Handle<mirror::Class> class_array_class(hs.NewHandle(
- Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &class_class)));
- if (class_array_class == nullptr) {
- return nullptr;
- }
+ StackHandleScope<1> hs(Thread::Current());
+ Handle<mirror::Class> class_array_class =
+ hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::Class>>());
+ DCHECK(class_array_class != nullptr);
ObjPtr<mirror::Object> obj =
GetAnnotationValue(klass, annotation_item, "value", class_array_class,
DexFile::kDexAnnotationArray);
@@ -1020,7 +1015,7 @@ ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForField(ArtField* fie
return ProcessAnnotationSet(field_class, annotation_set, DexFile::kDexVisibilityRuntime);
}
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForField(ArtField* field) {
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForField(ArtField* field) {
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
if (annotation_set == nullptr) {
return nullptr;
@@ -1171,9 +1166,10 @@ ObjPtr<mirror::Object> GetAnnotationForMethodParameter(ArtMethod* method,
annotation_class);
}
-bool GetParametersMetadataForMethod(ArtMethod* method,
- MutableHandle<mirror::ObjectArray<mirror::String>>* names,
- MutableHandle<mirror::IntArray>* access_flags) {
+bool GetParametersMetadataForMethod(
+ ArtMethod* method,
+ /*out*/ MutableHandle<mirror::ObjectArray<mirror::String>>* names,
+ /*out*/ MutableHandle<mirror::IntArray>* access_flags) {
const DexFile::AnnotationSetItem* annotation_set =
FindAnnotationSetForMethod(method);
if (annotation_set == nullptr) {
@@ -1193,12 +1189,10 @@ bool GetParametersMetadataForMethod(ArtMethod* method,
StackHandleScope<4> hs(Thread::Current());
// Extract the parameters' names String[].
- ObjPtr<mirror::Class> string_class = mirror::String::GetJavaLangString();
- Handle<mirror::Class> string_array_class(hs.NewHandle(
- Runtime::Current()->GetClassLinker()->FindArrayClass(Thread::Current(), &string_class)));
- if (UNLIKELY(string_array_class == nullptr)) {
- return false;
- }
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Handle<mirror::Class> string_array_class =
+ hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::String>>(class_linker));
+ DCHECK(string_array_class != nullptr);
ClassData data(method);
Handle<mirror::Object> names_obj =
@@ -1212,10 +1206,8 @@ bool GetParametersMetadataForMethod(ArtMethod* method,
}
// Extract the parameters' access flags int[].
- Handle<mirror::Class> int_array_class(hs.NewHandle(GetClassRoot<mirror::IntArray>()));
- if (UNLIKELY(int_array_class == nullptr)) {
- return false;
- }
+ Handle<mirror::Class> int_array_class(hs.NewHandle(GetClassRoot<mirror::IntArray>(class_linker)));
+ DCHECK(int_array_class != nullptr);
Handle<mirror::Object> access_flags_obj =
hs.NewHandle(GetAnnotationValue(data,
annotation_item,
@@ -1226,12 +1218,12 @@ bool GetParametersMetadataForMethod(ArtMethod* method,
return false;
}
- names->Assign(names_obj.Get()->AsObjectArray<mirror::String>());
- access_flags->Assign(access_flags_obj.Get()->AsIntArray());
+ names->Assign(names_obj->AsObjectArray<mirror::String>());
+ access_flags->Assign(access_flags_obj->AsIntArray());
return true;
}
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method) {
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForMethod(ArtMethod* method) {
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
if (annotation_set == nullptr) {
return nullptr;
@@ -1345,12 +1337,9 @@ ObjPtr<mirror::ObjectArray<mirror::Class>> GetDeclaredClasses(Handle<mirror::Cla
return nullptr;
}
StackHandleScope<1> hs(Thread::Current());
- ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
- Handle<mirror::Class> class_array_class(hs.NewHandle(
- Runtime::Current()->GetClassLinker()->FindArrayClass(hs.Self(), &class_class)));
- if (class_array_class == nullptr) {
- return nullptr;
- }
+ Handle<mirror::Class> class_array_class =
+ hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::Class>>());
+ DCHECK(class_array_class != nullptr);
ObjPtr<mirror::Object> obj =
GetAnnotationValue(data, annotation_item, "value", class_array_class,
DexFile::kDexAnnotationArray);
@@ -1446,7 +1435,7 @@ ObjPtr<mirror::Object> GetEnclosingMethod(Handle<mirror::Class> klass) {
DexFile::kDexAnnotationMethod);
}
-bool GetInnerClass(Handle<mirror::Class> klass, ObjPtr<mirror::String>* name) {
+bool GetInnerClass(Handle<mirror::Class> klass, /*out*/ ObjPtr<mirror::String>* name) {
ClassData data(klass);
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
if (annotation_set == nullptr) {
@@ -1513,7 +1502,8 @@ bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) {
return true;
}
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass) {
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForClass(
+ Handle<mirror::Class> klass) {
ClassData data(klass);
const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
if (annotation_set == nullptr) {
diff --git a/runtime/dex/dex_file_annotations.h b/runtime/dex/dex_file_annotations.h
index 9645a7febd..bde7891091 100644
--- a/runtime/dex/dex_file_annotations.h
+++ b/runtime/dex/dex_file_annotations.h
@@ -41,7 +41,7 @@ ObjPtr<mirror::Object> GetAnnotationForField(ArtField* field,
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForField(ArtField* field)
REQUIRES_SHARED(Locks::mutator_lock_);
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForField(ArtField* field)
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForField(ArtField* field)
REQUIRES_SHARED(Locks::mutator_lock_);
bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -64,11 +64,11 @@ ObjPtr<mirror::Object> GetAnnotationForMethodParameter(ArtMethod* method,
uint32_t parameter_idx,
Handle<mirror::Class> annotation_class)
REQUIRES_SHARED(Locks::mutator_lock_);
-bool GetParametersMetadataForMethod(ArtMethod* method,
- MutableHandle<mirror::ObjectArray<mirror::String>>* names,
- MutableHandle<mirror::IntArray>* access_flags)
- REQUIRES_SHARED(Locks::mutator_lock_);
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method)
+bool GetParametersMetadataForMethod(
+ ArtMethod* method,
+ /*out*/ MutableHandle<mirror::ObjectArray<mirror::String>>* names,
+ /*out*/ MutableHandle<mirror::IntArray>* access_flags) REQUIRES_SHARED(Locks::mutator_lock_);
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForMethod(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_);
// Check whether `method` is annotated with `annotation_class`.
// If `lookup_in_resolved_boot_classes` is true, look up any of the
@@ -101,12 +101,12 @@ ObjPtr<mirror::Class> GetEnclosingClass(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::Object> GetEnclosingMethod(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
-bool GetInnerClass(Handle<mirror::Class> klass, ObjPtr<mirror::String>* name)
+bool GetInnerClass(Handle<mirror::Class> klass, /*out*/ ObjPtr<mirror::String>* name)
REQUIRES_SHARED(Locks::mutator_lock_);
bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags)
REQUIRES_SHARED(Locks::mutator_lock_);
-mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForClass(
+ Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
const char* GetSourceDebugExtension(Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
bool IsClassAnnotationPresent(Handle<mirror::Class> klass,
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index ed5885f224..5f7594c68d 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -25,6 +25,7 @@
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
+#include "mirror/string-inl.h"
namespace art {
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 37234e1462..0ee780d32d 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -35,6 +35,7 @@
#include "base/macros.h"
#include "base/mutex.h"
#include "class_linker-inl.h"
+#include "class_root.h"
#include "common_dex_operations.h"
#include "common_throws.h"
#include "dex/dex_file-inl.h"
@@ -328,7 +329,7 @@ static inline ObjPtr<mirror::String> ResolveString(Thread* self,
ShadowFrame& shadow_frame,
dex::StringIndex string_idx)
REQUIRES_SHARED(Locks::mutator_lock_) {
- ObjPtr<mirror::Class> java_lang_string_class = mirror::String::GetJavaLangString();
+ ObjPtr<mirror::Class> java_lang_string_class = GetClassRoot<mirror::String>();
if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
StackHandleScope<1> hs(self);
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 98fe8b271b..88cfafba47 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -388,7 +388,7 @@ TEST_F(UnstartedRuntimeTest, StringCharAt) {
TEST_F(UnstartedRuntimeTest, StringInit) {
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
- ObjPtr<mirror::Class> klass = mirror::String::GetJavaLangString();
+ ObjPtr<mirror::Class> klass = GetClassRoot<mirror::String>();
ArtMethod* method =
klass->FindConstructor("(Ljava/lang/String;)V",
Runtime::Current()->GetClassLinker()->GetImagePointerSize());
@@ -537,7 +537,7 @@ TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
tmp,
false,
object_class.Get(),
- mirror::String::GetJavaLangString(),
+ GetClassRoot<mirror::String>(),
hs_src,
1,
hs_dst,
@@ -551,7 +551,7 @@ TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
{
StackHandleScope<3> hs_src(self);
hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
- hs_src.NewHandle(mirror::String::GetJavaLangString());
+ hs_src.NewHandle(GetClassRoot<mirror::String>());
hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
StackHandleScope<3> hs_dst(self);
@@ -568,7 +568,7 @@ TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
tmp,
true,
object_class.Get(),
- mirror::String::GetJavaLangString(),
+ GetClassRoot<mirror::String>(),
hs_src,
0,
hs_dst,
@@ -1348,7 +1348,7 @@ TEST_F(UnstartedRuntimeTest, ConstructorNewInstance0) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
// Get Throwable.
- Handle<mirror::Class> throw_class = hs.NewHandle(mirror::Throwable::GetJavaLangThrowable());
+ Handle<mirror::Class> throw_class = hs.NewHandle(GetClassRoot<mirror::Throwable>());
ASSERT_TRUE(class_linker->EnsureInitialized(self, throw_class, true, true));
// Get an input object.
@@ -1387,8 +1387,8 @@ TEST_F(UnstartedRuntimeTest, ConstructorNewInstance0) {
// Should be a new object.
ASSERT_NE(result.GetL(), input.Get());
- // Should be a String.
- ASSERT_EQ(mirror::Throwable::GetJavaLangThrowable(), result.GetL()->GetClass());
+ // Should be of type Throwable.
+ ASSERT_OBJ_PTR_EQ(GetClassRoot<mirror::Throwable>(), result.GetL()->GetClass());
// Should have the right string.
ObjPtr<mirror::String> result_msg =
reinterpret_cast<mirror::Throwable*>(result.GetL())->GetDetailMessage();
diff --git a/runtime/jit/profiling_info_test.cc b/runtime/jit/profiling_info_test.cc
new file mode 100644
index 0000000000..106a80a568
--- /dev/null
+++ b/runtime/jit/profiling_info_test.cc
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2016 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 <gtest/gtest.h>
+#include <stdio.h>
+
+#include "art_method-inl.h"
+#include "base/unix_file/fd_file.h"
+#include "class_linker-inl.h"
+#include "common_runtime_test.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_loader.h"
+#include "dex/method_reference.h"
+#include "dex/type_reference.h"
+#include "handle_scope-inl.h"
+#include "linear_alloc.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_loader.h"
+#include "profile/profile_compilation_info.h"
+#include "scoped_thread_state_change-inl.h"
+#include "ziparchive/zip_writer.h"
+
+namespace art {
+
+using Hotness = ProfileCompilationInfo::MethodHotness;
+
+static constexpr size_t kMaxMethodIds = 65535;
+
+class ProfileCompilationInfoTest : public CommonRuntimeTest {
+ public:
+ void PostRuntimeCreate() OVERRIDE {
+ allocator_.reset(new ArenaAllocator(Runtime::Current()->GetArenaPool()));
+ }
+
+ protected:
+ std::vector<ArtMethod*> GetVirtualMethods(jobject class_loader,
+ const std::string& clazz) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+ StackHandleScope<1> hs(self);
+ Handle<mirror::ClassLoader> h_loader(
+ hs.NewHandle(self->DecodeJObject(class_loader)->AsClassLoader()));
+ ObjPtr<mirror::Class> klass = class_linker->FindClass(self, clazz.c_str(), h_loader);
+
+ const auto pointer_size = class_linker->GetImagePointerSize();
+ std::vector<ArtMethod*> methods;
+ for (auto& m : klass->GetVirtualMethods(pointer_size)) {
+ methods.push_back(&m);
+ }
+ return methods;
+ }
+
+ bool AddMethod(const std::string& dex_location,
+ uint32_t checksum,
+ uint16_t method_index,
+ ProfileCompilationInfo* info) {
+ return info->AddMethodIndex(Hotness::kFlagHot,
+ dex_location,
+ checksum,
+ method_index,
+ kMaxMethodIds);
+ }
+
+ bool AddMethod(const std::string& dex_location,
+ uint32_t checksum,
+ uint16_t method_index,
+ const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi,
+ ProfileCompilationInfo* info) {
+ return info->AddMethod(
+ dex_location, checksum, method_index, kMaxMethodIds, pmi, Hotness::kFlagPostStartup);
+ }
+
+ bool AddClass(const std::string& dex_location,
+ uint32_t checksum,
+ dex::TypeIndex type_index,
+ ProfileCompilationInfo* info) {
+ DexCacheResolvedClasses classes(dex_location, dex_location, checksum, kMaxMethodIds);
+ classes.AddClass(type_index);
+ return info->AddClasses({classes});
+ }
+
+ uint32_t GetFd(const ScratchFile& file) {
+ return static_cast<uint32_t>(file.GetFd());
+ }
+
+ bool SaveProfilingInfo(
+ const std::string& filename,
+ const std::vector<ArtMethod*>& methods,
+ const std::set<DexCacheResolvedClasses>& resolved_classes,
+ Hotness::Flag flags) {
+ ProfileCompilationInfo info;
+ std::vector<ProfileMethodInfo> profile_methods;
+ ScopedObjectAccess soa(Thread::Current());
+ for (ArtMethod* method : methods) {
+ profile_methods.emplace_back(
+ MethodReference(method->GetDexFile(), method->GetDexMethodIndex()));
+ }
+ if (!info.AddMethods(profile_methods, flags) || !info.AddClasses(resolved_classes)) {
+ return false;
+ }
+ if (info.GetNumberOfMethods() != profile_methods.size()) {
+ return false;
+ }
+ ProfileCompilationInfo file_profile;
+ if (!file_profile.Load(filename, false)) {
+ return false;
+ }
+ if (!info.MergeWith(file_profile)) {
+ return false;
+ }
+
+ return info.Save(filename, nullptr);
+ }
+
+ // Saves the given art methods to a profile backed by 'filename' and adds
+ // some fake inline caches to it. The added inline caches are returned in
+ // the out map `profile_methods_map`.
+ bool SaveProfilingInfoWithFakeInlineCaches(
+ const std::string& filename,
+ const std::vector<ArtMethod*>& methods,
+ Hotness::Flag flags,
+ /*out*/ SafeMap<ArtMethod*, ProfileMethodInfo>* profile_methods_map) {
+ ProfileCompilationInfo info;
+ std::vector<ProfileMethodInfo> profile_methods;
+ ScopedObjectAccess soa(Thread::Current());
+ for (ArtMethod* method : methods) {
+ std::vector<ProfileMethodInfo::ProfileInlineCache> caches;
+ // Monomorphic
+ for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) {
+ std::vector<TypeReference> classes;
+ classes.emplace_back(method->GetDexFile(), dex::TypeIndex(0));
+ caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
+ }
+ // Polymorphic
+ for (uint16_t dex_pc = 11; dex_pc < 22; dex_pc++) {
+ std::vector<TypeReference> classes;
+ for (uint16_t k = 0; k < InlineCache::kIndividualCacheSize / 2; k++) {
+ classes.emplace_back(method->GetDexFile(), dex::TypeIndex(k));
+ }
+ caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
+ }
+ // Megamorphic
+ for (uint16_t dex_pc = 22; dex_pc < 33; dex_pc++) {
+ std::vector<TypeReference> classes;
+ for (uint16_t k = 0; k < 2 * InlineCache::kIndividualCacheSize; k++) {
+ classes.emplace_back(method->GetDexFile(), dex::TypeIndex(k));
+ }
+ caches.emplace_back(dex_pc, /*is_missing_types*/false, classes);
+ }
+ // Missing types
+ for (uint16_t dex_pc = 33; dex_pc < 44; dex_pc++) {
+ std::vector<TypeReference> classes;
+ caches.emplace_back(dex_pc, /*is_missing_types*/true, classes);
+ }
+ ProfileMethodInfo pmi(MethodReference(method->GetDexFile(),
+ method->GetDexMethodIndex()),
+ caches);
+ profile_methods.push_back(pmi);
+ profile_methods_map->Put(method, pmi);
+ }
+
+ if (!info.AddMethods(profile_methods, flags)
+ || info.GetNumberOfMethods() != profile_methods.size()) {
+ return false;
+ }
+ return info.Save(filename, nullptr);
+ }
+
+ // Creates an inline cache which will be destructed at the end of the test.
+ ProfileCompilationInfo::InlineCacheMap* CreateInlineCacheMap() {
+ used_inline_caches.emplace_back(new ProfileCompilationInfo::InlineCacheMap(
+ std::less<uint16_t>(), allocator_->Adapter(kArenaAllocProfile)));
+ return used_inline_caches.back().get();
+ }
+
+ ProfileCompilationInfo::OfflineProfileMethodInfo ConvertProfileMethodInfo(
+ const ProfileMethodInfo& pmi) {
+ ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap();
+ ProfileCompilationInfo::OfflineProfileMethodInfo offline_pmi(ic_map);
+ SafeMap<DexFile*, uint8_t> dex_map; // dex files to profile index
+ for (const auto& inline_cache : pmi.inline_caches) {
+ ProfileCompilationInfo::DexPcData& dex_pc_data =
+ ic_map->FindOrAdd(
+ inline_cache.dex_pc, ProfileCompilationInfo::DexPcData(allocator_.get()))->second;
+ if (inline_cache.is_missing_types) {
+ dex_pc_data.SetIsMissingTypes();
+ }
+ for (const auto& class_ref : inline_cache.classes) {
+ uint8_t dex_profile_index = dex_map.FindOrAdd(const_cast<DexFile*>(class_ref.dex_file),
+ static_cast<uint8_t>(dex_map.size()))->second;
+ dex_pc_data.AddClass(dex_profile_index, class_ref.TypeIndex());
+ if (dex_profile_index >= offline_pmi.dex_references.size()) {
+ // This is a new dex.
+ const std::string& dex_key = ProfileCompilationInfo::GetProfileDexFileKey(
+ class_ref.dex_file->GetLocation());
+ offline_pmi.dex_references.emplace_back(dex_key,
+ class_ref.dex_file->GetLocationChecksum(),
+ class_ref.dex_file->NumMethodIds());
+ }
+ }
+ }
+ return offline_pmi;
+ }
+
+ // Cannot sizeof the actual arrays so hard code the values here.
+ // They should not change anyway.
+ static constexpr int kProfileMagicSize = 4;
+ static constexpr int kProfileVersionSize = 4;
+
+ std::unique_ptr<ArenaAllocator> allocator_;
+
+ // Cache of inline caches generated during tests.
+ // This makes it easier to pass data between different utilities and ensure that
+ // caches are destructed at the end of the test.
+ std::vector<std::unique_ptr<ProfileCompilationInfo::InlineCacheMap>> used_inline_caches;
+};
+
+TEST_F(ProfileCompilationInfoTest, SaveArtMethods) {
+ ScratchFile profile;
+
+ Thread* self = Thread::Current();
+ jobject class_loader;
+ {
+ ScopedObjectAccess soa(self);
+ class_loader = LoadDex("ProfileTestMultiDex");
+ }
+ ASSERT_NE(class_loader, nullptr);
+
+ // Save virtual methods from Main.
+ std::set<DexCacheResolvedClasses> resolved_classes;
+ std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
+ ASSERT_TRUE(SaveProfilingInfo(
+ profile.GetFilename(), main_methods, resolved_classes, Hotness::kFlagPostStartup));
+
+ // Check that what we saved is in the profile.
+ ProfileCompilationInfo info1;
+ ASSERT_TRUE(info1.Load(GetFd(profile)));
+ ASSERT_EQ(info1.GetNumberOfMethods(), main_methods.size());
+ {
+ ScopedObjectAccess soa(self);
+ for (ArtMethod* m : main_methods) {
+ Hotness h = info1.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsPostStartup());
+ }
+ }
+
+ // Save virtual methods from Second.
+ std::vector<ArtMethod*> second_methods = GetVirtualMethods(class_loader, "LSecond;");
+ ASSERT_TRUE(SaveProfilingInfo(
+ profile.GetFilename(), second_methods, resolved_classes, Hotness::kFlagStartup));
+
+ // Check that what we saved is in the profile (methods form Main and Second).
+ ProfileCompilationInfo info2;
+ ASSERT_TRUE(profile.GetFile()->ResetOffset());
+ ASSERT_TRUE(info2.Load(GetFd(profile)));
+ ASSERT_EQ(info2.GetNumberOfMethods(), main_methods.size() + second_methods.size());
+ {
+ ScopedObjectAccess soa(self);
+ for (ArtMethod* m : main_methods) {
+ Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsPostStartup());
+ }
+ for (ArtMethod* m : second_methods) {
+ Hotness h = info2.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsStartup());
+ }
+ }
+}
+
+TEST_F(ProfileCompilationInfoTest, SaveArtMethodsWithInlineCaches) {
+ ScratchFile profile;
+
+ Thread* self = Thread::Current();
+ jobject class_loader;
+ {
+ ScopedObjectAccess soa(self);
+ class_loader = LoadDex("ProfileTestMultiDex");
+ }
+ ASSERT_NE(class_loader, nullptr);
+
+ // Save virtual methods from Main.
+ std::set<DexCacheResolvedClasses> resolved_classes;
+ std::vector<ArtMethod*> main_methods = GetVirtualMethods(class_loader, "LMain;");
+
+ SafeMap<ArtMethod*, ProfileMethodInfo> profile_methods_map;
+ ASSERT_TRUE(SaveProfilingInfoWithFakeInlineCaches(
+ profile.GetFilename(), main_methods, Hotness::kFlagStartup, &profile_methods_map));
+
+ // Check that what we saved is in the profile.
+ ProfileCompilationInfo info;
+ ASSERT_TRUE(info.Load(GetFd(profile)));
+ ASSERT_EQ(info.GetNumberOfMethods(), main_methods.size());
+ {
+ ScopedObjectAccess soa(self);
+ for (ArtMethod* m : main_methods) {
+ Hotness h = info.GetMethodHotness(MethodReference(m->GetDexFile(), m->GetDexMethodIndex()));
+ ASSERT_TRUE(h.IsHot());
+ ASSERT_TRUE(h.IsStartup());
+ const ProfileMethodInfo& pmi = profile_methods_map.find(m)->second;
+ std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> offline_pmi =
+ info.GetMethod(m->GetDexFile()->GetLocation(),
+ m->GetDexFile()->GetLocationChecksum(),
+ m->GetDexMethodIndex());
+ ASSERT_TRUE(offline_pmi != nullptr);
+ ProfileCompilationInfo::OfflineProfileMethodInfo converted_pmi =
+ ConvertProfileMethodInfo(pmi);
+ ASSERT_EQ(converted_pmi, *offline_pmi);
+ }
+ }
+}
+
+} // namespace art
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index ad6b37b86a..cb2708d0cb 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -39,6 +39,7 @@
#include "object-refvisitor-inl.h"
#include "object_array-inl.h"
#include "object_lock.h"
+#include "string-inl.h"
#include "runtime.h"
#include "thread.h"
#include "throwable.h"
@@ -1460,12 +1461,12 @@ template<VerifyObjectFlags kVerifyFlags> void Class::GetAccessFlagsDCheck() {
// circularity issue during loading the names of its members
DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() ||
IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ||
- this == String::GetJavaLangString())
+ this == GetClassRoot<String>())
<< "IsIdxLoaded=" << IsIdxLoaded<kVerifyFlags>()
<< " IsRetired=" << IsRetired<kVerifyFlags>()
<< " IsErroneous=" <<
IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>()
- << " IsString=" << (this == String::GetJavaLangString())
+ << " IsString=" << (this == GetClassRoot<String>())
<< " status= " << GetStatus<kVerifyFlags>()
<< " descriptor=" << PrettyDescriptor();
}
diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc
index 527408b3e5..5595102866 100644
--- a/runtime/mirror/emulated_stack_frame.cc
+++ b/runtime/mirror/emulated_stack_frame.cc
@@ -27,8 +27,6 @@
namespace art {
namespace mirror {
-GcRoot<mirror::Class> EmulatedStackFrame::static_class_;
-
// Calculates the size of a stack frame based on the size of its argument
// types and return types.
static void CalculateFrameAndReferencesSize(ObjPtr<mirror::ObjectArray<mirror::Class>> p_types,
@@ -192,7 +190,7 @@ mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs(
// Step 5: Construct the EmulatedStackFrame object.
Handle<EmulatedStackFrame> sf(hs.NewHandle(
- ObjPtr<EmulatedStackFrame>::DownCast(StaticClass()->AllocObject(self))));
+ ObjPtr<EmulatedStackFrame>::DownCast(GetClassRoot<EmulatedStackFrame>()->AllocObject(self))));
sf->SetFieldObject<false>(CallsiteTypeOffset(), caller_type.Get());
sf->SetFieldObject<false>(TypeOffset(), callee_type.Get());
sf->SetFieldObject<false>(ReferencesOffset(), references.Get());
@@ -272,20 +270,5 @@ void EmulatedStackFrame::SetReturnValue(Thread* self, const JValue& value) {
}
}
-void EmulatedStackFrame::SetClass(Class* klass) {
- CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
- CHECK(klass != nullptr);
- static_class_ = GcRoot<Class>(klass);
-}
-
-void EmulatedStackFrame::ResetClass() {
- CHECK(!static_class_.IsNull());
- static_class_ = GcRoot<Class>(nullptr);
-}
-
-void EmulatedStackFrame::VisitRoots(RootVisitor* visitor) {
- static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/emulated_stack_frame.h b/runtime/mirror/emulated_stack_frame.h
index 23626f46e0..ec45f57a4d 100644
--- a/runtime/mirror/emulated_stack_frame.h
+++ b/runtime/mirror/emulated_stack_frame.h
@@ -64,15 +64,7 @@ class MANAGED EmulatedStackFrame : public Object {
return GetReferences()->Get(0);
}
- static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
- static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
- return static_class_.Read();
- }
-
mirror::ObjectArray<mirror::Object>* GetReferences() REQUIRES_SHARED(Locks::mutator_lock_) {
return GetFieldObject<mirror::ObjectArray<mirror::Object>>(
OFFSET_OF_OBJECT_MEMBER(EmulatedStackFrame, references_));
@@ -104,8 +96,6 @@ class MANAGED EmulatedStackFrame : public Object {
HeapReference<mirror::ByteArray> stack_frame_;
HeapReference<mirror::MethodType> type_;
- static GcRoot<mirror::Class> static_class_; // dalvik.system.EmulatedStackFrame.class
-
friend struct art::EmulatedStackFrameOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(EmulatedStackFrame);
};
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index c7561f4278..bfebd5d365 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -37,7 +37,7 @@
#include "read_barrier-inl.h"
#include "reference.h"
#include "runtime.h"
-#include "string-inl.h"
+#include "string.h"
#include "throwable.h"
namespace art {
diff --git a/runtime/mirror/stack_trace_element.cc b/runtime/mirror/stack_trace_element.cc
index bb3242e035..ff353d8939 100644
--- a/runtime/mirror/stack_trace_element.cc
+++ b/runtime/mirror/stack_trace_element.cc
@@ -18,6 +18,7 @@
#include "class-inl.h"
#include "class.h"
+#include "class_root.h"
#include "gc/accounting/card_table-inl.h"
#include "gc_root-inl.h"
#include "handle_scope-inl.h"
@@ -27,26 +28,13 @@
namespace art {
namespace mirror {
-GcRoot<Class> StackTraceElement::java_lang_StackTraceElement_;
-
-void StackTraceElement::SetClass(ObjPtr<Class> java_lang_StackTraceElement) {
- CHECK(java_lang_StackTraceElement_.IsNull());
- CHECK(java_lang_StackTraceElement != nullptr);
- java_lang_StackTraceElement_ = GcRoot<Class>(java_lang_StackTraceElement);
-}
-
-void StackTraceElement::ResetClass() {
- CHECK(!java_lang_StackTraceElement_.IsNull());
- java_lang_StackTraceElement_ = GcRoot<Class>(nullptr);
-}
-
StackTraceElement* StackTraceElement::Alloc(Thread* self,
Handle<String> declaring_class,
Handle<String> method_name,
Handle<String> file_name,
int32_t line_number) {
ObjPtr<StackTraceElement> trace =
- ObjPtr<StackTraceElement>::DownCast(GetStackTraceElement()->AllocObject(self));
+ ObjPtr<StackTraceElement>::DownCast(GetClassRoot<StackTraceElement>()->AllocObject(self));
if (LIKELY(trace != nullptr)) {
if (Runtime::Current()->IsActiveTransaction()) {
trace->Init<true>(declaring_class.Get(), method_name.Get(), file_name.Get(), line_number);
@@ -72,10 +60,5 @@ void StackTraceElement::Init(ObjPtr<String> declaring_class,
line_number);
}
-void StackTraceElement::VisitRoots(RootVisitor* visitor) {
- java_lang_StackTraceElement_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index 87e8a1f659..f25211c397 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -53,15 +53,6 @@ class MANAGED StackTraceElement FINAL : public Object {
int32_t line_number)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
- static void SetClass(ObjPtr<Class> java_lang_StackTraceElement);
- static void ResetClass();
- static void VisitRoots(RootVisitor* visitor)
- REQUIRES_SHARED(Locks::mutator_lock_);
- static Class* GetStackTraceElement() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(!java_lang_StackTraceElement_.IsNull());
- return java_lang_StackTraceElement_.Read();
- }
-
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
HeapReference<String> declaring_class_;
@@ -76,8 +67,6 @@ class MANAGED StackTraceElement FINAL : public Object {
int32_t line_number)
REQUIRES_SHARED(Locks::mutator_lock_);
- static GcRoot<Class> java_lang_StackTraceElement_;
-
friend struct art::StackTraceElementOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement);
};
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index a60861cc28..8fa2c6cf7f 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -25,6 +25,7 @@
#include "base/globals.h"
#include "base/utils.h"
#include "class.h"
+#include "class_root.h"
#include "common_throws.h"
#include "dex/utf.h"
#include "gc/heap-inl.h"
@@ -194,21 +195,6 @@ int32_t String::FastIndexOf(MemoryType* chars, int32_t ch, int32_t start) {
return -1;
}
-template<VerifyObjectFlags kVerifyFlags>
-inline size_t String::SizeOf() {
- size_t size = sizeof(String);
- if (IsCompressed()) {
- size += (sizeof(uint8_t) * GetLength<kVerifyFlags>());
- } else {
- size += (sizeof(uint16_t) * GetLength<kVerifyFlags>());
- }
- // String.equals() intrinsics assume zero-padding up to kObjectAlignment,
- // so make sure the zero-padding is actually copied around if GC compaction
- // chooses to copy only SizeOf() bytes.
- // http://b/23528461
- return RoundUp(size, kObjectAlignment);
-}
-
template <bool kIsInstrumented, typename PreFenceVisitor>
inline String* String::Alloc(Thread* self, int32_t utf16_length_with_flag,
gc::AllocatorType allocator_type,
@@ -226,7 +212,8 @@ inline String* String::Alloc(Thread* self, int32_t utf16_length_with_flag,
// http://b/23528461
size_t alloc_size = RoundUp(size, kObjectAlignment);
- Class* string_class = GetJavaLangString();
+ Runtime* runtime = Runtime::Current();
+ ObjPtr<Class> string_class = GetClassRoot<String>(runtime->GetClassLinker());
// Check for overflow and throw OutOfMemoryError if this was an unreasonable request.
// Do this by comparing with the maximum length that will _not_ cause an overflow.
const size_t overflow_length = (-header_size) / block_size; // Unsigned arithmetic.
@@ -242,7 +229,7 @@ inline String* String::Alloc(Thread* self, int32_t utf16_length_with_flag,
return nullptr;
}
- gc::Heap* heap = Runtime::Current()->GetHeap();
+ gc::Heap* heap = runtime->GetHeap();
return down_cast<String*>(
heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, string_class, alloc_size,
allocator_type, pre_fence_visitor));
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index 6208a962e5..b76ca1968a 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -35,9 +35,6 @@
namespace art {
namespace mirror {
-// TODO: get global references for these
-GcRoot<Class> String::java_lang_String_;
-
int32_t String::FastIndexOf(int32_t ch, int32_t start) {
int32_t count = GetLength();
if (start < 0) {
@@ -52,18 +49,6 @@ int32_t String::FastIndexOf(int32_t ch, int32_t start) {
}
}
-void String::SetClass(ObjPtr<Class> java_lang_String) {
- CHECK(java_lang_String_.IsNull());
- CHECK(java_lang_String != nullptr);
- CHECK(java_lang_String->IsStringClass());
- java_lang_String_ = GcRoot<Class>(java_lang_String);
-}
-
-void String::ResetClass() {
- CHECK(!java_lang_String_.IsNull());
- java_lang_String_ = GcRoot<Class>(nullptr);
-}
-
int String::ComputeHashCode() {
int32_t hash_code = 0;
if (IsCompressed()) {
@@ -372,10 +357,6 @@ int32_t String::CompareTo(ObjPtr<String> rhs) {
return count_diff;
}
-void String::VisitRoots(RootVisitor* visitor) {
- java_lang_String_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
CharArray* String::ToCharArray(Thread* self) {
StackHandleScope<1> hs(self);
Handle<String> string(hs.NewHandle(this));
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index c45dc499e5..598175b749 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -17,6 +17,8 @@
#ifndef ART_RUNTIME_MIRROR_STRING_H_
#define ART_RUNTIME_MIRROR_STRING_H_
+#include "base/bit_utils.h"
+#include "base/globals.h"
#include "gc/allocator_type.h"
#include "gc_root-inl.h"
#include "class.h"
@@ -66,7 +68,19 @@ class MANAGED String FINAL : public Object {
}
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- size_t SizeOf() REQUIRES_SHARED(Locks::mutator_lock_);
+ size_t SizeOf() REQUIRES_SHARED(Locks::mutator_lock_) {
+ size_t size = sizeof(String);
+ if (IsCompressed()) {
+ size += (sizeof(uint8_t) * GetLength<kVerifyFlags>());
+ } else {
+ size += (sizeof(uint16_t) * GetLength<kVerifyFlags>());
+ }
+ // String.equals() intrinsics assume zero-padding up to kObjectAlignment,
+ // so make sure the zero-padding is actually copied around if GC compaction
+ // chooses to copy only SizeOf() bytes.
+ // http://b/23528461
+ return RoundUp(size, kObjectAlignment);
+ }
// Taking out the first/uppermost bit because it is not part of actual length value
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -214,15 +228,6 @@ class MANAGED String FINAL : public Object {
: length;
}
- static Class* GetJavaLangString() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(!java_lang_String_.IsNull());
- return java_lang_String_.Read();
- }
-
- static void SetClass(ObjPtr<Class> java_lang_String) REQUIRES_SHARED(Locks::mutator_lock_);
- static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
// Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
// "[[I" would be "int[][]", "[Ljava/lang/String;" would be
// "java.lang.String[]", and so forth.
@@ -267,10 +272,7 @@ class MANAGED String FINAL : public Object {
uint8_t value_compressed_[0];
};
- static GcRoot<Class> java_lang_String_;
-
friend struct art::StringOffsets; // for verifying offset information
- ART_FRIEND_TEST(art::StubTest, ReadBarrierForRoot); // For java_lang_String_.
DISALLOW_IMPLICIT_CONSTRUCTORS(String);
};
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index 70069733d1..82e295a616 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -22,6 +22,7 @@
#include "base/enums.h"
#include "base/utils.h"
#include "class-inl.h"
+#include "class_root.h"
#include "dex/dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
#include "object-inl.h"
@@ -36,8 +37,6 @@ namespace mirror {
using android::base::StringPrintf;
-GcRoot<Class> Throwable::java_lang_Throwable_;
-
void Throwable::SetDetailMessage(ObjPtr<String> new_detail_message) {
if (Runtime::Current()->IsActiveTransaction()) {
SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), new_detail_message);
@@ -128,8 +127,7 @@ std::string Throwable::Dump() {
} else {
ObjPtr<Object> stack_trace = GetStackTrace();
if (stack_trace != nullptr && stack_trace->IsObjectArray()) {
- CHECK_EQ(stack_trace->GetClass()->GetComponentType(),
- StackTraceElement::GetStackTraceElement());
+ CHECK_EQ(stack_trace->GetClass()->GetComponentType(), GetClassRoot<StackTraceElement>());
ObjPtr<ObjectArray<StackTraceElement>> ste_array =
ObjPtr<ObjectArray<StackTraceElement>>::DownCast(stack_trace);
if (ste_array->GetLength() == 0) {
@@ -159,21 +157,6 @@ std::string Throwable::Dump() {
return result;
}
-void Throwable::SetClass(ObjPtr<Class> java_lang_Throwable) {
- CHECK(java_lang_Throwable_.IsNull());
- CHECK(java_lang_Throwable != nullptr);
- java_lang_Throwable_ = GcRoot<Class>(java_lang_Throwable);
-}
-
-void Throwable::ResetClass() {
- CHECK(!java_lang_Throwable_.IsNull());
- java_lang_Throwable_ = GcRoot<Class>(nullptr);
-}
-
-void Throwable::VisitRoots(RootVisitor* visitor) {
- java_lang_Throwable_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
Object* Throwable::GetStackState() {
return GetFieldObjectVolatile<Object>(OFFSET_OF_OBJECT_MEMBER(Throwable, backtrace_));
}
diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h
index b901ca2d00..42c612f8b6 100644
--- a/runtime/mirror/throwable.h
+++ b/runtime/mirror/throwable.h
@@ -46,18 +46,8 @@ class MANAGED Throwable : public Object {
bool IsCheckedException() REQUIRES_SHARED(Locks::mutator_lock_);
bool IsError() REQUIRES_SHARED(Locks::mutator_lock_);
- static Class* GetJavaLangThrowable() REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(!java_lang_Throwable_.IsNull());
- return java_lang_Throwable_.Read();
- }
-
int32_t GetStackDepth() REQUIRES_SHARED(Locks::mutator_lock_);
- static void SetClass(ObjPtr<Class> java_lang_Throwable);
- static void ResetClass();
- static void VisitRoots(RootVisitor* visitor)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
Object* GetStackState() REQUIRES_SHARED(Locks::mutator_lock_);
Object* GetStackTrace() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -69,8 +59,6 @@ class MANAGED Throwable : public Object {
HeapReference<Object> stack_trace_;
HeapReference<Object> suppressed_exceptions_;
- static GcRoot<Class> java_lang_Throwable_;
-
friend struct art::ThrowableOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable);
};
diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc
index 2c1283225d..cb2d628b5b 100644
--- a/runtime/mirror/var_handle_test.cc
+++ b/runtime/mirror/var_handle_test.cc
@@ -92,8 +92,7 @@ class VarHandleTest : public CommonRuntimeTest {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Handle<Class> var_type = hs.NewHandle(view_array_class->GetComponentType());
Handle<Class> index_type = hs.NewHandle(class_linker->FindPrimitiveClass('I'));
- ObjPtr<mirror::Class> byte_class = class_linker->FindPrimitiveClass('B');
- Handle<Class> byte_array_class(hs.NewHandle(class_linker->FindArrayClass(self, &byte_class)));
+ Handle<Class> byte_array_class(hs.NewHandle(GetClassRoot<mirror::ByteArray>()));
InitializeVarHandle(bvh.Get(), var_type, byte_array_class, index_type, access_modes_bit_mask);
bvh->SetFieldBoolean<false>(ByteArrayViewVarHandle::NativeByteOrderOffset(), native_byte_order);
return bvh.Get();
@@ -234,8 +233,7 @@ static MethodType* MethodTypeOf(const std::string& method_descriptor) {
ScopedObjectAccess soa(self);
StackHandleScope<3> hs(self);
int ptypes_count = static_cast<int>(descriptors.size()) - 1;
- ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
- ObjPtr<mirror::Class> array_of_class = class_linker->FindArrayClass(self, &class_type);
+ ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>();
Handle<ObjectArray<Class>> ptypes = hs.NewHandle(
ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, ptypes_count));
Handle<mirror::ClassLoader> boot_class_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
@@ -599,10 +597,10 @@ TEST_F(VarHandleTest, ArrayElementVarHandle) {
VarHandle::AccessMode::kGetAndBitwiseXorRelease,
VarHandle::AccessMode::kGetAndBitwiseXorAcquire);
- ObjPtr<mirror::Class> string_class = mirror::String::GetJavaLangString();
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Handle<Class> string_array_class(hs.NewHandle(class_linker->FindArrayClass(self, &string_class)));
- Handle<mirror::ArrayElementVarHandle> vh(hs.NewHandle(CreateArrayElementVarHandle(self, string_array_class, mask)));
+ Handle<mirror::Class> string_array_class = hs.NewHandle(
+ GetClassRoot<mirror::ObjectArray<mirror::String>>());
+ Handle<mirror::ArrayElementVarHandle> vh(
+ hs.NewHandle(CreateArrayElementVarHandle(self, string_array_class, mask)));
EXPECT_FALSE(vh.IsNull());
// Check access modes
@@ -746,11 +744,10 @@ TEST_F(VarHandleTest, ByteArrayViewVarHandle) {
VarHandle::AccessMode::kGetAndBitwiseXor,
VarHandle::AccessMode::kGetAndBitwiseXorAcquire);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::Class> char_class = class_linker->FindPrimitiveClass('C');
- Handle<Class> char_array_class(hs.NewHandle(class_linker->FindArrayClass(self, &char_class)));
+ Handle<Class> char_array_class(hs.NewHandle(GetClassRoot<mirror::CharArray>()));
const bool native_byte_order = true;
- Handle<mirror::ByteArrayViewVarHandle> vh(hs.NewHandle(CreateByteArrayViewVarHandle(self, char_array_class, native_byte_order, mask)));
+ Handle<mirror::ByteArrayViewVarHandle> vh(
+ hs.NewHandle(CreateByteArrayViewVarHandle(self, char_array_class, native_byte_order, mask)));
EXPECT_FALSE(vh.IsNull());
EXPECT_EQ(native_byte_order, vh->GetNativeByteOrder());
@@ -895,11 +892,10 @@ TEST_F(VarHandleTest, ByteBufferViewVarHandle) {
VarHandle::AccessMode::kGetAndBitwiseXor,
VarHandle::AccessMode::kGetAndBitwiseXorAcquire);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::Class> double_class = class_linker->FindPrimitiveClass('D');
- Handle<Class> double_array_class(hs.NewHandle(class_linker->FindArrayClass(self, &double_class)));
+ Handle<Class> double_array_class(hs.NewHandle(GetClassRoot<mirror::DoubleArray>()));
const bool native_byte_order = false;
- Handle<mirror::ByteBufferViewVarHandle> vh(hs.NewHandle(CreateByteBufferViewVarHandle(self, double_array_class, native_byte_order, mask)));
+ Handle<mirror::ByteBufferViewVarHandle> vh(hs.NewHandle(
+ CreateByteBufferViewVarHandle(self, double_array_class, native_byte_order, mask)));
EXPECT_FALSE(vh.IsNull());
EXPECT_EQ(native_byte_order, vh->GetNativeByteOrder());
diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc
index 07e875efcb..3978ca8a36 100644
--- a/runtime/native/java_lang_StringFactory.cc
+++ b/runtime/native/java_lang_StringFactory.cc
@@ -19,7 +19,7 @@
#include "common_throws.h"
#include "jni/jni_internal.h"
#include "mirror/object-inl.h"
-#include "mirror/string.h"
+#include "mirror/string-inl.h"
#include "native_util.h"
#include "nativehelper/jni_macros.h"
#include "nativehelper/scoped_local_ref.h"
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 0630737d29..b1511c0d88 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -20,6 +20,7 @@
#include "class_linker.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file_loader.h"
+#include "dex/utf.h"
#include "jni/jni_internal.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
diff --git a/runtime/oat.h b/runtime/oat.h
index 7b8f71a3f3..8069a15661 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@ class InstructionSetFeatures;
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- // Last oat version changed reason: Refactor stackmap encoding.
- static constexpr uint8_t kOatVersion[] = { '1', '4', '4', '\0' };
+ // Last oat version changed reason: Optimize masks in stack maps.
+ static constexpr uint8_t kOatVersion[] = { '1', '4', '5', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index de613d3b20..26489209b8 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -439,7 +439,7 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor {
const uint8_t* addr = reinterpret_cast<const uint8_t*>(GetCurrentQuickFrame()) + offset;
value = *reinterpret_cast<const uint32_t*>(addr);
uint32_t bit = (offset >> 2);
- if (bit < code_info.GetNumberOfStackMaskBits() && stack_mask.LoadBit(bit)) {
+ if (bit < stack_mask.size_in_bits() && stack_mask.LoadBit(bit)) {
is_reference = true;
}
break;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 630053ac71..6384d01aaf 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1979,10 +1979,6 @@ void Runtime::VisitConstantRoots(RootVisitor* visitor) {
// Visit the classes held as static in mirror classes, these can be visited concurrently and only
// need to be visited once per GC since they never change.
mirror::Class::VisitRoots(visitor);
- mirror::StackTraceElement::VisitRoots(visitor);
- mirror::String::VisitRoots(visitor);
- mirror::Throwable::VisitRoots(visitor);
- mirror::EmulatedStackFrame::VisitRoots(visitor);
mirror::ClassExt::VisitRoots(visitor);
// Visiting the roots of these ArtMethods is not currently required since all the GcRoots are
// null.
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 2b7e8dd748..fd0e28d9ac 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -200,7 +200,7 @@ void StackMap::Dump(VariableIndentationOutputStream* vios,
<< std::dec
<< ", stack_mask=0b";
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(*this);
- for (size_t i = 0, e = code_info.GetNumberOfStackMaskBits(); i < e; ++i) {
+ for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
vios->Stream() << stack_mask.LoadBit(e - i - 1);
}
vios->Stream() << ")\n";
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 91cecf0690..1cb9a399f8 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -799,6 +799,24 @@ class InvokeInfo : public BitTable<3>::Accessor {
}
};
+// Register masks tend to have many trailing zero bits (caller-saves are usually not encoded),
+// therefore it is worth encoding the mask as value+shift.
+class RegisterMask : public BitTable<2>::Accessor {
+ public:
+ enum Field {
+ kValue,
+ kShift,
+ kCount,
+ };
+
+ RegisterMask(const BitTable<kCount>* table, uint32_t row)
+ : BitTable<kCount>::Accessor(table, row) {}
+
+ ALWAYS_INLINE uint32_t GetMask() const {
+ return Get<kValue>() << Get<kShift>();
+ }
+};
+
/**
* Wrapper around all compiler information collected for a method.
* The information is of the form:
@@ -833,24 +851,22 @@ class CodeInfo {
return DexRegisterLocationCatalog(location_catalog_);
}
- ALWAYS_INLINE size_t GetNumberOfStackMaskBits() const {
- return stack_mask_bits_;
- }
-
ALWAYS_INLINE StackMap GetStackMapAt(size_t index) const {
return StackMap(&stack_maps_, index);
}
BitMemoryRegion GetStackMask(size_t index) const {
- return stack_masks_.Subregion(index * stack_mask_bits_, stack_mask_bits_);
+ return stack_masks_.GetBitMemoryRegion(index);
}
BitMemoryRegion GetStackMaskOf(const StackMap& stack_map) const {
- return GetStackMask(stack_map.GetStackMaskIndex());
+ uint32_t index = stack_map.GetStackMaskIndex();
+ return (index == StackMap::kNoValue) ? BitMemoryRegion() : GetStackMask(index);
}
uint32_t GetRegisterMaskOf(const StackMap& stack_map) const {
- return register_masks_.Get(stack_map.GetRegisterMaskIndex());
+ uint32_t index = stack_map.GetRegisterMaskIndex();
+ return (index == StackMap::kNoValue) ? 0 : RegisterMask(&register_masks_, index).GetMask();
}
uint32_t GetNumberOfLocationCatalogEntries() const {
@@ -1045,8 +1061,8 @@ class CodeInfo {
invoke_infos_.Decode(bit_region, &bit_offset);
inline_infos_.Decode(bit_region, &bit_offset);
register_masks_.Decode(bit_region, &bit_offset);
- stack_mask_bits_ = DecodeVarintBits(bit_region, &bit_offset);
- stack_masks_ = bit_region.Subregion(bit_offset, non_header_size * kBitsPerByte - bit_offset);
+ stack_masks_.Decode(bit_region, &bit_offset);
+ CHECK_EQ(BitsToBytesRoundUp(bit_offset), non_header_size);
}
size_t size_;
@@ -1056,9 +1072,8 @@ class CodeInfo {
BitTable<StackMap::Field::kCount> stack_maps_;
BitTable<InvokeInfo::Field::kCount> invoke_infos_;
BitTable<InlineInfo::Field::kCount> inline_infos_;
- BitTable<1> register_masks_;
- uint32_t stack_mask_bits_ = 0;
- BitMemoryRegion stack_masks_;
+ BitTable<RegisterMask::Field::kCount> register_masks_;
+ BitTable<1> stack_masks_;
friend class OatDumper;
};
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 129bae6d9a..95efc8a42e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2461,7 +2461,7 @@ class FetchStackTraceVisitor : public StackVisitor {
// save frame)
ArtMethod* m = GetMethod();
if (skipping_ && !m->IsRuntimeMethod() &&
- !mirror::Throwable::GetJavaLangThrowable()->IsAssignableFrom(m->GetDeclaringClass())) {
+ !GetClassRoot<mirror::Throwable>()->IsAssignableFrom(m->GetDeclaringClass())) {
skipping_ = false;
}
if (!skipping_) {
@@ -3568,9 +3568,8 @@ class ReferenceMapVisitor : public StackVisitor {
T vreg_info(m, code_info, map, visitor_);
// Visit stack entries that hold pointers.
- const size_t number_of_bits = code_info.GetNumberOfStackMaskBits();
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(map);
- for (size_t i = 0; i < number_of_bits; ++i) {
+ for (size_t i = 0; i < stack_mask.size_in_bits(); ++i) {
if (stack_mask.LoadBit(i)) {
StackReference<mirror::Object>* ref_addr = vreg_base + i;
mirror::Object* ref = ref_addr->AsMirrorPtr();
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 3a49e4d21f..cc71dc5f84 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3366,7 +3366,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
}
break;
}
- auto* klass = declaring_class.GetClass();
+ ObjPtr<mirror::Class> klass = declaring_class.GetClass();
for (uint32_t i = 0, num_fields = klass->NumInstanceFields(); i < num_fields; ++i) {
if (klass->GetInstanceField(i)->IsFinal()) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void-no-barrier not expected for "
@@ -3529,7 +3529,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
ObjPtr<mirror::Class> klass =
linker->ResolveType(handler_type_idx, dex_cache_, class_loader_);
if (klass != nullptr) {
- if (klass == mirror::Throwable::GetJavaLangThrowable()) {
+ if (klass == GetClassRoot<mirror::Throwable>()) {
has_catch_all_handler = true;
}
} else {
@@ -3667,10 +3667,10 @@ const RegType& MethodVerifier::ResolveClass(dex::TypeIndex class_idx) {
UninstantiableError(descriptor);
precise = false;
}
- result = reg_types_.FindClass(klass.Ptr(), precise);
+ result = reg_types_.FindClass(klass, precise);
if (result == nullptr) {
const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
- result = reg_types_.InsertClass(descriptor, klass.Ptr(), precise);
+ result = reg_types_.InsertClass(descriptor, klass, precise);
}
} else {
const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
@@ -4943,7 +4943,7 @@ const RegType& MethodVerifier::GetDeclaringClass() {
const char* descriptor
= dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
if (method_being_verified_ != nullptr) {
- mirror::Class* klass = method_being_verified_->GetDeclaringClass();
+ ObjPtr<mirror::Class> klass = method_being_verified_->GetDeclaringClass();
declaring_class_ = &FromClass(descriptor, klass, klass->CannotBeAssignedFromOtherTypes());
} else {
declaring_class_ = &reg_types_.FromDescriptor(GetClassLoader(), descriptor, false);
@@ -5045,7 +5045,7 @@ void MethodVerifier::VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
}
const RegType& MethodVerifier::FromClass(const char* descriptor,
- mirror::Class* klass,
+ ObjPtr<mirror::Class> klass,
bool precise) {
DCHECK(klass != nullptr);
if (precise && !klass->IsInstantiable() && !klass->IsPrimitive()) {
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 531d3dabfa..b2adc62a97 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -691,7 +691,7 @@ class MethodVerifier {
// non-precise reference will be returned.
// Note: we reuse NO_CLASS as this will throw an exception at runtime, when the failing class is
// actually touched.
- const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
+ const RegType& FromClass(const char* descriptor, ObjPtr<mirror::Class> klass, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
ALWAYS_INLINE bool FailOrAbort(bool condition, const char* error_msg, uint32_t work_insn_idx);
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index e7864a28a0..73e516c7bf 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -54,17 +54,19 @@ const DoubleHiType* DoubleHiType::instance_ = nullptr;
const IntegerType* IntegerType::instance_ = nullptr;
const NullType* NullType::instance_ = nullptr;
-PrimitiveType::PrimitiveType(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
+PrimitiveType::PrimitiveType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
+ uint16_t cache_id)
: RegType(klass, descriptor, cache_id) {
CHECK(klass != nullptr);
CHECK(!descriptor.empty());
}
-Cat1Type::Cat1Type(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
+Cat1Type::Cat1Type(ObjPtr<mirror::Class> klass, const StringPiece& descriptor, uint16_t cache_id)
: PrimitiveType(klass, descriptor, cache_id) {
}
-Cat2Type::Cat2Type(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
+Cat2Type::Cat2Type(ObjPtr<mirror::Class> klass, const StringPiece& descriptor, uint16_t cache_id)
: PrimitiveType(klass, descriptor, cache_id) {
}
@@ -129,7 +131,7 @@ std::string IntegerType::Dump() const {
return "Integer";
}
-const DoubleHiType* DoubleHiType::CreateInstance(mirror::Class* klass,
+const DoubleHiType* DoubleHiType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
@@ -144,7 +146,7 @@ void DoubleHiType::Destroy() {
}
}
-const DoubleLoType* DoubleLoType::CreateInstance(mirror::Class* klass,
+const DoubleLoType* DoubleLoType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
@@ -159,14 +161,16 @@ void DoubleLoType::Destroy() {
}
}
-const LongLoType* LongLoType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const LongLoType* LongLoType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new LongLoType(klass, descriptor, cache_id);
return instance_;
}
-const LongHiType* LongHiType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const LongHiType* LongHiType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new LongHiType(klass, descriptor, cache_id);
@@ -187,7 +191,8 @@ void LongLoType::Destroy() {
}
}
-const FloatType* FloatType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const FloatType* FloatType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new FloatType(klass, descriptor, cache_id);
@@ -201,7 +206,8 @@ void FloatType::Destroy() {
}
}
-const CharType* CharType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const CharType* CharType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new CharType(klass, descriptor, cache_id);
@@ -215,7 +221,8 @@ void CharType::Destroy() {
}
}
-const ShortType* ShortType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const ShortType* ShortType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new ShortType(klass, descriptor, cache_id);
@@ -229,7 +236,8 @@ void ShortType::Destroy() {
}
}
-const ByteType* ByteType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const ByteType* ByteType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new ByteType(klass, descriptor, cache_id);
@@ -243,7 +251,8 @@ void ByteType::Destroy() {
}
}
-const IntegerType* IntegerType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
+const IntegerType* IntegerType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
instance_ = new IntegerType(klass, descriptor, cache_id);
@@ -257,7 +266,7 @@ void IntegerType::Destroy() {
}
}
-const ConflictType* ConflictType::CreateInstance(mirror::Class* klass,
+const ConflictType* ConflictType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
@@ -272,8 +281,9 @@ void ConflictType::Destroy() {
}
}
-const BooleanType* BooleanType::CreateInstance(mirror::Class* klass, const StringPiece& descriptor,
- uint16_t cache_id) {
+const BooleanType* BooleanType::CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
+ uint16_t cache_id) {
CHECK(BooleanType::instance_ == nullptr);
instance_ = new BooleanType(klass, descriptor, cache_id);
return BooleanType::instance_;
@@ -290,7 +300,7 @@ std::string UndefinedType::Dump() const REQUIRES_SHARED(Locks::mutator_lock_) {
return "Undefined";
}
-const UndefinedType* UndefinedType::CreateInstance(mirror::Class* klass,
+const UndefinedType* UndefinedType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
@@ -305,7 +315,8 @@ void UndefinedType::Destroy() {
}
}
-PreciseReferenceType::PreciseReferenceType(mirror::Class* klass, const StringPiece& descriptor,
+PreciseReferenceType::PreciseReferenceType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id)
: RegType(klass, descriptor, cache_id) {
// Note: no check for IsInstantiable() here. We may produce this in case an InstantiationError
@@ -505,7 +516,7 @@ bool UnresolvedType::IsNonZeroReferenceTypes() const {
const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
if (!IsUnresolvedTypes()) {
- mirror::Class* super_klass = GetClass()->GetSuperClass();
+ ObjPtr<mirror::Class> super_klass = GetClass()->GetSuperClass();
if (super_klass != nullptr) {
// A super class of a precise type isn't precise as a precise type indicates the register
// holds exactly that type.
@@ -543,7 +554,7 @@ bool RegType::IsObjectArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
return descriptor_[0] == '[';
} else if (HasClass()) {
- mirror::Class* type = GetClass();
+ ObjPtr<mirror::Class> type = GetClass();
return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
} else {
return false;
@@ -569,7 +580,7 @@ bool RegType::IsArrayTypes() const REQUIRES_SHARED(Locks::mutator_lock_) {
bool RegType::IsJavaLangObjectArray() const {
if (HasClass()) {
- mirror::Class* type = GetClass();
+ ObjPtr<mirror::Class> type = GetClass();
return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
}
return false;
@@ -712,11 +723,10 @@ const RegType& RegType::Merge(const RegType& incoming_type,
// mechanics to continue.
return reg_types->FromUnresolvedMerge(*this, incoming_type, verifier);
} else { // Two reference types, compute Join
- mirror::Class* c1 = GetClass();
- mirror::Class* c2 = incoming_type.GetClass();
- DCHECK(c1 != nullptr && !c1->IsPrimitive());
- DCHECK(c2 != nullptr && !c2->IsPrimitive());
- mirror::Class* join_class = ClassJoin(c1, c2);
+ // Do not cache the classes as ClassJoin() can suspend and invalidate ObjPtr<>s.
+ DCHECK(GetClass() != nullptr && !GetClass()->IsPrimitive());
+ DCHECK(incoming_type.GetClass() != nullptr && !incoming_type.GetClass()->IsPrimitive());
+ ObjPtr<mirror::Class> join_class = ClassJoin(GetClass(), incoming_type.GetClass());
if (UNLIKELY(join_class == nullptr)) {
// Internal error joining the classes (e.g., OOME). Report an unresolved reference type.
// We cannot report an unresolved merge type, as that will attempt to merge the resolved
@@ -731,30 +741,37 @@ const RegType& RegType::Merge(const RegType& incoming_type,
// (In that case, it is likely a misconfiguration of dex2oat.)
if (!kIsTargetBuild && Runtime::Current()->IsAotCompiler()) {
LOG(FATAL) << "Could not create class join of "
- << c1->PrettyClass()
+ << GetClass()->PrettyClass()
<< " & "
- << c2->PrettyClass();
+ << incoming_type.GetClass()->PrettyClass();
UNREACHABLE();
}
return reg_types->MakeUnresolvedReference();
}
- // Record the dependency that both `c1` and `c2` are assignable to `join_class`.
- // The `verifier` is null during unit tests.
+ // Record the dependency that both `GetClass()` and `incoming_type.GetClass()`
+ // are assignable to `join_class`. The `verifier` is null during unit tests.
if (verifier != nullptr) {
- VerifierDeps::MaybeRecordAssignability(
- verifier->GetDexFile(), join_class, c1, true /* strict */, true /* is_assignable */);
- VerifierDeps::MaybeRecordAssignability(
- verifier->GetDexFile(), join_class, c2, true /* strict */, true /* is_assignable */);
+ VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
+ join_class,
+ GetClass(),
+ /* strict */ true,
+ /* is_assignable */ true);
+ VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(),
+ join_class,
+ incoming_type.GetClass(),
+ /* strict */ true,
+ /* is_assignable */ true);
}
- if (c1 == join_class && !IsPreciseReference()) {
+ if (GetClass() == join_class && !IsPreciseReference()) {
return *this;
- } else if (c2 == join_class && !incoming_type.IsPreciseReference()) {
+ } else if (incoming_type.GetClass() == join_class && !incoming_type.IsPreciseReference()) {
return incoming_type;
} else {
std::string temp;
- return reg_types->FromClass(join_class->GetDescriptor(&temp), join_class, false);
+ const char* descriptor = join_class->GetDescriptor(&temp);
+ return reg_types->FromClass(descriptor, join_class, /* precise */ false);
}
}
} else {
@@ -763,7 +780,7 @@ const RegType& RegType::Merge(const RegType& incoming_type,
}
// See comment in reg_type.h
-mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
+ObjPtr<mirror::Class> RegType::ClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t) {
DCHECK(!s->IsPrimitive()) << s->PrettyClass();
DCHECK(!t->IsPrimitive()) << t->PrettyClass();
if (s == t) {
@@ -773,12 +790,12 @@ mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
} else if (t->IsAssignableFrom(s)) {
return t;
} else if (s->IsArrayClass() && t->IsArrayClass()) {
- mirror::Class* s_ct = s->GetComponentType();
- mirror::Class* t_ct = t->GetComponentType();
+ ObjPtr<mirror::Class> s_ct = s->GetComponentType();
+ ObjPtr<mirror::Class> t_ct = t->GetComponentType();
if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
// Given the types aren't the same, if either array is of primitive types then the only
// common parent is java.lang.Object
- mirror::Class* result = s->GetSuperClass(); // short-cut to java.lang.Object
+ ObjPtr<mirror::Class> result = s->GetSuperClass(); // short-cut to java.lang.Object
DCHECK(result->IsObjectClass());
return result;
}
@@ -788,8 +805,9 @@ mirror::Class* RegType::ClassJoin(mirror::Class* s, mirror::Class* t) {
self->AssertPendingException();
return nullptr;
}
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- mirror::Class* array_class = class_linker->FindArrayClass(self, &common_elem);
+ // Note: The following lookup invalidates existing ObjPtr<>s.
+ ObjPtr<mirror::Class> array_class =
+ Runtime::Current()->GetClassLinker()->FindArrayClass(self, &common_elem);
if (UNLIKELY(array_class == nullptr)) {
self->AssertPendingException();
return nullptr;
@@ -971,7 +989,7 @@ bool RegType::CanAssignArray(const RegType& src,
return cmp1.CanAssignArray(cmp2, reg_types, class_loader, verifier, soft_error);
}
-const NullType* NullType::CreateInstance(mirror::Class* klass,
+const NullType* NullType::CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) {
CHECK(instance_ == nullptr);
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index 3e994074a1..29da376091 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -191,7 +191,7 @@ class RegType {
!IsUnresolvedSuperClass()));
return descriptor_;
}
- mirror::Class* GetClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
+ ObjPtr<mirror::Class> GetClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(!IsUnresolvedReference());
DCHECK(!klass_.IsNull()) << Dump();
DCHECK(HasClass());
@@ -318,7 +318,7 @@ class RegType {
}
protected:
- RegType(mirror::Class* klass,
+ RegType(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: descriptor_(descriptor),
@@ -365,7 +365,7 @@ class RegType {
*
* [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
*/
- static mirror::Class* ClassJoin(mirror::Class* s, mirror::Class* t)
+ static ObjPtr<mirror::Class> ClassJoin(ObjPtr<mirror::Class> s, ObjPtr<mirror::Class> t)
REQUIRES_SHARED(Locks::mutator_lock_);
static bool AssignableFrom(const RegType& lhs,
@@ -388,7 +388,7 @@ class ConflictType FINAL : public RegType {
static const ConflictType* GetInstance() PURE;
// Create the singleton instance.
- static const ConflictType* CreateInstance(mirror::Class* klass,
+ static const ConflictType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -401,7 +401,8 @@ class ConflictType FINAL : public RegType {
}
private:
- ConflictType(mirror::Class* klass, const StringPiece& descriptor,
+ ConflictType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -423,7 +424,7 @@ class UndefinedType FINAL : public RegType {
static const UndefinedType* GetInstance() PURE;
// Create the singleton instance.
- static const UndefinedType* CreateInstance(mirror::Class* klass,
+ static const UndefinedType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -436,7 +437,8 @@ class UndefinedType FINAL : public RegType {
}
private:
- UndefinedType(mirror::Class* klass, const StringPiece& descriptor,
+ UndefinedType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -447,7 +449,8 @@ class UndefinedType FINAL : public RegType {
class PrimitiveType : public RegType {
public:
- PrimitiveType(mirror::Class* klass, const StringPiece& descriptor,
+ PrimitiveType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
bool HasClassVirtual() const OVERRIDE { return true; }
@@ -455,7 +458,7 @@ class PrimitiveType : public RegType {
class Cat1Type : public PrimitiveType {
public:
- Cat1Type(mirror::Class* klass, const StringPiece& descriptor,
+ Cat1Type(ObjPtr<mirror::Class> klass, const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
};
@@ -463,7 +466,7 @@ class IntegerType FINAL : public Cat1Type {
public:
bool IsInteger() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const IntegerType* CreateInstance(mirror::Class* klass,
+ static const IntegerType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -475,7 +478,8 @@ class IntegerType FINAL : public Cat1Type {
}
private:
- IntegerType(mirror::Class* klass, const StringPiece& descriptor,
+ IntegerType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -487,7 +491,7 @@ class BooleanType FINAL : public Cat1Type {
public:
bool IsBoolean() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const BooleanType* CreateInstance(mirror::Class* klass,
+ static const BooleanType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -499,7 +503,8 @@ class BooleanType FINAL : public Cat1Type {
}
private:
- BooleanType(mirror::Class* klass, const StringPiece& descriptor,
+ BooleanType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -512,7 +517,7 @@ class ByteType FINAL : public Cat1Type {
public:
bool IsByte() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const ByteType* CreateInstance(mirror::Class* klass,
+ static const ByteType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -524,7 +529,8 @@ class ByteType FINAL : public Cat1Type {
}
private:
- ByteType(mirror::Class* klass, const StringPiece& descriptor,
+ ByteType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -536,7 +542,7 @@ class ShortType FINAL : public Cat1Type {
public:
bool IsShort() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const ShortType* CreateInstance(mirror::Class* klass,
+ static const ShortType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -548,7 +554,7 @@ class ShortType FINAL : public Cat1Type {
}
private:
- ShortType(mirror::Class* klass, const StringPiece& descriptor,
+ ShortType(ObjPtr<mirror::Class> klass, const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -560,7 +566,7 @@ class CharType FINAL : public Cat1Type {
public:
bool IsChar() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const CharType* CreateInstance(mirror::Class* klass,
+ static const CharType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -572,7 +578,8 @@ class CharType FINAL : public Cat1Type {
}
private:
- CharType(mirror::Class* klass, const StringPiece& descriptor,
+ CharType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -584,7 +591,7 @@ class FloatType FINAL : public Cat1Type {
public:
bool IsFloat() const OVERRIDE { return true; }
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
- static const FloatType* CreateInstance(mirror::Class* klass,
+ static const FloatType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -596,7 +603,8 @@ class FloatType FINAL : public Cat1Type {
}
private:
- FloatType(mirror::Class* klass, const StringPiece& descriptor,
+ FloatType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat1Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -606,7 +614,8 @@ class FloatType FINAL : public Cat1Type {
class Cat2Type : public PrimitiveType {
public:
- Cat2Type(mirror::Class* klass, const StringPiece& descriptor,
+ Cat2Type(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_);
};
@@ -615,7 +624,7 @@ class LongLoType FINAL : public Cat2Type {
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
bool IsLongLo() const OVERRIDE { return true; }
bool IsLong() const OVERRIDE { return true; }
- static const LongLoType* CreateInstance(mirror::Class* klass,
+ static const LongLoType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -627,7 +636,8 @@ class LongLoType FINAL : public Cat2Type {
}
private:
- LongLoType(mirror::Class* klass, const StringPiece& descriptor,
+ LongLoType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -639,7 +649,7 @@ class LongHiType FINAL : public Cat2Type {
public:
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
bool IsLongHi() const OVERRIDE { return true; }
- static const LongHiType* CreateInstance(mirror::Class* klass,
+ static const LongHiType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -651,7 +661,8 @@ class LongHiType FINAL : public Cat2Type {
}
private:
- LongHiType(mirror::Class* klass, const StringPiece& descriptor,
+ LongHiType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -664,7 +675,7 @@ class DoubleLoType FINAL : public Cat2Type {
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
bool IsDoubleLo() const OVERRIDE { return true; }
bool IsDouble() const OVERRIDE { return true; }
- static const DoubleLoType* CreateInstance(mirror::Class* klass,
+ static const DoubleLoType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -676,7 +687,8 @@ class DoubleLoType FINAL : public Cat2Type {
}
private:
- DoubleLoType(mirror::Class* klass, const StringPiece& descriptor,
+ DoubleLoType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -688,9 +700,9 @@ class DoubleHiType FINAL : public Cat2Type {
public:
std::string Dump() const OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
virtual bool IsDoubleHi() const OVERRIDE { return true; }
- static const DoubleHiType* CreateInstance(mirror::Class* klass,
- const StringPiece& descriptor,
- uint16_t cache_id)
+ static const DoubleHiType* CreateInstance(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
+ uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
static const DoubleHiType* GetInstance() PURE;
static void Destroy();
@@ -700,7 +712,8 @@ class DoubleHiType FINAL : public Cat2Type {
}
private:
- DoubleHiType(mirror::Class* klass, const StringPiece& descriptor,
+ DoubleHiType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: Cat2Type(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -872,7 +885,7 @@ class NullType FINAL : public RegType {
static const NullType* GetInstance() PURE;
// Create the singleton instance.
- static const NullType* CreateInstance(mirror::Class* klass,
+ static const NullType* CreateInstance(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -892,7 +905,7 @@ class NullType FINAL : public RegType {
}
private:
- NullType(mirror::Class* klass, const StringPiece& descriptor, uint16_t cache_id)
+ NullType(ObjPtr<mirror::Class> klass, const StringPiece& descriptor, uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -906,8 +919,10 @@ class NullType FINAL : public RegType {
// instructions and must be passed to a constructor.
class UninitializedType : public RegType {
public:
- UninitializedType(mirror::Class* klass, const StringPiece& descriptor,
- uint32_t allocation_pc, uint16_t cache_id)
+ UninitializedType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
+ uint32_t allocation_pc,
+ uint16_t cache_id)
: RegType(klass, descriptor, cache_id), allocation_pc_(allocation_pc) {}
bool IsUninitializedTypes() const OVERRIDE;
@@ -929,9 +944,10 @@ class UninitializedType : public RegType {
// Similar to ReferenceType but not yet having been passed to a constructor.
class UninitializedReferenceType FINAL : public UninitializedType {
public:
- UninitializedReferenceType(mirror::Class* klass,
+ UninitializedReferenceType(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
- uint32_t allocation_pc, uint16_t cache_id)
+ uint32_t allocation_pc,
+ uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
: UninitializedType(klass, descriptor, allocation_pc, cache_id) {
CheckConstructorInvariants(this);
@@ -969,7 +985,7 @@ class UnresolvedUninitializedRefType FINAL : public UninitializedType {
// of a constructor.
class UninitializedThisReferenceType FINAL : public UninitializedType {
public:
- UninitializedThisReferenceType(mirror::Class* klass,
+ UninitializedThisReferenceType(ObjPtr<mirror::Class> klass,
const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_)
@@ -1010,7 +1026,8 @@ class UnresolvedUninitializedThisRefType FINAL : public UninitializedType {
// sub-class.
class ReferenceType FINAL : public RegType {
public:
- ReferenceType(mirror::Class* klass, const StringPiece& descriptor,
+ ReferenceType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id) REQUIRES_SHARED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
CheckConstructorInvariants(this);
@@ -1034,7 +1051,8 @@ class ReferenceType FINAL : public RegType {
// type.
class PreciseReferenceType FINAL : public RegType {
public:
- PreciseReferenceType(mirror::Class* klass, const StringPiece& descriptor,
+ PreciseReferenceType(ObjPtr<mirror::Class> klass,
+ const StringPiece& descriptor,
uint16_t cache_id)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/verifier/reg_type_cache-inl.h b/runtime/verifier/reg_type_cache-inl.h
index 43c0ab9598..9f87adfa31 100644
--- a/runtime/verifier/reg_type_cache-inl.h
+++ b/runtime/verifier/reg_type_cache-inl.h
@@ -124,36 +124,42 @@ inline const ImpreciseConstType& RegTypeCache::PosShortConstant() {
}
inline const PreciseReferenceType& RegTypeCache::JavaLangClass() {
- const RegType* result = &FromClass("Ljava/lang/Class;", mirror::Class::GetJavaLangClass(), true);
+ const RegType* result = &FromClass("Ljava/lang/Class;",
+ GetClassRoot<mirror::Class>(),
+ /* precise */ true);
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
}
inline const PreciseReferenceType& RegTypeCache::JavaLangString() {
// String is final and therefore always precise.
- const RegType* result = &FromClass("Ljava/lang/String;", mirror::String::GetJavaLangString(),
- true);
+ const RegType* result = &FromClass("Ljava/lang/String;",
+ GetClassRoot<mirror::String>(),
+ /* precise */ true);
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
}
inline const PreciseReferenceType& RegTypeCache::JavaLangInvokeMethodHandle() {
const RegType* result = &FromClass("Ljava/lang/invoke/MethodHandle;",
- GetClassRoot<mirror::MethodHandle>().Ptr(), true);
+ GetClassRoot<mirror::MethodHandle>(),
+ /* precise */ true);
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
}
inline const PreciseReferenceType& RegTypeCache::JavaLangInvokeMethodType() {
const RegType* result = &FromClass("Ljava/lang/invoke/MethodType;",
- GetClassRoot<mirror::MethodType>().Ptr(), true);
+ GetClassRoot<mirror::MethodType>(),
+ /* precise */ true);
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
}
inline const RegType& RegTypeCache::JavaLangThrowable(bool precise) {
const RegType* result = &FromClass("Ljava/lang/Throwable;",
- mirror::Throwable::GetJavaLangThrowable(), precise);
+ GetClassRoot<mirror::Throwable>(),
+ precise);
if (precise) {
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
@@ -164,8 +170,7 @@ inline const RegType& RegTypeCache::JavaLangThrowable(bool precise) {
}
inline const RegType& RegTypeCache::JavaLangObject(bool precise) {
- const RegType* result = &FromClass("Ljava/lang/Object;",
- mirror::Class::GetJavaLangClass()->GetSuperClass(), precise);
+ const RegType* result = &FromClass("Ljava/lang/Object;", GetClassRoot<mirror::Object>(), precise);
if (precise) {
DCHECK(result->IsPreciseReference());
return *down_cast<const PreciseReferenceType*>(result);
@@ -180,7 +185,7 @@ inline RegTypeType& RegTypeCache::AddEntry(RegTypeType* new_entry) {
DCHECK(new_entry != nullptr);
entries_.push_back(new_entry);
if (new_entry->HasClass()) {
- mirror::Class* klass = new_entry->GetClass();
+ ObjPtr<mirror::Class> klass = new_entry->GetClass();
DCHECK(!klass->IsPrimitive());
klass_entries_.push_back(std::make_pair(GcRoot<mirror::Class>(klass), new_entry));
}
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 87fc60bd23..f1f3488a3c 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -77,7 +77,7 @@ void RegTypeCache::FillPrimitiveAndSmallConstantTypes() {
DCHECK_EQ(entries_.size(), primitive_count_);
}
-const RegType& RegTypeCache::FromDescriptor(mirror::ClassLoader* loader,
+const RegType& RegTypeCache::FromDescriptor(ObjPtr<mirror::ClassLoader> loader,
const char* descriptor,
bool precise) {
DCHECK(RegTypeCache::primitive_initialized_);
@@ -149,14 +149,15 @@ bool RegTypeCache::MatchDescriptor(size_t idx, const StringPiece& descriptor, bo
return true;
}
-mirror::Class* RegTypeCache::ResolveClass(const char* descriptor, mirror::ClassLoader* loader) {
+ObjPtr<mirror::Class> RegTypeCache::ResolveClass(const char* descriptor,
+ ObjPtr<mirror::ClassLoader> loader) {
// Class was not found, must create new type.
// Try resolving class
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Thread* self = Thread::Current();
StackHandleScope<1> hs(self);
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(loader));
- mirror::Class* klass = nullptr;
+ ObjPtr<mirror::Class> klass = nullptr;
if (can_load_classes_) {
klass = class_linker->FindClass(self, descriptor, class_loader);
} else {
@@ -175,7 +176,7 @@ StringPiece RegTypeCache::AddString(const StringPiece& string_piece) {
return StringPiece(ptr, string_piece.length());
}
-const RegType& RegTypeCache::From(mirror::ClassLoader* loader,
+const RegType& RegTypeCache::From(ObjPtr<mirror::ClassLoader> loader,
const char* descriptor,
bool precise) {
StringPiece sp_descriptor(descriptor);
@@ -188,7 +189,7 @@ const RegType& RegTypeCache::From(mirror::ClassLoader* loader,
}
// Class not found in the cache, will create a new type for that.
// Try resolving class.
- mirror::Class* klass = ResolveClass(descriptor, loader);
+ ObjPtr<mirror::Class> klass = ResolveClass(descriptor, loader);
if (klass != nullptr) {
// Class resolved, first look for the class in the list of entries
// Class was not found, must create new type.
@@ -234,7 +235,7 @@ const RegType& RegTypeCache::MakeUnresolvedReference() {
return AddEntry(new (&allocator_) UnresolvedReferenceType(AddString("a"), entries_.size()));
}
-const RegType* RegTypeCache::FindClass(mirror::Class* klass, bool precise) const {
+const RegType* RegTypeCache::FindClass(ObjPtr<mirror::Class> klass, bool precise) const {
DCHECK(klass != nullptr);
if (klass->IsPrimitive()) {
// Note: precise isn't used for primitive classes. A char is assignable to an int. All
@@ -242,7 +243,7 @@ const RegType* RegTypeCache::FindClass(mirror::Class* klass, bool precise) const
return &RegTypeFromPrimitiveType(klass->GetPrimitiveType());
}
for (auto& pair : klass_entries_) {
- mirror::Class* const reg_klass = pair.first.Read();
+ ObjPtr<mirror::Class> const reg_klass = pair.first.Read();
if (reg_klass == klass) {
const RegType* reg_type = pair.second;
if (MatchingPrecisionForClass(reg_type, precise)) {
@@ -254,7 +255,7 @@ const RegType* RegTypeCache::FindClass(mirror::Class* klass, bool precise) const
}
const RegType* RegTypeCache::InsertClass(const StringPiece& descriptor,
- mirror::Class* klass,
+ ObjPtr<mirror::Class> klass,
bool precise) {
// No reference to the class was found, create new reference.
DCHECK(FindClass(klass, precise) == nullptr);
@@ -265,7 +266,9 @@ const RegType* RegTypeCache::InsertClass(const StringPiece& descriptor,
return &AddEntry(reg_type);
}
-const RegType& RegTypeCache::FromClass(const char* descriptor, mirror::Class* klass, bool precise) {
+const RegType& RegTypeCache::FromClass(const char* descriptor,
+ ObjPtr<mirror::Class> klass,
+ bool precise) {
DCHECK(klass != nullptr);
const RegType* reg_type = FindClass(klass, precise);
if (reg_type == nullptr) {
@@ -342,7 +345,7 @@ void RegTypeCache::CreatePrimitiveAndSmallConstantTypes() {
// code cannot leak to other users.
auto create_primitive_type_instance = [&](auto type) REQUIRES_SHARED(Locks::mutator_lock_) {
using Type = typename decltype(type)::type;
- mirror::Class* klass = nullptr;
+ ObjPtr<mirror::Class> klass = nullptr;
// Try loading the class from linker.
DCHECK(type.descriptor != nullptr);
if (strlen(type.descriptor) > 0) {
@@ -500,7 +503,7 @@ const UninitializedType& RegTypeCache::Uninitialized(const RegType& type, uint32
allocation_pc,
entries_.size());
} else {
- mirror::Class* klass = type.GetClass();
+ ObjPtr<mirror::Class> klass = type.GetClass();
for (size_t i = primitive_count_; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUninitializedReference() &&
@@ -532,7 +535,7 @@ const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
}
entry = new (&allocator_) UnresolvedReferenceType(descriptor, entries_.size());
} else {
- mirror::Class* klass = uninit_type.GetClass();
+ ObjPtr<mirror::Class> klass = uninit_type.GetClass();
if (uninit_type.IsUninitializedThisReference() && !klass->IsFinal()) {
// For uninitialized "this reference" look for reference types that are not precise.
for (size_t i = primitive_count_; i < entries_.size(); i++) {
@@ -583,7 +586,7 @@ const UninitializedType& RegTypeCache::UninitializedThisArgument(const RegType&
}
entry = new (&allocator_) UnresolvedUninitializedThisRefType(descriptor, entries_.size());
} else {
- mirror::Class* klass = type.GetClass();
+ ObjPtr<mirror::Class> klass = type.GetClass();
for (size_t i = primitive_count_; i < entries_.size(); i++) {
const RegType* cur_entry = entries_[i];
if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
@@ -647,7 +650,8 @@ const ConstantType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
return AddEntry(entry);
}
-const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::ClassLoader* loader) {
+const RegType& RegTypeCache::GetComponentType(const RegType& array,
+ ObjPtr<mirror::ClassLoader> loader) {
if (!array.IsArrayTypes()) {
return Conflict();
} else if (array.IsUnresolvedTypes()) {
@@ -655,7 +659,7 @@ const RegType& RegTypeCache::GetComponentType(const RegType& array, mirror::Clas
const std::string descriptor(array.GetDescriptor().as_string());
return FromDescriptor(loader, descriptor.c_str() + 1, false);
} else {
- mirror::Class* klass = array.GetClass()->GetComponentType();
+ ObjPtr<mirror::Class> klass = array.GetClass()->GetComponentType();
std::string temp;
const char* descriptor = klass->GetDescriptor(&temp);
if (klass->IsErroneous()) {
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index b32dc115a7..d668222901 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -74,16 +74,18 @@ class RegTypeCache {
}
static void ShutDown();
const art::verifier::RegType& GetFromId(uint16_t id) const;
- const RegType& From(mirror::ClassLoader* loader, const char* descriptor, bool precise)
+ const RegType& From(ObjPtr<mirror::ClassLoader> loader, const char* descriptor, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
// Find a RegType, returns null if not found.
- const RegType* FindClass(mirror::Class* klass, bool precise) const
+ const RegType* FindClass(ObjPtr<mirror::Class> klass, bool precise) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Insert a new class with a specified descriptor, must not already be in the cache.
- const RegType* InsertClass(const StringPiece& descriptor, mirror::Class* klass, bool precise)
+ const RegType* InsertClass(const StringPiece& descriptor,
+ ObjPtr<mirror::Class> klass,
+ bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
// Get or insert a reg type for a description, klass, and precision.
- const RegType& FromClass(const char* descriptor, mirror::Class* klass, bool precise)
+ const RegType& FromClass(const char* descriptor, ObjPtr<mirror::Class> klass, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
const ConstantType& FromCat1Const(int32_t value, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -91,7 +93,9 @@ class RegTypeCache {
REQUIRES_SHARED(Locks::mutator_lock_);
const ConstantType& FromCat2ConstHi(int32_t value, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
- const RegType& FromDescriptor(mirror::ClassLoader* loader, const char* descriptor, bool precise)
+ const RegType& FromDescriptor(ObjPtr<mirror::ClassLoader> loader,
+ const char* descriptor,
+ bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
const RegType& FromUnresolvedMerge(const RegType& left,
const RegType& right,
@@ -146,7 +150,7 @@ class RegTypeCache {
const ImpreciseConstType& IntConstant() REQUIRES_SHARED(Locks::mutator_lock_);
const ImpreciseConstType& PosByteConstant() REQUIRES_SHARED(Locks::mutator_lock_);
const ImpreciseConstType& PosShortConstant() REQUIRES_SHARED(Locks::mutator_lock_);
- const RegType& GetComponentType(const RegType& array, mirror::ClassLoader* loader)
+ const RegType& GetComponentType(const RegType& array, ObjPtr<mirror::ClassLoader> loader)
REQUIRES_SHARED(Locks::mutator_lock_);
void Dump(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_);
const RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
@@ -158,7 +162,7 @@ class RegTypeCache {
private:
void FillPrimitiveAndSmallConstantTypes() REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)
+ ObjPtr<mirror::Class> ResolveClass(const char* descriptor, ObjPtr<mirror::ClassLoader> loader)
REQUIRES_SHARED(Locks::mutator_lock_);
bool MatchDescriptor(size_t idx, const StringPiece& descriptor, bool precise)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index fe839f7312..500cc37af4 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -77,8 +77,8 @@ const VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex
static constexpr uint32_t kAccVdexAccessFlags =
kAccPublic | kAccPrivate | kAccProtected | kAccStatic | kAccInterface;
-template <typename T>
-uint16_t VerifierDeps::GetAccessFlags(T* element) {
+template <typename Ptr>
+uint16_t VerifierDeps::GetAccessFlags(Ptr element) {
static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
if (element == nullptr) {
return VerifierDeps::kUnresolvedMarker;
@@ -277,7 +277,7 @@ bool VerifierDeps::IsInClassPath(ObjPtr<mirror::Class> klass) const {
void VerifierDeps::AddClassResolution(const DexFile& dex_file,
dex::TypeIndex type_idx,
- mirror::Class* klass) {
+ ObjPtr<mirror::Class> klass) {
DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
if (dex_deps == nullptr) {
// This invocation is from verification of a dex file which is not being compiled.
@@ -336,12 +336,13 @@ void VerifierDeps::AddMethodResolution(const DexFile& dex_file,
dex_deps->methods_.insert(method_tuple);
}
-mirror::Class* VerifierDeps::FindOneClassPathBoundaryForInterface(mirror::Class* destination,
- mirror::Class* source) const {
+ObjPtr<mirror::Class> VerifierDeps::FindOneClassPathBoundaryForInterface(
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source) const {
DCHECK(destination->IsInterface());
DCHECK(IsInClassPath(destination));
Thread* thread = Thread::Current();
- mirror::Class* current = source;
+ ObjPtr<mirror::Class> current = source;
// Record the classes that are at the boundary between the compiled DEX files and
// the classpath. We will check those classes later to find one class that inherits
// `destination`.
@@ -367,7 +368,7 @@ mirror::Class* VerifierDeps::FindOneClassPathBoundaryForInterface(mirror::Class*
int32_t iftable_count = source->GetIfTableCount();
ObjPtr<mirror::IfTable> iftable = source->GetIfTable();
for (int32_t i = 0; i < iftable_count; ++i) {
- mirror::Class* itf = iftable->GetInterface(i);
+ ObjPtr<mirror::Class> itf = iftable->GetInterface(i);
if (!IsInClassPath(itf)) {
for (size_t j = 0; j < itf->NumDirectInterfaces(); ++j) {
ObjPtr<mirror::Class> direct = mirror::Class::GetDirectInterface(thread, itf, j);
@@ -391,8 +392,8 @@ mirror::Class* VerifierDeps::FindOneClassPathBoundaryForInterface(mirror::Class*
}
void VerifierDeps::AddAssignability(const DexFile& dex_file,
- mirror::Class* destination,
- mirror::Class* source,
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source,
bool is_strict,
bool is_assignable) {
// Test that the method is only called on reference types.
@@ -429,8 +430,8 @@ void VerifierDeps::AddAssignability(const DexFile& dex_file,
// Both types are arrays. Break down to component types and add recursively.
// This helps filter out destinations from compiled DEX files (see below)
// and deduplicate entries with the same canonical component type.
- mirror::Class* destination_component = destination->GetComponentType();
- mirror::Class* source_component = source->GetComponentType();
+ ObjPtr<mirror::Class> destination_component = destination->GetComponentType();
+ ObjPtr<mirror::Class> source_component = source->GetComponentType();
// Only perform the optimization if both types are resolved which guarantees
// that they linked successfully, as required at the top of this method.
@@ -511,7 +512,7 @@ void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file,
void VerifierDeps::MaybeRecordClassResolution(const DexFile& dex_file,
dex::TypeIndex type_idx,
- mirror::Class* klass) {
+ ObjPtr<mirror::Class> klass) {
VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
if (thread_deps != nullptr) {
thread_deps->AddClassResolution(dex_file, type_idx, klass);
@@ -537,8 +538,8 @@ void VerifierDeps::MaybeRecordMethodResolution(const DexFile& dex_file,
}
void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file,
- mirror::Class* destination,
- mirror::Class* source,
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source,
bool is_strict,
bool is_assignable) {
VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
@@ -858,12 +859,12 @@ bool VerifierDeps::ValidateDependencies(Handle<mirror::ClassLoader> class_loader
// TODO: share that helper with other parts of the compiler that have
// the same lookup pattern.
-static mirror::Class* FindClassAndClearException(ClassLinker* class_linker,
- Thread* self,
- const char* name,
- Handle<mirror::ClassLoader> class_loader)
+static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker,
+ Thread* self,
+ const char* name,
+ Handle<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_) {
- mirror::Class* result = class_linker->FindClass(self, name, class_loader);
+ ObjPtr<mirror::Class> result = class_linker->FindClass(self, name, class_loader);
if (result == nullptr) {
DCHECK(self->IsExceptionPending());
self->ClearException();
@@ -971,7 +972,7 @@ bool VerifierDeps::VerifyFields(Handle<mirror::ClassLoader> class_loader,
std::string expected_decl_klass = entry.IsResolved()
? GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
: dex_file.StringByTypeIdx(field_id.class_idx_);
- mirror::Class* cls = FindClassAndClearException(
+ ObjPtr<mirror::Class> cls = FindClassAndClearException(
class_linker, self, expected_decl_klass.c_str(), class_loader);
if (cls == nullptr) {
LOG(INFO) << "VerifierDeps: Could not resolve class " << expected_decl_klass;
@@ -1034,7 +1035,7 @@ bool VerifierDeps::VerifyMethods(Handle<mirror::ClassLoader> class_loader,
? GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
: dex_file.StringByTypeIdx(method_id.class_idx_);
- mirror::Class* cls = FindClassAndClearException(
+ ObjPtr<mirror::Class> cls = FindClassAndClearException(
class_linker, self, expected_decl_klass.c_str(), class_loader);
if (cls == nullptr) {
LOG(INFO) << "VerifierDeps: Could not resolve class " << expected_decl_klass;
diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h
index 94441da7e2..0146b17020 100644
--- a/runtime/verifier/verifier_deps.h
+++ b/runtime/verifier/verifier_deps.h
@@ -75,7 +75,7 @@ class VerifierDeps {
// If `klass` is null, the class is assumed unresolved.
static void MaybeRecordClassResolution(const DexFile& dex_file,
dex::TypeIndex type_idx,
- mirror::Class* klass)
+ ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::verifier_deps_lock_);
@@ -99,8 +99,8 @@ class VerifierDeps {
// to `destination` as defined by RegType::AssignableFrom. `dex_file` is the
// owner of the method for which MethodVerifier performed the assignability test.
static void MaybeRecordAssignability(const DexFile& dex_file,
- mirror::Class* destination,
- mirror::Class* source,
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source,
bool is_strict,
bool is_assignable)
REQUIRES_SHARED(Locks::mutator_lock_)
@@ -218,8 +218,8 @@ class VerifierDeps {
// Finds the class in the classpath that makes `source` inherit` from `destination`.
// Returns null if a class defined in the compiled DEX files, and assignable to
// `source`, direclty inherits from `destination`.
- mirror::Class* FindOneClassPathBoundaryForInterface(mirror::Class* destination,
- mirror::Class* source) const
+ ObjPtr<mirror::Class> FindOneClassPathBoundaryForInterface(ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the index of `str`. If it is defined in `dex_file_`, this is the dex
@@ -234,8 +234,8 @@ class VerifierDeps {
// Returns the bytecode access flags of `element` (bottom 16 bits), or
// `kUnresolvedMarker` if `element` is null.
- template <typename T>
- static uint16_t GetAccessFlags(T* element)
+ template <typename Ptr>
+ static uint16_t GetAccessFlags(Ptr element)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns a string ID of the descriptor of the declaring class of `element`,
@@ -256,7 +256,7 @@ class VerifierDeps {
void AddClassResolution(const DexFile& dex_file,
dex::TypeIndex type_idx,
- mirror::Class* klass)
+ ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::verifier_deps_lock_);
@@ -273,8 +273,8 @@ class VerifierDeps {
REQUIRES(!Locks::verifier_deps_lock_);
void AddAssignability(const DexFile& dex_file,
- mirror::Class* destination,
- mirror::Class* source,
+ ObjPtr<mirror::Class> destination,
+ ObjPtr<mirror::Class> source,
bool is_strict,
bool is_assignable)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/test/166-bad-interface-super/build b/test/166-bad-interface-super/build
index d85147f17b..bba6184e16 100644
--- a/test/166-bad-interface-super/build
+++ b/test/166-bad-interface-super/build
@@ -14,7 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# See b/65168732
-export USE_D8=false
+# Use the jasmin sources for JVM, otherwise the smali sources.
+extra_arg="--no-jasmin"
-./default-build "$@"
+for arg in "$@"; do
+ if [[ "$arg" == "--jvm" ]]; then
+ extra_arg="--no-smali"
+ break
+ fi
+done
+
+./default-build "$@" "$extra_arg"
diff --git a/test/476-checker-ctor-fence-redun-elim/build b/test/166-bad-interface-super/smali/BadSuper1.smali
index 10ffcc537d..6233403897 100644
--- a/test/476-checker-ctor-fence-redun-elim/build
+++ b/test/166-bad-interface-super/smali/BadSuper1.smali
@@ -1,6 +1,4 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
+# Copyright (C) 2018 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.
@@ -14,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
+.class public interface LBadSuper1;
+.super LBaseInterface;
+.source "BadSuper1.j"
diff --git a/test/450-checker-types/build b/test/166-bad-interface-super/smali/BadSuper2.smali
index 10ffcc537d..8e410cf1b4 100755..100644
--- a/test/450-checker-types/build
+++ b/test/166-bad-interface-super/smali/BadSuper2.smali
@@ -1,6 +1,4 @@
-#!/bin/bash
-#
-# Copyright 2017 The Android Open Source Project
+# Copyright (C) 2018 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.
@@ -14,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# See b/65168732
-export USE_D8=false
-
-./default-build "$@"
+.class public interface LBadSuper2;
+.super LBaseClass;
+.source "BadSuper2.j"
diff --git a/test/dexdump/run-all-tests b/test/dexdump/run-all-tests
index c9976cd090..e555a44e5d 100755
--- a/test/dexdump/run-all-tests
+++ b/test/dexdump/run-all-tests
@@ -37,51 +37,73 @@ prog="${progdir}"/`basename "${prog}"`
tmpdir=/tmp/test-$$
mkdir ${tmpdir}
-# Set up dexdump binary and flags to test.
-DEXD="${ANDROID_HOST_OUT}/bin/dexdump2"
-DEXDFLAGS1="-adfh"
-DEXDFLAGS2="-e -l xml"
+# Set up tools and commands to run
+DEXDUMP="${ANDROID_HOST_OUT}/bin/dexdump2"
+DEXLIST="${ANDROID_HOST_OUT}/bin/dexlist"
-# Set up dexlist binary and flags to test.
-DEXL="${ANDROID_HOST_OUT}/bin/dexlist"
-DEXLFLAGS=""
+declare -A SUFFIX_COMMAND_MAP
+SUFFIX_COMMAND_MAP[txt]="${DEXDUMP} -adfh"
+SUFFIX_COMMAND_MAP[xml]="${DEXDUMP} -e -l xml"
+SUFFIX_COMMAND_MAP[lst]="${DEXLIST}"
+
+# Parse command-line options
+UPDATE="no"
+USAGE="no"
+while [ $# -ne 0 ]; do
+ case "$1" in
+ --update)
+ UPDATE="yes"
+ ;;
+ *)
+ echo "Unknown option $1" 1>&2
+ USAGE="yes"
+ ;;
+ esac
+ shift
+done
+
+if [ "${USAGE}" = "yes" ]; then
+ cat 1>&2 <<USAGE_END
+Usage:
+ ${prog##*/} [--update]
+Options:
+ --update Update reference outputs
+USAGE_END
+ exit 1
+fi
+
+if [ "${UPDATE}" = "yes" ]; then
+ for dex in *.dex; do
+ for suffix in ${!SUFFIX_COMMAND_MAP[@]}; do
+ new_output=${dex%%.*}.${suffix}
+ ${SUFFIX_COMMAND_MAP[${suffix}]} ${dex} > ${new_output}
+ if [ $? -ne 0 ]; then
+ echo "Failed running ${SUFFIX_COMMAND_MAP[${suffix}]} ${dex} > ${new_output}" 2>&1
+ exit 1
+ fi
+ done
+ done
+ exit 0
+fi
# Run the tests.
passed=0
failed=0
-for i in *.dex; do
- echo $i
- basenm=`basename "${i}" .dex`
- txtfile=${basenm}.txt
- xmlfile=${basenm}.xml
- lstfile=${basenm}.lst
- gentxtfile=${tmpdir}/${txtfile}
- genxmlfile=${tmpdir}/${xmlfile}
- genlstfile=${tmpdir}/${lstfile}
- ${DEXD} ${DEXDFLAGS1} ${i} > ${gentxtfile}
- cmp ${txtfile} ${gentxtfile}
- if [ "$?" = "0" ]; then
- ((passed += 1))
- else
- ((failed += 1))
- echo failed: ${i}
- fi
- ${DEXD} ${DEXDFLAGS2} ${i} > ${genxmlfile}
- cmp ${xmlfile} ${genxmlfile}
- if [ "$?" = "0" ]; then
- ((passed += 1))
- else
- ((failed += 1))
- echo failed: ${i}
- fi
- ${DEXL} ${DEXLFLAGS} ${i} > ${genlstfile}
- cmp ${lstfile} ${genlstfile}
+for dex in *.dex; do
+ echo ${dex}
+ for suffix in ${!SUFFIX_COMMAND_MAP[@]}; do
+ expected_output=${dex%%.*}.${suffix}
+ actual_output=${tmpdir}/${expected_output}
+ cmd="${SUFFIX_COMMAND_MAP[${suffix}]} ${dex}"
+ ${cmd} > ${actual_output}
+ cmp ${expected_output} ${actual_output}
if [ "$?" = "0" ]; then
((passed += 1))
else
((failed += 1))
- echo failed: ${i}
+ echo failed: ${cmd}
fi
+ done
done
# Report results.
diff --git a/test/etc/default-build b/test/etc/default-build
index d0ebe80e68..9dbc73c6b4 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -169,6 +169,9 @@ while true; do
elif [ "x$1" = "x--no-smali" ]; then
HAS_SMALI=false
shift
+ elif [ "x$1" = "x--no-jasmin" ]; then
+ HAS_JASMIN=false
+ shift
elif [ "x$1" = "x--experimental" ]; then
shift
# We have a specific experimental configuration so don't use the default.
diff --git a/tools/cleanup-buildbot-device.sh b/tools/cleanup-buildbot-device.sh
index 2144b02c2f..ca5219aa25 100755
--- a/tools/cleanup-buildbot-device.sh
+++ b/tools/cleanup-buildbot-device.sh
@@ -40,7 +40,7 @@ if [[ -n "$ART_TEST_CHROOT" ]]; then
#
# TODO: Reorder ART Buildbot steps so that "device cleanup" happens
# before "setup device" and remove this special case.
- adb shell test -f "$ART_TEST_CHROOT/system" \
+ adb shell test -d "$ART_TEST_CHROOT/system" \
"&&" find "$ART_TEST_CHROOT/system" \
! -path "$ART_TEST_CHROOT/system/etc/selinux/plat_property_contexts" \
! -type d \
diff --git a/tools/dexanalyze/dexanalyze_experiments.cc b/tools/dexanalyze/dexanalyze_experiments.cc
index 82cb0d28ab..0f20a99f05 100644
--- a/tools/dexanalyze/dexanalyze_experiments.cc
+++ b/tools/dexanalyze/dexanalyze_experiments.cc
@@ -130,7 +130,7 @@ void CountDexIndices::ProcessDexFile(const DexFile& dex_file) {
for (ClassAccessor accessor : dex_file.GetClasses()) {
std::set<size_t> unique_method_ids;
std::set<size_t> unique_string_ids;
- accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
dex_code_bytes_ += method.GetInstructions().InsnsSizeInBytes();
unique_code_items.insert(method.GetCodeItemOffset());
for (const DexInstructionPcPair& inst : method.GetInstructions()) {
@@ -188,7 +188,7 @@ void CountDexIndices::ProcessDexFile(const DexFile& dex_file) {
break;
}
}
- });
+ }
total_unique_method_idx_ += unique_method_ids.size();
total_unique_string_ids_ += unique_string_ids.size();
}
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index eebc09278a..0796432f68 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -36,10 +36,9 @@ if [ -z "$ANDROID_HOST_OUT" ] ; then
ANDROID_HOST_OUT=${OUT_DIR-$ANDROID_BUILD_TOP/out}/host/linux-x86
fi
-android_root="/system"
-if [ -n "$ART_TEST_ANDROID_ROOT" ]; then
- android_root="$ART_TEST_ANDROID_ROOT"
-fi
+# "Root" (actually "system") directory on device (in the case of
+# target testing).
+android_root=${ART_TEST_ANDROID_ROOT:-/system}
java_lib_location="${ANDROID_HOST_OUT}/../common/obj/JAVA_LIBRARIES"
make_target_name="apache-harmony-jdwp-tests-hostdex"
@@ -48,6 +47,7 @@ vm_args=""
art="$android_root/bin/art"
art_debugee="sh $android_root/bin/art"
args=$@
+chroot_option=
debuggee_args="-Xcompiler-option --debuggable"
device_dir="--device-dir=/data/local/tmp"
# We use the art script on target to ensure the runner and the debuggee share the same
@@ -68,8 +68,6 @@ test="org.apache.harmony.jpda.tests.share.AllTests"
mode="target"
# Use JIT compiling by default.
use_jit=true
-# Don't use chroot by default.
-use_chroot=false
variant_cmdline_parameter="--variant=X32"
dump_command="/bin/true"
# Timeout of JDWP test in ms.
@@ -112,15 +110,6 @@ while true; do
# We don't care about jit with the RI
use_jit=false
shift
- elif [[ "$1" == "--chroot" ]]; then
- use_chroot=true
- # Adjust settings for chroot environment.
- art="/system/bin/art"
- art_debugee="sh /system/bin/art"
- vm_command="--vm-command=$art"
- device_dir="--device-dir=/tmp"
- # Shift the "--chroot" flag and its argument.
- shift 2
elif [[ $1 == --test-timeout-ms ]]; then
# Remove the --test-timeout-ms from the arguments.
args=${args/$1}
@@ -202,10 +191,17 @@ while true; do
fi
done
-if $use_chroot && [[ $mode == "host" ]]; then
- # Chroot-based testing is not supported on host.
- echo "Cannot use --chroot with --mode=host"
- exit 1
+if [[ $mode == "target" ]]; then
+ # Honor environment variable ART_TEST_CHROOT.
+ if [[ -n "$ART_TEST_CHROOT" ]]; then
+ # Set Vogar's `--chroot` option.
+ chroot_option="--chroot $ART_TEST_CHROOT"
+ # Adjust settings for chroot environment.
+ art="/system/bin/art"
+ art_debugee="sh /system/bin/art"
+ vm_command="--vm-command=$art"
+ device_dir="--device-dir=/tmp"
+ fi
fi
if [[ $has_gdb = "yes" ]]; then
@@ -341,6 +337,7 @@ vogar $vm_command \
$vm_args \
--verbose \
$args \
+ $chroot_option \
$device_dir \
$image_compiler_option \
--timeout 800 \
diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh
index 3537c1b861..aff009abb6 100755
--- a/tools/run-libcore-tests.sh
+++ b/tools/run-libcore-tests.sh
@@ -28,10 +28,9 @@ else
JAVA_LIBRARIES=${ANDROID_PRODUCT_OUT}/../../common/obj/JAVA_LIBRARIES
fi
-android_root="/system"
-if [ -n "$ART_TEST_ANDROID_ROOT" ]; then
- android_root="$ART_TEST_ANDROID_ROOT"
-fi
+# "Root" (actually "system") directory on device (in the case of
+# target testing).
+android_root=${ART_TEST_ANDROID_ROOT:-/system}
function classes_jar_path {
local var="$1"
@@ -106,8 +105,6 @@ debug=false
# Don't use device mode by default.
device_mode=false
-# Don't use chroot by default.
-use_chroot=false
while true; do
if [[ "$1" == "--mode=device" ]]; then
@@ -135,10 +132,6 @@ while true; do
elif [[ "$1" == "-Xgc:gcstress" ]]; then
gcstress=true
shift
- elif [[ "$1" == "--chroot" ]]; then
- use_chroot=true
- # Shift the "--chroot" flag and its argument.
- shift 2
elif [[ "$1" == "" ]]; then
break
else
@@ -147,20 +140,17 @@ while true; do
done
if $device_mode; then
- if $use_chroot; then
+ # Honor environment variable ART_TEST_CHROOT.
+ if [[ -n "$ART_TEST_CHROOT" ]]; then
+ # Set Vogar's `--chroot` option.
+ vogar_args="$vogar_args --chroot $ART_TEST_CHROOT"
vogar_args="$vogar_args --device-dir=/tmp"
- vogar_args="$vogar_args --vm-command=/system/bin/art"
else
+ # When not using a chroot on device, set Vogar's work directory to
+ # /data/local/tmp.
vogar_args="$vogar_args --device-dir=/data/local/tmp"
- vogar_args="$vogar_args --vm-command=$android_root/bin/art"
- fi
-else
- # Host mode.
- if $use_chroot; then
- # Chroot-based testing is not supported on host.
- echo "Cannot use --chroot with --mode=host"
- exit 1
fi
+ vogar_args="$vogar_args --vm-command=$android_root/bin/art"
fi
# Increase the timeout, as vogar cannot set individual test