diff options
108 files changed, 1644 insertions, 1428 deletions
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc index 548b6f8..ef94d8b 100644 --- a/compiler/dex/dex_to_dex_compiler.cc +++ b/compiler/dex/dex_to_dex_compiler.cc @@ -14,13 +14,13 @@ * limitations under the License. */ +#include "art_field-inl.h" #include "base/logging.h" #include "base/mutex.h" #include "dex_file-inl.h" #include "dex_instruction-inl.h" #include "driver/compiler_driver.h" #include "driver/dex_compilation_unit.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/dex_cache.h" diff --git a/compiler/dex/mir_field_info.cc b/compiler/dex/mir_field_info.cc index a9ab3bb..4dfec17 100644 --- a/compiler/dex/mir_field_info.cc +++ b/compiler/dex/mir_field_info.cc @@ -56,7 +56,7 @@ void MirIFieldLoweringInfo::Resolve(CompilerDriver* compiler_driver, // definition) we still want to resolve fields and record all available info. for (auto it = field_infos, end = field_infos + count; it != end; ++it) { uint32_t field_idx; - mirror::ArtField* resolved_field; + ArtField* resolved_field; if (!it->IsQuickened()) { field_idx = it->field_idx_; resolved_field = compiler_driver->ResolveField(soa, dex_cache, class_loader, mUnit, @@ -121,7 +121,7 @@ void MirSFieldLoweringInfo::Resolve(CompilerDriver* compiler_driver, for (auto it = field_infos, end = field_infos + count; it != end; ++it) { uint32_t field_idx = it->field_idx_; - mirror::ArtField* resolved_field = + ArtField* resolved_field = compiler_driver->ResolveField(soa, dex_cache, class_loader, mUnit, field_idx, true); if (UNLIKELY(resolved_field == nullptr)) { continue; diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc index 5b90ba9..ae814b4 100644 --- a/compiler/dex/verified_method.cc +++ b/compiler/dex/verified_method.cc @@ -222,7 +222,7 @@ bool VerifiedMethod::GenerateDequickenMap(verifier::MethodVerifier* method_verif } else if (IsInstructionIGetQuickOrIPutQuick(inst->Opcode())) { uint32_t dex_pc = inst->GetDexPc(insns); verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc); - mirror::ArtField* field = method_verifier->GetQuickFieldAccess(inst, line); + ArtField* field = method_verifier->GetQuickFieldAccess(inst, line); if (field == nullptr) { // It can be null if the line wasn't verified since it was unreachable. return false; diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h index 8babc28..b4d4695 100644 --- a/compiler/driver/compiler_driver-inl.h +++ b/compiler/driver/compiler_driver-inl.h @@ -19,12 +19,11 @@ #include "compiler_driver.h" +#include "art_field-inl.h" #include "dex_compilation_unit.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class_loader.h" #include "mirror/dex_cache-inl.h" -#include "mirror/art_field-inl.h" #include "scoped_thread_state_change.h" #include "handle_scope-inl.h" @@ -65,12 +64,12 @@ inline mirror::Class* CompilerDriver::ResolveCompilingMethodsClass( return ResolveClass(soa, dex_cache, class_loader, referrer_method_id.class_idx_, mUnit); } -inline mirror::ArtField* CompilerDriver::ResolveFieldWithDexFile( +inline ArtField* CompilerDriver::ResolveFieldWithDexFile( const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, const DexFile* dex_file, uint32_t field_idx, bool is_static) { DCHECK_EQ(dex_cache->GetDexFile(), dex_file); - mirror::ArtField* resolved_field = Runtime::Current()->GetClassLinker()->ResolveField( + ArtField* resolved_field = Runtime::Current()->GetClassLinker()->ResolveField( *dex_file, field_idx, dex_cache, class_loader, is_static); DCHECK_EQ(resolved_field == nullptr, soa.Self()->IsExceptionPending()); if (UNLIKELY(resolved_field == nullptr)) { @@ -90,7 +89,7 @@ inline mirror::DexCache* CompilerDriver::FindDexCache(const DexFile* dex_file) { return Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file); } -inline mirror::ArtField* CompilerDriver::ResolveField( +inline ArtField* CompilerDriver::ResolveField( const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, uint32_t field_idx, bool is_static) { @@ -100,7 +99,7 @@ inline mirror::ArtField* CompilerDriver::ResolveField( } inline void CompilerDriver::GetResolvedFieldDexFileLocation( - mirror::ArtField* resolved_field, const DexFile** declaring_dex_file, + ArtField* resolved_field, const DexFile** declaring_dex_file, uint16_t* declaring_class_idx, uint16_t* declaring_field_idx) { mirror::Class* declaring_class = resolved_field->GetDeclaringClass(); *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile(); @@ -108,17 +107,17 @@ inline void CompilerDriver::GetResolvedFieldDexFileLocation( *declaring_field_idx = resolved_field->GetDexFieldIndex(); } -inline bool CompilerDriver::IsFieldVolatile(mirror::ArtField* field) { +inline bool CompilerDriver::IsFieldVolatile(ArtField* field) { return field->IsVolatile(); } -inline MemberOffset CompilerDriver::GetFieldOffset(mirror::ArtField* field) { +inline MemberOffset CompilerDriver::GetFieldOffset(ArtField* field) { return field->GetOffset(); } inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, - mirror::ArtField* resolved_field, uint16_t field_idx) { + ArtField* resolved_field, uint16_t field_idx) { DCHECK(!resolved_field->IsStatic()); mirror::Class* fields_class = resolved_field->GetDeclaringClass(); bool fast_get = referrer_class != nullptr && @@ -130,7 +129,7 @@ inline std::pair<bool, bool> CompilerDriver::IsFastInstanceField( inline std::pair<bool, bool> CompilerDriver::IsFastStaticField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, - mirror::ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) { + ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) { DCHECK(resolved_field->IsStatic()); if (LIKELY(referrer_class != nullptr)) { mirror::Class* fields_class = resolved_field->GetDeclaringClass(); @@ -177,14 +176,14 @@ inline std::pair<bool, bool> CompilerDriver::IsFastStaticField( } inline bool CompilerDriver::IsStaticFieldInReferrerClass(mirror::Class* referrer_class, - mirror::ArtField* resolved_field) { + ArtField* resolved_field) { DCHECK(resolved_field->IsStatic()); mirror::Class* fields_class = resolved_field->GetDeclaringClass(); return referrer_class == fields_class; } inline bool CompilerDriver::IsStaticFieldsClassInitialized(mirror::Class* referrer_class, - mirror::ArtField* resolved_field) { + ArtField* resolved_field) { DCHECK(resolved_field->IsStatic()); mirror::Class* fields_class = resolved_field->GetDeclaringClass(); return fields_class == referrer_class || fields_class->IsInitialized(); diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index f263f6d..6d79248 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -27,6 +27,7 @@ #include <malloc.h> // For mallinfo #endif +#include "art_field-inl.h" #include "base/stl_util.h" #include "base/timing_logger.h" #include "class_linker.h" @@ -48,7 +49,6 @@ #include "gc/accounting/card_table-inl.h" #include "gc/accounting/heap_bitmap.h" #include "gc/space/space.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class_loader.h" #include "mirror/class-inl.h" @@ -1183,7 +1183,7 @@ uint32_t CompilerDriver::GetReferenceDisableFlagOffset() const { DexCacheArraysLayout CompilerDriver::GetDexCacheArraysLayout(const DexFile* dex_file) { // Currently only image dex caches have fixed array layout. return IsImage() && GetSupportBootImageFixup() - ? DexCacheArraysLayout(dex_file) + ? DexCacheArraysLayout(GetInstructionSetPointerSize(instruction_set_), dex_file) : DexCacheArraysLayout(); } @@ -1209,12 +1209,11 @@ void CompilerDriver::ProcessedInvoke(InvokeType invoke_type, int flags) { stats_->ProcessedInvoke(invoke_type, flags); } -mirror::ArtField* CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, - const DexCompilationUnit* mUnit, - bool is_put, - const ScopedObjectAccess& soa) { +ArtField* CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, + const DexCompilationUnit* mUnit, bool is_put, + const ScopedObjectAccess& soa) { // Try to resolve the field and compiling method's class. - mirror::ArtField* resolved_field; + ArtField* resolved_field; mirror::Class* referrer_class; mirror::DexCache* dex_cache; { @@ -1223,11 +1222,10 @@ mirror::ArtField* CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()))); Handle<mirror::ClassLoader> class_loader_handle( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()))); - Handle<mirror::ArtField> resolved_field_handle(hs.NewHandle( - ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, false))); - referrer_class = (resolved_field_handle.Get() != nullptr) + resolved_field = + ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, false); + referrer_class = resolved_field != nullptr ? ResolveCompilingMethodsClass(soa, dex_cache_handle, class_loader_handle, mUnit) : nullptr; - resolved_field = resolved_field_handle.Get(); dex_cache = dex_cache_handle.Get(); } bool can_link = false; @@ -1244,11 +1242,9 @@ bool CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompi bool is_put, MemberOffset* field_offset, bool* is_volatile) { ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<1> hs(soa.Self()); - Handle<mirror::ArtField> resolved_field = - hs.NewHandle(ComputeInstanceFieldInfo(field_idx, mUnit, is_put, soa)); + ArtField* resolved_field = ComputeInstanceFieldInfo(field_idx, mUnit, is_put, soa); - if (resolved_field.Get() == nullptr) { + if (resolved_field == nullptr) { // Conservative defaults. *is_volatile = true; *field_offset = MemberOffset(static_cast<size_t>(-1)); @@ -1267,20 +1263,19 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila Primitive::Type* type) { ScopedObjectAccess soa(Thread::Current()); // Try to resolve the field and compiling method's class. - mirror::ArtField* resolved_field; + ArtField* resolved_field; mirror::Class* referrer_class; mirror::DexCache* dex_cache; { - StackHandleScope<3> hs(soa.Self()); + StackHandleScope<2> hs(soa.Self()); Handle<mirror::DexCache> dex_cache_handle( hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()))); Handle<mirror::ClassLoader> class_loader_handle( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()))); - Handle<mirror::ArtField> resolved_field_handle(hs.NewHandle( - ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, true))); - referrer_class = (resolved_field_handle.Get() != nullptr) + resolved_field = + ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, true); + referrer_class = resolved_field != nullptr ? ResolveCompilingMethodsClass(soa, dex_cache_handle, class_loader_handle, mUnit) : nullptr; - resolved_field = resolved_field_handle.Get(); dex_cache = dex_cache_handle.Get(); } bool result = false; @@ -1728,7 +1723,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag ClassDataItemIterator it(dex_file, class_data); while (it.HasNextStaticField()) { if (resolve_fields_and_methods) { - mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), + ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache, class_loader, true); if (field == nullptr) { CheckAndClearResolveException(soa.Self()); @@ -1743,7 +1738,7 @@ static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manag requires_constructor_barrier = true; } if (resolve_fields_and_methods) { - mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), + ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache, class_loader, false); if (field == nullptr) { CheckAndClearResolveException(soa.Self()); diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index a6ed559..f1066a5 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -239,14 +239,14 @@ class CompilerDriver { // Resolve a field. Returns nullptr on failure, including incompatible class change. // NOTE: Unlike ClassLinker's ResolveField(), this method enforces is_static. - mirror::ArtField* ResolveField( + ArtField* ResolveField( const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit, uint32_t field_idx, bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a field with a given dex file. - mirror::ArtField* ResolveFieldWithDexFile( + ArtField* ResolveFieldWithDexFile( const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, const DexFile* dex_file, uint32_t field_idx, bool is_static) @@ -254,12 +254,12 @@ class CompilerDriver { // Get declaration location of a resolved field. void GetResolvedFieldDexFileLocation( - mirror::ArtField* resolved_field, const DexFile** declaring_dex_file, + ArtField* resolved_field, const DexFile** declaring_dex_file, uint16_t* declaring_class_idx, uint16_t* declaring_field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool IsFieldVolatile(mirror::ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - MemberOffset GetFieldOffset(mirror::ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool IsFieldVolatile(ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + MemberOffset GetFieldOffset(ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Find a dex cache for a dex file. inline mirror::DexCache* FindDexCache(const DexFile* dex_file) @@ -268,23 +268,23 @@ class CompilerDriver { // Can we fast-path an IGET/IPUT access to an instance field? If yes, compute the field offset. std::pair<bool, bool> IsFastInstanceField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, - mirror::ArtField* resolved_field, uint16_t field_idx) + ArtField* resolved_field, uint16_t field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Can we fast-path an SGET/SPUT access to a static field? If yes, compute the type index // of the declaring class in the referrer's dex file. std::pair<bool, bool> IsFastStaticField( mirror::DexCache* dex_cache, mirror::Class* referrer_class, - mirror::ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) + ArtField* resolved_field, uint16_t field_idx, uint32_t* storage_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Is static field's in referrer's class? - bool IsStaticFieldInReferrerClass(mirror::Class* referrer_class, mirror::ArtField* resolved_field) + bool IsStaticFieldInReferrerClass(mirror::Class* referrer_class, ArtField* resolved_field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Is static field's class initialized? bool IsStaticFieldsClassInitialized(mirror::Class* referrer_class, - mirror::ArtField* resolved_field) + ArtField* resolved_field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a method. Returns nullptr on failure, including incompatible class change. @@ -331,7 +331,7 @@ class CompilerDriver { void ComputeFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, const ScopedObjectAccess& soa, bool is_static, - mirror::ArtField** resolved_field, + ArtField** resolved_field, mirror::Class** referrer_class, mirror::DexCache** dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -341,7 +341,7 @@ class CompilerDriver { MemberOffset* field_offset, bool* is_volatile) LOCKS_EXCLUDED(Locks::mutator_lock_); - mirror::ArtField* ComputeInstanceFieldInfo(uint32_t field_idx, + ArtField* ComputeInstanceFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, bool is_put, const ScopedObjectAccess& soa) diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc index 5ebc029..7200cda 100644 --- a/compiler/driver/compiler_driver_test.cc +++ b/compiler/driver/compiler_driver_test.cc @@ -132,7 +132,7 @@ TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) { } EXPECT_EQ(dex.NumFieldIds(), dex_cache->NumResolvedFields()); for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { - mirror::ArtField* field = dex_cache->GetResolvedField(i); + ArtField* field = Runtime::Current()->GetClassLinker()->GetResolvedField(i, dex_cache); EXPECT_TRUE(field != NULL) << "field_idx=" << i << " " << dex.GetFieldDeclaringClassDescriptor(dex.GetFieldId(i)) << " " << dex.GetFieldName(dex.GetFieldId(i)); diff --git a/compiler/image_test.cc b/compiler/image_test.cc index cf97943..627a42e 100644 --- a/compiler/image_test.cc +++ b/compiler/image_test.cc @@ -205,6 +205,7 @@ TEST_F(ImageTest, ImageHeaderIsValid) { uint32_t oat_file_end = ART_BASE_ADDRESS + (10 * KB); ImageHeader image_header(image_begin, image_size_, + 0u, 0u, image_bitmap_offset, image_bitmap_size, image_roots, diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 1ede228..6f8884a 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -22,6 +22,7 @@ #include <numeric> #include <vector> +#include "art_field-inl.h" #include "base/logging.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" @@ -40,8 +41,8 @@ #include "globals.h" #include "image.h" #include "intern_table.h" +#include "linear_alloc.h" #include "lock_word.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/array-inl.h" #include "mirror/class-inl.h" @@ -57,7 +58,6 @@ #include "handle_scope-inl.h" #include "utils/dex_cache_arrays_layout-inl.h" -using ::art::mirror::ArtField; using ::art::mirror::ArtMethod; using ::art::mirror::Class; using ::art::mirror::DexCache; @@ -164,6 +164,9 @@ bool ImageWriter::Write(const std::string& image_filename, Thread::Current()->TransitionFromSuspendedToRunnable(); CreateHeader(oat_loaded_size, oat_data_offset); + // TODO: heap validation can't handle these fix up passes. + Runtime::Current()->GetHeap()->DisableObjectValidation(); + CopyAndFixupNativeData(); CopyAndFixupObjects(); Thread::Current()->TransitionFromRunnableToSuspended(kNative); @@ -186,9 +189,10 @@ bool ImageWriter::Write(const std::string& image_filename, return EXIT_FAILURE; } - // Write out the image. + // Write out the image + fields. + const auto write_count = image_header->GetImageSize() + image_header->GetArtFieldsSize(); CHECK_EQ(image_end_, image_header->GetImageSize()); - if (!image_file->WriteFully(image_->Begin(), image_end_)) { + if (!image_file->WriteFully(image_->Begin(), write_count)) { PLOG(ERROR) << "Failed to write image file " << image_filename; image_file->Erase(); return false; @@ -204,6 +208,8 @@ bool ImageWriter::Write(const std::string& image_filename, return false; } + CHECK_EQ(image_header->GetImageBitmapOffset() + image_header->GetImageBitmapSize(), + static_cast<size_t>(image_file->GetLength())); if (image_file->FlushCloseOrErase() != 0) { PLOG(ERROR) << "Failed to flush and close image file " << image_filename; return false; @@ -219,6 +225,8 @@ void ImageWriter::SetImageOffset(mirror::Object* object, mirror::Object* obj = reinterpret_cast<mirror::Object*>(image_->Begin() + offset); DCHECK_ALIGNED(obj, kObjectAlignment); + static size_t max_offset = 0; + max_offset = std::max(max_offset, offset); image_bitmap_->Set(obj); // Mark the obj as mutated, since we will end up changing it. { // Remember the object-inside-of-the-image's hash code so we can restore it after the copy. @@ -302,13 +310,26 @@ void ImageWriter::PrepareDexCacheArraySlots() { DexCache* dex_cache = class_linker->GetDexCache(idx); const DexFile* dex_file = dex_cache->GetDexFile(); dex_cache_array_starts_.Put(dex_file, size); - DexCacheArraysLayout layout(dex_file); + DexCacheArraysLayout layout(target_ptr_size_, dex_file); DCHECK(layout.Valid()); - dex_cache_array_indexes_.Put(dex_cache->GetResolvedTypes(), size + layout.TypesOffset()); - dex_cache_array_indexes_.Put(dex_cache->GetResolvedMethods(), size + layout.MethodsOffset()); - dex_cache_array_indexes_.Put(dex_cache->GetResolvedFields(), size + layout.FieldsOffset()); - dex_cache_array_indexes_.Put(dex_cache->GetStrings(), size + layout.StringsOffset()); + auto types_size = layout.TypesSize(dex_file->NumTypeIds()); + auto methods_size = layout.MethodsSize(dex_file->NumMethodIds()); + auto fields_size = layout.FieldsSize(dex_file->NumFieldIds()); + auto strings_size = layout.StringsSize(dex_file->NumStringIds()); + dex_cache_array_indexes_.Put( + dex_cache->GetResolvedTypes(), + DexCacheArrayLocation {size + layout.TypesOffset(), types_size}); + dex_cache_array_indexes_.Put( + dex_cache->GetResolvedMethods(), + DexCacheArrayLocation {size + layout.MethodsOffset(), methods_size}); + dex_cache_array_indexes_.Put( + dex_cache->GetResolvedFields(), + DexCacheArrayLocation {size + layout.FieldsOffset(), fields_size}); + dex_cache_array_indexes_.Put( + dex_cache->GetStrings(), + DexCacheArrayLocation {size + layout.StringsOffset(), strings_size}); size += layout.Size(); + CHECK_EQ(layout.Size(), types_size + methods_size + fields_size + strings_size); } // Set the slot size early to avoid DCHECK() failures in IsImageBinSlotAssigned() // when AssignImageBinSlot() assigns their indexes out or order. @@ -405,12 +426,20 @@ void ImageWriter::AssignImageBinSlot(mirror::Object* object) { } } else if (object->GetClass<kVerifyNone>()->IsStringClass()) { bin = kBinString; // Strings are almost always immutable (except for object header). - } else if (object->IsObjectArray()) { - auto it = dex_cache_array_indexes_.find(object); - if (it != dex_cache_array_indexes_.end()) { - bin = kBinDexCacheArray; - current_offset = it->second; // Use prepared offset defined by the DexCacheLayout. - } // else bin = kBinRegular + } else if (object->IsArrayInstance()) { + mirror::Class* klass = object->GetClass<kVerifyNone>(); + auto* component_type = klass->GetComponentType(); + if (!component_type->IsPrimitive() || component_type->IsPrimitiveInt() || + component_type->IsPrimitiveLong()) { + auto it = dex_cache_array_indexes_.find(object); + if (it != dex_cache_array_indexes_.end()) { + bin = kBinDexCacheArray; + // Use prepared offset defined by the DexCacheLayout. + current_offset = it->second.offset_; + // Override incase of cross compilation. + object_size = it->second.length_; + } // else bin = kBinRegular + } } // else bin = kBinRegular } @@ -465,7 +494,10 @@ ImageWriter::BinSlot ImageWriter::GetImageBinSlot(mirror::Object* object) const } bool ImageWriter::AllocMemory() { - size_t length = RoundUp(Runtime::Current()->GetHeap()->GetTotalMemory(), kPageSize); + auto* runtime = Runtime::Current(); + const size_t heap_size = runtime->GetHeap()->GetTotalMemory(); + // Add linear alloc usage since we need to have room for the ArtFields. + const size_t length = RoundUp(heap_size + runtime->GetLinearAlloc()->GetUsedMemory(), kPageSize); std::string error_msg; image_.reset(MemMap::MapAnonymous("image writer image", nullptr, length, PROT_READ | PROT_WRITE, false, false, &error_msg)); @@ -476,7 +508,7 @@ bool ImageWriter::AllocMemory() { // Create the image bitmap. image_bitmap_.reset(gc::accounting::ContinuousSpaceBitmap::Create("image bitmap", image_->Begin(), - length)); + RoundUp(length, kPageSize))); if (image_bitmap_.get() == nullptr) { LOG(ERROR) << "Failed to allocate memory for image bitmap"; return false; @@ -698,9 +730,9 @@ void ImageWriter::PruneNonImageClasses() { } } for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { - ArtField* field = dex_cache->GetResolvedField(i); - if (field != NULL && !IsImageClass(field->GetDeclaringClass())) { - dex_cache->SetResolvedField(i, NULL); + ArtField* field = dex_cache->GetResolvedField(i, sizeof(void*)); + if (field != nullptr && !IsImageClass(field->GetDeclaringClass())) { + dex_cache->SetResolvedField(i, nullptr, sizeof(void*)); } } // Clean the dex field. It might have been populated during the initialization phase, but @@ -786,7 +818,7 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { // caches. We check that the number of dex caches does not change. size_t dex_cache_count; { - ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock()); + ReaderMutexLock mu(self, *class_linker->DexLock()); dex_cache_count = class_linker->GetDexCacheCount(); } Handle<ObjectArray<Object>> dex_caches( @@ -794,7 +826,7 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { dex_cache_count))); CHECK(dex_caches.Get() != nullptr) << "Failed to allocate a dex cache array."; { - ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock()); + ReaderMutexLock mu(self, *class_linker->DexLock()); CHECK_EQ(dex_cache_count, class_linker->GetDexCacheCount()) << "The number of dex caches changed."; for (size_t i = 0; i < dex_cache_count; ++i) { @@ -861,9 +893,9 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { WalkInstanceFields(h_obj.Get(), klass.Get()); // Walk static fields of a Class. if (h_obj->IsClass()) { - size_t num_static_fields = klass->NumReferenceStaticFields(); + size_t num_reference_static_fields = klass->NumReferenceStaticFields(); MemberOffset field_offset = klass->GetFirstReferenceStaticFieldOffset(); - for (size_t i = 0; i < num_static_fields; ++i) { + for (size_t i = 0; i < num_reference_static_fields; ++i) { mirror::Object* value = h_obj->GetFieldObject<mirror::Object>(field_offset); if (value != nullptr) { WalkFieldsInOrder(value); @@ -871,6 +903,21 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { field_offset = MemberOffset(field_offset.Uint32Value() + sizeof(mirror::HeapReference<mirror::Object>)); } + + // Visit and assign offsets for fields. + ArtField* fields[2] = { h_obj->AsClass()->GetSFields(), h_obj->AsClass()->GetIFields() }; + size_t num_fields[2] = { h_obj->AsClass()->NumStaticFields(), + h_obj->AsClass()->NumInstanceFields() }; + for (size_t i = 0; i < 2; ++i) { + for (size_t j = 0; j < num_fields[i]; ++j) { + auto* field = fields[i] + j; + auto it = art_field_reloc_.find(field); + CHECK(it == art_field_reloc_.end()) << "Field at index " << i << ":" << j + << " already assigned " << PrettyField(field); + art_field_reloc_.emplace(field, bin_slot_sizes_[kBinArtField]); + bin_slot_sizes_[kBinArtField] += sizeof(ArtField); + } + } } else if (h_obj->IsObjectArray()) { // Walk elements of an object array. int32_t length = h_obj->AsObjectArray<mirror::Object>()->GetLength(); @@ -921,7 +968,6 @@ void ImageWriter::CalculateNewObjectOffsets() { // know where image_roots is going to end up image_end_ += RoundUp(sizeof(ImageHeader), kObjectAlignment); // 64-bit-alignment - // TODO: Image spaces only? DCHECK_LT(image_end_, image_->Size()); image_objects_offset_begin_ = image_end_; // Prepare bin slots for dex cache arrays. @@ -935,34 +981,47 @@ void ImageWriter::CalculateNewObjectOffsets() { previous_sizes += bin_slot_sizes_[i]; } DCHECK_EQ(previous_sizes, GetBinSizeSum()); + DCHECK_EQ(image_end_, GetBinSizeSum(kBinMirrorCount) + image_objects_offset_begin_); + // Transform each object's bin slot into an offset which will be used to do the final copy. heap->VisitObjects(UnbinObjectsIntoOffsetCallback, this); DCHECK(saved_hashes_map_.empty()); // All binslot hashes should've been put into vector by now. - DCHECK_GT(image_end_, GetBinSizeSum()); + DCHECK_EQ(image_end_, GetBinSizeSum(kBinMirrorCount) + image_objects_offset_begin_); image_roots_address_ = PointerToLowMemUInt32(GetImageAddress(image_roots.Get())); - // Note that image_end_ is left at end of used space + // Note that image_end_ is left at end of used mirror space } void ImageWriter::CreateHeader(size_t oat_loaded_size, size_t oat_data_offset) { CHECK_NE(0U, oat_loaded_size); const uint8_t* oat_file_begin = GetOatFileBegin(); const uint8_t* oat_file_end = oat_file_begin + oat_loaded_size; - oat_data_begin_ = oat_file_begin + oat_data_offset; const uint8_t* oat_data_end = oat_data_begin_ + oat_file_->Size(); - + // Write out sections. + size_t cur_pos = image_end_; + // Add fields. + auto fields_offset = cur_pos; + CHECK_EQ(image_objects_offset_begin_ + GetBinSizeSum(kBinArtField), fields_offset); + auto fields_size = bin_slot_sizes_[kBinArtField]; + cur_pos += fields_size; // Return to write header at start of image with future location of image_roots. At this point, - // image_end_ is the size of the image (excluding bitmaps). + // image_end_ is the size of the image (excluding bitmaps, ArtFields). + /* const size_t heap_bytes_per_bitmap_byte = kBitsPerByte * kObjectAlignment; const size_t bitmap_bytes = RoundUp(image_end_, heap_bytes_per_bitmap_byte) / heap_bytes_per_bitmap_byte; + */ + const size_t bitmap_bytes = image_bitmap_->Size(); + auto bitmap_offset = RoundUp(cur_pos, kPageSize); + auto bitmap_size = RoundUp(bitmap_bytes, kPageSize); + cur_pos += bitmap_size; new (image_->Begin()) ImageHeader(PointerToLowMemUInt32(image_begin_), static_cast<uint32_t>(image_end_), - RoundUp(image_end_, kPageSize), - RoundUp(bitmap_bytes, kPageSize), + fields_offset, fields_size, + bitmap_offset, bitmap_size, image_roots_address_, oat_file_->GetOatHeader().GetChecksum(), PointerToLowMemUInt32(oat_file_begin), @@ -972,11 +1031,21 @@ void ImageWriter::CreateHeader(size_t oat_loaded_size, size_t oat_data_offset) { compile_pic_); } +void ImageWriter::CopyAndFixupNativeData() { + // Copy ArtFields to their locations and update the array for convenience. + auto fields_offset = image_objects_offset_begin_ + GetBinSizeSum(kBinArtField); + for (auto& pair : art_field_reloc_) { + pair.second += fields_offset; + auto* dest = image_->Begin() + pair.second; + DCHECK_GE(dest, image_->Begin() + image_end_); + memcpy(dest, pair.first, sizeof(ArtField)); + reinterpret_cast<ArtField*>(dest)->SetDeclaringClass( + down_cast<Class*>(GetImageAddress(pair.first->GetDeclaringClass()))); + } +} + void ImageWriter::CopyAndFixupObjects() { gc::Heap* heap = Runtime::Current()->GetHeap(); - // TODO: heap validation can't handle this fix up pass - heap->DisableObjectValidation(); - // TODO: Image spaces only? heap->VisitObjects(CopyAndFixupObjectsCallback, this); // Fix up the object previously had hash codes. for (const std::pair<mirror::Object*, uint32_t>& hash_pair : saved_hashes_) { @@ -990,26 +1059,88 @@ void ImageWriter::CopyAndFixupObjects() { void ImageWriter::CopyAndFixupObjectsCallback(Object* obj, void* arg) { DCHECK(obj != nullptr); DCHECK(arg != nullptr); - ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); + reinterpret_cast<ImageWriter*>(arg)->CopyAndFixupObject(obj); +} + +bool ImageWriter::CopyAndFixupIfDexCacheFieldArray(mirror::Object* dst, mirror::Object* obj, + mirror::Class* klass) { + if (!klass->IsArrayClass()) { + return false; + } + auto* component_type = klass->GetComponentType(); + bool is_int_arr = component_type->IsPrimitiveInt(); + bool is_long_arr = component_type->IsPrimitiveLong(); + if (!is_int_arr && !is_long_arr) { + return false; + } + auto it = dex_cache_array_indexes_.find(obj); // Is this a dex cache array? + if (it == dex_cache_array_indexes_.end()) { + return false; + } + mirror::Array* arr = obj->AsArray(); + CHECK_EQ(reinterpret_cast<Object*>( + image_->Begin() + it->second.offset_ + image_objects_offset_begin_), dst); + dex_cache_array_indexes_.erase(it); + // Fixup int pointers for the field array. + CHECK(!arr->IsObjectArray()); + const size_t num_elements = arr->GetLength(); + if (target_ptr_size_ == 4) { + // Will get fixed up by fixup object. + dst->SetClass(down_cast<mirror::Class*>( + GetImageAddress(mirror::IntArray::GetArrayClass()))); + } else { + DCHECK_EQ(target_ptr_size_, 8u); + dst->SetClass(down_cast<mirror::Class*>( + GetImageAddress(mirror::LongArray::GetArrayClass()))); + } + mirror::Array* dest_array = down_cast<mirror::Array*>(dst); + dest_array->SetLength(num_elements); + for (size_t i = 0, count = num_elements; i < count; ++i) { + ArtField* field = reinterpret_cast<ArtField*>(is_int_arr ? + arr->AsIntArray()->GetWithoutChecks(i) : arr->AsLongArray()->GetWithoutChecks(i)); + uint8_t* fixup_location = nullptr; + if (field != nullptr) { + auto it2 = art_field_reloc_.find(field); + CHECK(it2 != art_field_reloc_.end()) << "No relocation for field " << PrettyField(field); + fixup_location = image_begin_ + it2->second; + } + if (target_ptr_size_ == 4) { + down_cast<mirror::IntArray*>(dest_array)->SetWithoutChecks<kVerifyNone>( + i, static_cast<uint32_t>(reinterpret_cast<uint64_t>(fixup_location))); + } else { + down_cast<mirror::LongArray*>(dest_array)->SetWithoutChecks<kVerifyNone>( + i, reinterpret_cast<uint64_t>(fixup_location)); + } + } + dst->SetLockWord(LockWord::Default(), false); + return true; +} + +void ImageWriter::CopyAndFixupObject(Object* obj) { // see GetLocalAddress for similar computation - size_t offset = image_writer->GetImageOffset(obj); - uint8_t* dst = image_writer->image_->Begin() + offset; + size_t offset = GetImageOffset(obj); + auto* dst = reinterpret_cast<Object*>(image_->Begin() + offset); const uint8_t* src = reinterpret_cast<const uint8_t*>(obj); size_t n; - if (obj->IsArtMethod()) { + mirror::Class* klass = obj->GetClass(); + + if (CopyAndFixupIfDexCacheFieldArray(dst, obj, klass)) { + return; + } + if (klass->IsArtMethodClass()) { // Size without pointer fields since we don't want to overrun the buffer if target art method // is 32 bits but source is 64 bits. - n = mirror::ArtMethod::SizeWithoutPointerFields(image_writer->target_ptr_size_); + n = mirror::ArtMethod::SizeWithoutPointerFields(target_ptr_size_); } else { n = obj->SizeOf(); } - DCHECK_LT(offset + n, image_writer->image_->Size()); + DCHECK_LE(offset + n, image_->Size()); memcpy(dst, src, n); - Object* copy = reinterpret_cast<Object*>(dst); + // Write in a hash code of objects which have inflated monitors or a hash code in their monitor // word. - copy->SetLockWord(LockWord::Default(), false); - image_writer->FixupObject(obj, copy); + dst->SetLockWord(LockWord::Default(), false); + FixupObject(obj, dst); } // Rewrite all the references in the copied object to point to their image address equivalent @@ -1045,15 +1176,10 @@ class FixupClassVisitor FINAL : public FixupVisitor { FixupClassVisitor(ImageWriter* image_writer, Object* copy) : FixupVisitor(image_writer, copy) { } - void operator()(Object* obj, MemberOffset offset, bool /*is_static*/) const + void operator()(Object* obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) { DCHECK(obj->IsClass()); FixupVisitor::operator()(obj, offset, /*is_static*/false); - - // TODO: Remove dead code - if (offset.Uint32Value() < mirror::Class::EmbeddedVTableOffset().Uint32Value()) { - return; - } } void operator()(mirror::Class* klass ATTRIBUTE_UNUSED, @@ -1064,6 +1190,31 @@ class FixupClassVisitor FINAL : public FixupVisitor { } }; +void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) { + // Copy and fix up ArtFields in the class. + ArtField* fields[2] = { orig->AsClass()->GetSFields(), orig->AsClass()->GetIFields() }; + size_t num_fields[2] = { orig->AsClass()->NumStaticFields(), + orig->AsClass()->NumInstanceFields() }; + // Update the arrays. + for (size_t i = 0; i < 2; ++i) { + if (num_fields[i] == 0) { + CHECK(fields[i] == nullptr); + continue; + } + auto it = art_field_reloc_.find(fields[i]); + CHECK(it != art_field_reloc_.end()) << PrettyClass(orig->AsClass()) << " : " + << PrettyField(fields[i]); + auto* image_fields = reinterpret_cast<ArtField*>(image_begin_ + it->second); + if (i == 0) { + down_cast<Class*>(copy)->SetSFieldsUnchecked(image_fields); + } else { + down_cast<Class*>(copy)->SetIFieldsUnchecked(image_fields); + } + } + FixupClassVisitor visitor(this, copy); + static_cast<mirror::Object*>(orig)->VisitReferences<true /*visit class*/>(visitor, visitor); +} + void ImageWriter::FixupObject(Object* orig, Object* copy) { DCHECK(orig != nullptr); DCHECK(copy != nullptr); @@ -1075,9 +1226,8 @@ void ImageWriter::FixupObject(Object* orig, Object* copy) { DCHECK_EQ(copy->GetReadBarrierPointer(), GetImageAddress(orig)); } } - if (orig->IsClass() && orig->AsClass()->ShouldHaveEmbeddedImtAndVTable()) { - FixupClassVisitor visitor(this, copy); - orig->VisitReferences<true /*visit class*/>(visitor, visitor); + if (orig->IsClass()) { + FixupClass(orig->AsClass<kVerifyNone>(), down_cast<mirror::Class*>(copy)); } else { FixupVisitor visitor(this, copy); orig->VisitReferences<true /*visit class*/>(visitor, visitor); diff --git a/compiler/image_writer.h b/compiler/image_writer.h index 71044f7..a2d99ee 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -90,7 +90,7 @@ class ImageWriter FINAL { } uint8_t* GetOatFileBegin() const { - return image_begin_ + RoundUp(image_end_, kPageSize); + return image_begin_ + RoundUp(image_end_ + bin_slot_sizes_[kBinArtField], kPageSize); } bool Write(const std::string& image_filename, @@ -127,12 +127,16 @@ class ImageWriter FINAL { kBinArtMethodNative, // Art method that is actually native kBinArtMethodNotInitialized, // Art method with a declaring class that wasn't initialized // Add more bins here if we add more segregation code. + // Non mirror fields must be below. ArtFields should be always clean. + kBinArtField, kBinSize, + // Number of bins which are for mirror objects. + kBinMirrorCount = kBinArtField, }; friend std::ostream& operator<<(std::ostream& stream, const Bin& bin); - static constexpr size_t kBinBits = MinimumBitsToStore(kBinSize - 1); + static constexpr size_t kBinBits = MinimumBitsToStore(kBinMirrorCount - 1); // uint32 = typeof(lockword_) static constexpr size_t kBinShift = BitSizeOf<uint32_t>() - kBinBits; // 111000.....0 @@ -251,11 +255,18 @@ class ImageWriter FINAL { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Creates the contiguous image in memory and adjusts pointers. + void CopyAndFixupNativeData() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void CopyAndFixupObjects() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void CopyAndFixupObjectsCallback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void CopyAndFixupObject(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool CopyAndFixupIfDexCacheFieldArray(mirror::Object* dst, mirror::Object* obj, + mirror::Class* klass) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void FixupMethod(mirror::ArtMethod* orig, mirror::ArtMethod* copy) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void FixupClass(mirror::Class* orig, mirror::Class* copy) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void FixupObject(mirror::Object* orig, mirror::Object* copy) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -295,8 +306,13 @@ class ImageWriter FINAL { // Memory mapped for generating the image. std::unique_ptr<MemMap> image_; - // Indexes for dex cache arrays (objects are inside of the image so that they don't move). - SafeMap<mirror::Object*, size_t> dex_cache_array_indexes_; + // Indexes, lengths for dex cache arrays (objects are inside of the image so that they don't + // move). + struct DexCacheArrayLocation { + size_t offset_; + size_t length_; + }; + SafeMap<mirror::Object*, DexCacheArrayLocation> dex_cache_array_indexes_; // The start offsets of the dex cache arrays. SafeMap<const DexFile*, size_t> dex_cache_array_starts_; @@ -331,6 +347,11 @@ class ImageWriter FINAL { size_t bin_slot_previous_sizes_[kBinSize]; // Number of bytes in previous bins. size_t bin_slot_count_[kBinSize]; // Number of objects in a bin + // ArtField relocating map, ArtFields are allocated as array of structs but we want to have one + // entry per art field for convenience. + // ArtFields are placed right after the end of the image objects (aka sum of bin_slot_sizes_). + std::unordered_map<ArtField*, uintptr_t> art_field_reloc_; + void* string_data_array_; // The backing for the interned strings. friend class FixupVisitor; diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index a912d4c..8a64d81 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -16,16 +16,13 @@ #include "builder.h" +#include "art_field-inl.h" #include "base/logging.h" #include "class_linker.h" -#include "dex_file.h" #include "dex_file-inl.h" -#include "dex_instruction.h" #include "dex_instruction-inl.h" #include "driver/compiler_driver-inl.h" #include "driver/compiler_options.h" -#include "mirror/art_field.h" -#include "mirror/art_field-inl.h" #include "mirror/class_loader.h" #include "mirror/dex_cache.h" #include "nodes.h" @@ -656,11 +653,10 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, uint16_t field_index = instruction.VRegC_22c(); ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<1> hs(soa.Self()); - Handle<mirror::ArtField> resolved_field(hs.NewHandle( - compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa))); + ArtField* resolved_field = + compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa); - if (resolved_field.Get() == nullptr) { + if (resolved_field == nullptr) { MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField); return false; } @@ -728,15 +724,15 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, uint16_t field_index = instruction.VRegB_21c(); ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<5> hs(soa.Self()); + StackHandleScope<4> hs(soa.Self()); Handle<mirror::DexCache> dex_cache(hs.NewHandle( dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile()))); Handle<mirror::ClassLoader> class_loader(hs.NewHandle( soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader()))); - Handle<mirror::ArtField> resolved_field(hs.NewHandle(compiler_driver_->ResolveField( - soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true))); + ArtField* resolved_field = compiler_driver_->ResolveField( + soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true); - if (resolved_field.Get() == nullptr) { + if (resolved_field == nullptr) { MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField); return false; } @@ -758,7 +754,7 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, std::pair<bool, bool> pair = compiler_driver_->IsFastStaticField( outer_dex_cache.Get(), referrer_class.Get(), - resolved_field.Get(), + resolved_field, field_index, &storage_index); bool can_easily_access = is_put ? pair.second : pair.first; diff --git a/compiler/utils/dex_cache_arrays_layout-inl.h b/compiler/utils/dex_cache_arrays_layout-inl.h index 7d02ce3..2c50c96 100644 --- a/compiler/utils/dex_cache_arrays_layout-inl.h +++ b/compiler/utils/dex_cache_arrays_layout-inl.h @@ -26,7 +26,6 @@ #include "utils.h" namespace mirror { -class ArtField; class ArtMethod; class Class; class String; @@ -34,40 +33,55 @@ class String; namespace art { -inline DexCacheArraysLayout::DexCacheArraysLayout(const DexFile* dex_file) +inline DexCacheArraysLayout::DexCacheArraysLayout(size_t pointer_size, const DexFile* dex_file) : /* types_offset_ is always 0u */ - methods_offset_(types_offset_ + ArraySize<mirror::Class>(dex_file->NumTypeIds())), - strings_offset_(methods_offset_ + ArraySize<mirror::ArtMethod>(dex_file->NumMethodIds())), - fields_offset_(strings_offset_ + ArraySize<mirror::String>(dex_file->NumStringIds())), - size_(fields_offset_ + ArraySize<mirror::ArtField>(dex_file->NumFieldIds())) { + pointer_size_(pointer_size), + methods_offset_(types_offset_ + TypesSize(dex_file->NumTypeIds())), + strings_offset_(methods_offset_ + MethodsSize(dex_file->NumMethodIds())), + fields_offset_(strings_offset_ + StringsSize(dex_file->NumStringIds())), + size_(fields_offset_ + FieldsSize(dex_file->NumFieldIds())) { + DCHECK(pointer_size == 4u || pointer_size == 8u); } inline size_t DexCacheArraysLayout::TypeOffset(uint32_t type_idx) const { - return types_offset_ + ElementOffset<mirror::Class>(type_idx); + return types_offset_ + ElementOffset(sizeof(mirror::HeapReference<mirror::Class>), type_idx); +} + +inline size_t DexCacheArraysLayout::TypesSize(size_t num_elements) const { + return ArraySize(sizeof(mirror::HeapReference<mirror::Class>), num_elements); } inline size_t DexCacheArraysLayout::MethodOffset(uint32_t method_idx) const { - return methods_offset_ + ElementOffset<mirror::ArtMethod>(method_idx); + return methods_offset_ + ElementOffset( + sizeof(mirror::HeapReference<mirror::ArtMethod>), method_idx); +} + +inline size_t DexCacheArraysLayout::MethodsSize(size_t num_elements) const { + return ArraySize(sizeof(mirror::HeapReference<mirror::ArtMethod>), num_elements); } inline size_t DexCacheArraysLayout::StringOffset(uint32_t string_idx) const { - return strings_offset_ + ElementOffset<mirror::String>(string_idx); + return strings_offset_ + ElementOffset(sizeof(mirror::HeapReference<mirror::String>), string_idx); +} + +inline size_t DexCacheArraysLayout::StringsSize(size_t num_elements) const { + return ArraySize(sizeof(mirror::HeapReference<mirror::String>), num_elements); } inline size_t DexCacheArraysLayout::FieldOffset(uint32_t field_idx) const { - return fields_offset_ + ElementOffset<mirror::ArtField>(field_idx); + return fields_offset_ + ElementOffset(pointer_size_, field_idx); +} + +inline size_t DexCacheArraysLayout::FieldsSize(size_t num_elements) const { + return ArraySize(pointer_size_, num_elements); } -template <typename MirrorType> -inline size_t DexCacheArraysLayout::ElementOffset(uint32_t idx) { - return mirror::Array::DataOffset(sizeof(mirror::HeapReference<MirrorType>)).Uint32Value() + - sizeof(mirror::HeapReference<MirrorType>) * idx; +inline size_t DexCacheArraysLayout::ElementOffset(size_t element_size, uint32_t idx) { + return mirror::Array::DataOffset(element_size).Uint32Value() + element_size * idx; } -template <typename MirrorType> -inline size_t DexCacheArraysLayout::ArraySize(uint32_t num_elements) { - size_t array_size = mirror::ComputeArraySize( - num_elements, ComponentSizeShiftWidth<sizeof(mirror::HeapReference<MirrorType>)>()); +inline size_t DexCacheArraysLayout::ArraySize(size_t element_size, uint32_t num_elements) { + size_t array_size = mirror::ComputeArraySize(num_elements, ComponentSizeShiftWidth(element_size)); DCHECK_NE(array_size, 0u); // No overflow expected for dex cache arrays. return RoundUp(array_size, kObjectAlignment); } diff --git a/compiler/utils/dex_cache_arrays_layout.h b/compiler/utils/dex_cache_arrays_layout.h index b461256..8f98ea1 100644 --- a/compiler/utils/dex_cache_arrays_layout.h +++ b/compiler/utils/dex_cache_arrays_layout.h @@ -29,6 +29,7 @@ class DexCacheArraysLayout { // Construct an invalid layout. DexCacheArraysLayout() : /* types_offset_ is always 0u */ + pointer_size_(0u), methods_offset_(0u), strings_offset_(0u), fields_offset_(0u), @@ -36,7 +37,7 @@ class DexCacheArraysLayout { } // Construct a layout for a particular dex file. - explicit DexCacheArraysLayout(const DexFile* dex_file); + explicit DexCacheArraysLayout(size_t pointer_size, const DexFile* dex_file); bool Valid() const { return Size() != 0u; @@ -52,36 +53,43 @@ class DexCacheArraysLayout { size_t TypeOffset(uint32_t type_idx) const; + size_t TypesSize(size_t num_elements) const; + size_t MethodsOffset() const { return methods_offset_; } size_t MethodOffset(uint32_t method_idx) const; + size_t MethodsSize(size_t num_elements) const; + size_t StringsOffset() const { return strings_offset_; } size_t StringOffset(uint32_t string_idx) const; + size_t StringsSize(size_t num_elements) const; + size_t FieldsOffset() const { return fields_offset_; } size_t FieldOffset(uint32_t field_idx) const; + size_t FieldsSize(size_t num_elements) const; + private: static constexpr size_t types_offset_ = 0u; + const size_t pointer_size_; // Must be first for construction initialization order. const size_t methods_offset_; const size_t strings_offset_; const size_t fields_offset_; const size_t size_; - template <typename MirrorType> - static size_t ElementOffset(uint32_t idx); + static size_t ElementOffset(size_t element_size, uint32_t idx); - template <typename MirrorType> - static size_t ArraySize(uint32_t num_elements); + static size_t ArraySize(size_t element_size, uint32_t num_elements); }; } // namespace art diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc index 9b57ecb..34a4c14 100644 --- a/imgdiag/imgdiag.cc +++ b/imgdiag/imgdiag.cc @@ -168,7 +168,10 @@ class ImgDiagDumper { << "\n\n"; const uint8_t* image_begin_unaligned = boot_image_header.GetImageBegin(); - const uint8_t* image_end_unaligned = image_begin_unaligned + boot_image_header.GetImageSize(); + const uint8_t* image_mirror_end_unaligned = image_begin_unaligned + + boot_image_header.GetImageSize(); + const uint8_t* image_end_unaligned = image_mirror_end_unaligned + + boot_image_header.GetArtFieldsSize(); // Adjust range to nearest page const uint8_t* image_begin = AlignDown(image_begin_unaligned, kPageSize); @@ -350,7 +353,7 @@ class ImgDiagDumper { size_t dirty_object_bytes = 0; { const uint8_t* begin_image_ptr = image_begin_unaligned; - const uint8_t* end_image_ptr = image_end_unaligned; + const uint8_t* end_image_ptr = image_mirror_end_unaligned; const uint8_t* current = begin_image_ptr + RoundUp(sizeof(ImageHeader), kObjectAlignment); while (reinterpret_cast<const uintptr_t>(current) diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 322d3aa..a36e5b1 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -26,6 +26,7 @@ #include <vector> #include "arch/instruction_set_features.h" +#include "art_field-inl.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" #include "class_linker-inl.h" @@ -40,7 +41,6 @@ #include "image.h" #include "indenter.h" #include "mapping_table.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/array-inl.h" #include "mirror/class-inl.h" @@ -1549,9 +1549,6 @@ class ImageDumper { } else if (type->IsClassClass()) { mirror::Class* klass = value->AsClass(); os << StringPrintf("%p Class: %s\n", klass, PrettyDescriptor(klass).c_str()); - } else if (type->IsArtFieldClass()) { - mirror::ArtField* field = value->AsArtField(); - os << StringPrintf("%p Field: %s\n", field, PrettyField(field).c_str()); } else if (type->IsArtMethodClass()) { mirror::ArtMethod* method = value->AsArtMethod(); os << StringPrintf("%p Method: %s\n", method, PrettyMethod(method).c_str()); @@ -1560,7 +1557,7 @@ class ImageDumper { } } - static void PrintField(std::ostream& os, mirror::ArtField* field, mirror::Object* obj) + static void PrintField(std::ostream& os, ArtField* field, mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { os << StringPrintf("%s: ", field->GetName()); switch (field->GetTypeAsPrimitiveType()) { @@ -1619,12 +1616,9 @@ class ImageDumper { if (super != nullptr) { DumpFields(os, obj, super); } - mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields(); - if (fields != nullptr) { - for (int32_t i = 0; i < fields->GetLength(); i++) { - mirror::ArtField* field = fields->Get(i); - PrintField(os, field, obj); - } + ArtField* fields = klass->GetIFields(); + for (size_t i = 0, count = klass->NumInstanceFields(); i < count; i++) { + PrintField(os, &fields[i], obj); } } @@ -1686,9 +1680,6 @@ class ImageDumper { mirror::Class* klass = obj->AsClass(); os << StringPrintf("%p: java.lang.Class \"%s\" (", obj, PrettyDescriptor(klass).c_str()) << klass->GetStatus() << ")\n"; - } else if (obj->IsArtField()) { - os << StringPrintf("%p: java.lang.reflect.ArtField %s\n", obj, - PrettyField(obj->AsArtField()).c_str()); } else if (obj->IsArtMethod()) { os << StringPrintf("%p: java.lang.reflect.ArtMethod %s\n", obj, PrettyMethod(obj->AsArtMethod()).c_str()); @@ -1725,14 +1716,15 @@ class ImageDumper { PrettyObjectValue(indent_os, value_class, value); } } else if (obj->IsClass()) { - mirror::ObjectArray<mirror::ArtField>* sfields = obj->AsClass()->GetSFields(); - if (sfields != nullptr) { + mirror::Class* klass = obj->AsClass(); + ArtField* sfields = klass->GetSFields(); + const size_t num_fields = klass->NumStaticFields(); + if (num_fields != 0) { indent_os << "STATICS:\n"; Indenter indent2_filter(indent_os.rdbuf(), kIndentChar, kIndentBy1Count); std::ostream indent2_os(&indent2_filter); - for (int32_t i = 0; i < sfields->GetLength(); i++) { - mirror::ArtField* field = sfields->Get(i); - PrintField(indent2_os, field, field->GetDeclaringClass()); + for (size_t i = 0; i < num_fields; i++) { + PrintField(indent2_os, &sfields[i], sfields[i].GetDeclaringClass()); } } } else if (obj->IsArtMethod()) { diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index 9584064..74c9c38 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -24,6 +24,7 @@ #include <string> #include <vector> +#include "art_field-inl.h" #include "base/dumpable.h" #include "base/scoped_flock.h" #include "base/stringpiece.h" @@ -34,7 +35,6 @@ #include "elf_file_impl.h" #include "gc/space/image_space.h" #include "image.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/object-inl.h" #include "mirror/reference.h" @@ -415,13 +415,64 @@ bool PatchOat::ReplaceOatFileWithSymlink(const std::string& input_oat_filename, return true; } +void PatchOat::PatchArtFields(const ImageHeader* image_header) { + const size_t art_field_size = image_header->GetArtFieldsSize(); + const size_t art_field_offset = image_header->GetArtFieldsOffset(); + for (size_t pos = 0; pos < art_field_size; pos += sizeof(ArtField)) { + auto* field = reinterpret_cast<ArtField*>(heap_->Begin() + art_field_offset + pos); + auto* dest_field = RelocatedCopyOf(field); + dest_field->SetDeclaringClass(RelocatedAddressOfPointer(field->GetDeclaringClass())); + } +} + +void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) { + auto* dex_caches = down_cast<mirror::ObjectArray<mirror::DexCache>*>( + img_roots->Get(ImageHeader::kDexCaches)); + for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) { + auto* dex_cache = dex_caches->GetWithoutChecks(i); + auto* fields = dex_cache->GetResolvedFields(); + if (fields == nullptr) { + continue; + } + CHECK(!fields->IsObjectArray()); + CHECK(fields->IsArrayInstance()); + auto* component_type = fields->GetClass()->GetComponentType(); + if (component_type->IsPrimitiveInt()) { + mirror::IntArray* arr = fields->AsIntArray(); + mirror::IntArray* copy_arr = down_cast<mirror::IntArray*>(RelocatedCopyOf(arr)); + for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) { + auto f = arr->GetWithoutChecks(j); + if (f != 0) { + copy_arr->SetWithoutChecks<false>(j, f + delta_); + } + } + } else { + CHECK(component_type->IsPrimitiveLong()); + mirror::LongArray* arr = fields->AsLongArray(); + mirror::LongArray* copy_arr = down_cast<mirror::LongArray*>(RelocatedCopyOf(arr)); + for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) { + auto f = arr->GetWithoutChecks(j); + if (f != 0) { + copy_arr->SetWithoutChecks<false>(j, f + delta_); + } + } + } + } +} + bool PatchOat::PatchImage() { ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); CHECK_GT(image_->Size(), sizeof(ImageHeader)); // These are the roots from the original file. - mirror::Object* img_roots = image_header->GetImageRoots(); + auto* img_roots = image_header->GetImageRoots(); image_header->RelocateImage(delta_); + // Patch and update ArtFields. + PatchArtFields(image_header); + + // Patch dex file int/long arrays which point to ArtFields. + PatchDexFileArrays(img_roots); + VisitObject(img_roots); if (!image_header->IsValid()) { LOG(ERROR) << "reloction renders image header invalid"; @@ -448,7 +499,7 @@ void PatchOat::PatchVisitor::operator() (mirror::Object* obj, MemberOffset off, bool is_static_unused ATTRIBUTE_UNUSED) const { mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off); DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; - mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent); + mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); } @@ -457,30 +508,10 @@ void PatchOat::PatchVisitor::operator() (mirror::Class* cls ATTRIBUTE_UNUSED, MemberOffset off = mirror::Reference::ReferentOffset(); mirror::Object* referent = ref->GetReferent(); DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; - mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent); + mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); } -mirror::Object* PatchOat::RelocatedCopyOf(mirror::Object* obj) { - if (obj == nullptr) { - return nullptr; - } - DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin())); - DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End())); - uintptr_t heap_off = - reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin()); - DCHECK_LT(heap_off, image_->Size()); - return reinterpret_cast<mirror::Object*>(image_->Begin() + heap_off); -} - -mirror::Object* PatchOat::RelocatedAddressOf(mirror::Object* obj) { - if (obj == nullptr) { - return nullptr; - } else { - return reinterpret_cast<mirror::Object*>(reinterpret_cast<uint8_t*>(obj) + delta_); - } -} - const OatHeader* PatchOat::GetOatHeader(const ElfFile* elf_file) { if (elf_file->Is64Bit()) { return GetOatHeader<ElfFileImpl64>(elf_file->GetImpl64()); @@ -507,7 +538,7 @@ void PatchOat::VisitObject(mirror::Object* object) { if (kUseBakerOrBrooksReadBarrier) { object->AssertReadBarrierPointer(); if (kUseBrooksReadBarrier) { - mirror::Object* moved_to = RelocatedAddressOf(object); + mirror::Object* moved_to = RelocatedAddressOfPointer(object); copy->SetReadBarrierPointer(moved_to); DCHECK_EQ(copy->GetReadBarrierPointer(), moved_to); } @@ -516,6 +547,12 @@ void PatchOat::VisitObject(mirror::Object* object) { object->VisitReferences<true, kVerifyNone>(visitor, visitor); if (object->IsArtMethod<kVerifyNone>()) { FixupMethod(down_cast<mirror::ArtMethod*>(object), down_cast<mirror::ArtMethod*>(copy)); + } else if (object->IsClass<kVerifyNone>()) { + mirror::Class* klass = down_cast<mirror::Class*>(object); + down_cast<mirror::Class*>(copy)->SetSFieldsUnchecked( + RelocatedAddressOfPointer(klass->GetSFields())); + down_cast<mirror::Class*>(copy)->SetIFieldsUnchecked( + RelocatedAddressOfPointer(klass->GetIFields())); } } diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h index 578df3a..418650a 100644 --- a/patchoat/patchoat.h +++ b/patchoat/patchoat.h @@ -117,12 +117,31 @@ class PatchOat { bool PatchOatHeader(ElfFileImpl* oat_file); bool PatchImage() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void PatchArtFields(const ImageHeader* image_header) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool WriteElf(File* out); bool WriteImage(File* out); - mirror::Object* RelocatedCopyOf(mirror::Object*); - mirror::Object* RelocatedAddressOf(mirror::Object* obj); + template <typename T> + T* RelocatedCopyOf(T* obj) { + if (obj == nullptr) { + return nullptr; + } + DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin())); + DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End())); + uintptr_t heap_off = + reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin()); + DCHECK_LT(heap_off, image_->Size()); + return reinterpret_cast<T*>(image_->Begin() + heap_off); + } + + template <typename T> + T* RelocatedAddressOfPointer(T* obj) { + return obj == nullptr ? nullptr : + reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(obj) + delta_); + } // Look up the oat header from any elf file. static const OatHeader* GetOatHeader(const ElfFile* elf_file); diff --git a/runtime/Android.mk b/runtime/Android.mk index c0e7f47..d3488fc 100644 --- a/runtime/Android.mk +++ b/runtime/Android.mk @@ -19,6 +19,7 @@ LOCAL_PATH := $(call my-dir) include art/build/Android.common_build.mk LIBART_COMMON_SRC_FILES := \ + art_field.cc \ atomic.cc.arm \ barrier.cc \ base/allocator.cc \ @@ -96,9 +97,9 @@ LIBART_COMMON_SRC_FILES := \ jit/jit_instrumentation.cc \ jni_internal.cc \ jobject_comparator.cc \ + linear_alloc.cc \ mem_map.cc \ memory_region.cc \ - mirror/art_field.cc \ mirror/art_method.cc \ mirror/array.cc \ mirror/class.cc \ diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc index 0769687..d7de119 100644 --- a/runtime/arch/stub_test.cc +++ b/runtime/arch/stub_test.cc @@ -16,9 +16,9 @@ #include <cstdio> +#include "art_field-inl.h" #include "common_runtime_test.h" #include "entrypoints/quick/quick_entrypoints_enum.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/string-inl.h" @@ -1305,7 +1305,7 @@ TEST_F(StubTest, StringCompareTo) { } -static void GetSetBooleanStatic(Handle<mirror::ArtField>* f, Thread* self, +static void GetSetBooleanStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) @@ -1313,14 +1313,14 @@ static void GetSetBooleanStatic(Handle<mirror::ArtField>* f, Thread* self, uint8_t values[num_values] = { 0, 1, 2, 128, 0xFF }; for (size_t i = 0; i < num_values; ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), static_cast<size_t>(values[i]), 0U, StubTest::GetEntrypoint(self, kQuickSet8Static), self, referrer); - size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 0U, 0U, StubTest::GetEntrypoint(self, kQuickGetBooleanStatic), self, @@ -1335,21 +1335,21 @@ static void GetSetBooleanStatic(Handle<mirror::ArtField>* f, Thread* self, std::cout << "Skipping set_boolean_static as I don't know how to do that on " << kRuntimeISA << std::endl; #endif } -static void GetSetByteStatic(Handle<mirror::ArtField>* f, Thread* self, - mirror::ArtMethod* referrer, StubTest* test) +static void GetSetByteStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer, + StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) int8_t values[] = { -128, -64, 0, 64, 127 }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), static_cast<size_t>(values[i]), 0U, StubTest::GetEntrypoint(self, kQuickSet8Static), self, referrer); - size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 0U, 0U, StubTest::GetEntrypoint(self, kQuickGetByteStatic), self, @@ -1365,26 +1365,26 @@ static void GetSetByteStatic(Handle<mirror::ArtField>* f, Thread* self, } -static void GetSetBooleanInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f, - Thread* self, mirror::ArtMethod* referrer, StubTest* test) +static void GetSetBooleanInstance(Handle<mirror::Object>* obj, ArtField* f, Thread* self, + mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) uint8_t values[] = { 0, true, 2, 128, 0xFF }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), static_cast<size_t>(values[i]), StubTest::GetEntrypoint(self, kQuickSet8Instance), self, referrer); - uint8_t res = f->Get()->GetBoolean(obj->Get()); + uint8_t res = f->GetBoolean(obj->Get()); EXPECT_EQ(values[i], res) << "Iteration " << i; - f->Get()->SetBoolean<false>(obj->Get(), res); + f->SetBoolean<false>(obj->Get(), res); - size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), 0U, StubTest::GetEntrypoint(self, kQuickGetBooleanInstance), @@ -1399,25 +1399,25 @@ static void GetSetBooleanInstance(Handle<mirror::Object>* obj, Handle<mirror::Ar std::cout << "Skipping set_boolean_instance as I don't know how to do that on " << kRuntimeISA << std::endl; #endif } -static void GetSetByteInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f, +static void GetSetByteInstance(Handle<mirror::Object>* obj, ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) int8_t values[] = { -128, -64, 0, 64, 127 }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), static_cast<size_t>(values[i]), StubTest::GetEntrypoint(self, kQuickSet8Instance), self, referrer); - int8_t res = f->Get()->GetByte(obj->Get()); + int8_t res = f->GetByte(obj->Get()); EXPECT_EQ(res, values[i]) << "Iteration " << i; - f->Get()->SetByte<false>(obj->Get(), ++res); + f->SetByte<false>(obj->Get(), ++res); - size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), 0U, StubTest::GetEntrypoint(self, kQuickGetByteInstance), @@ -1433,21 +1433,21 @@ static void GetSetByteInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtFi #endif } -static void GetSetCharStatic(Handle<mirror::ArtField>* f, Thread* self, mirror::ArtMethod* referrer, +static void GetSetCharStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) uint16_t values[] = { 0, 1, 2, 255, 32768, 0xFFFF }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), static_cast<size_t>(values[i]), 0U, StubTest::GetEntrypoint(self, kQuickSet16Static), self, referrer); - size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 0U, 0U, StubTest::GetEntrypoint(self, kQuickGetCharStatic), self, @@ -1462,21 +1462,21 @@ static void GetSetCharStatic(Handle<mirror::ArtField>* f, Thread* self, mirror:: std::cout << "Skipping set_char_static as I don't know how to do that on " << kRuntimeISA << std::endl; #endif } -static void GetSetShortStatic(Handle<mirror::ArtField>* f, Thread* self, +static void GetSetShortStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) int16_t values[] = { -0x7FFF, -32768, 0, 255, 32767, 0x7FFE }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), static_cast<size_t>(values[i]), 0U, StubTest::GetEntrypoint(self, kQuickSet16Static), self, referrer); - size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 0U, 0U, StubTest::GetEntrypoint(self, kQuickGetShortStatic), self, @@ -1492,25 +1492,25 @@ static void GetSetShortStatic(Handle<mirror::ArtField>* f, Thread* self, #endif } -static void GetSetCharInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f, - Thread* self, mirror::ArtMethod* referrer, StubTest* test) +static void GetSetCharInstance(Handle<mirror::Object>* obj, ArtField* f, + Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) uint16_t values[] = { 0, 1, 2, 255, 32768, 0xFFFF }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), static_cast<size_t>(values[i]), StubTest::GetEntrypoint(self, kQuickSet16Instance), self, referrer); - uint16_t res = f->Get()->GetChar(obj->Get()); + uint16_t res = f->GetChar(obj->Get()); EXPECT_EQ(res, values[i]) << "Iteration " << i; - f->Get()->SetChar<false>(obj->Get(), ++res); + f->SetChar<false>(obj->Get(), ++res); - size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), 0U, StubTest::GetEntrypoint(self, kQuickGetCharInstance), @@ -1525,25 +1525,25 @@ static void GetSetCharInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtFi std::cout << "Skipping set_char_instance as I don't know how to do that on " << kRuntimeISA << std::endl; #endif } -static void GetSetShortInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f, +static void GetSetShortInstance(Handle<mirror::Object>* obj, ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) int16_t values[] = { -0x7FFF, -32768, 0, 255, 32767, 0x7FFE }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), static_cast<size_t>(values[i]), StubTest::GetEntrypoint(self, kQuickSet16Instance), self, referrer); - int16_t res = f->Get()->GetShort(obj->Get()); + int16_t res = f->GetShort(obj->Get()); EXPECT_EQ(res, values[i]) << "Iteration " << i; - f->Get()->SetShort<false>(obj->Get(), ++res); + f->SetShort<false>(obj->Get(), ++res); - size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), 0U, StubTest::GetEntrypoint(self, kQuickGetShortInstance), @@ -1559,21 +1559,21 @@ static void GetSetShortInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtF #endif } -static void GetSet32Static(Handle<mirror::ArtField>* f, Thread* self, mirror::ArtMethod* referrer, +static void GetSet32Static(ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) uint32_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), static_cast<size_t>(values[i]), 0U, StubTest::GetEntrypoint(self, kQuickSet32Static), self, referrer); - size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 0U, 0U, StubTest::GetEntrypoint(self, kQuickGet32Static), self, @@ -1590,27 +1590,27 @@ static void GetSet32Static(Handle<mirror::ArtField>* f, Thread* self, mirror::Ar } -static void GetSet32Instance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f, +static void GetSet32Instance(Handle<mirror::Object>* obj, ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) uint32_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), static_cast<size_t>(values[i]), StubTest::GetEntrypoint(self, kQuickSet32Instance), self, referrer); - int32_t res = f->Get()->GetInt(obj->Get()); + int32_t res = f->GetInt(obj->Get()); EXPECT_EQ(res, static_cast<int32_t>(values[i])) << "Iteration " << i; res++; - f->Get()->SetInt<false>(obj->Get(), res); + f->SetInt<false>(obj->Get(), res); - size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), 0U, StubTest::GetEntrypoint(self, kQuickGet32Instance), @@ -1649,17 +1649,17 @@ static void set_and_check_static(uint32_t f_idx, mirror::Object* val, Thread* se } #endif -static void GetSetObjStatic(Handle<mirror::ArtField>* f, Thread* self, mirror::ArtMethod* referrer, +static void GetSetObjStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) - set_and_check_static((*f)->GetDexFieldIndex(), nullptr, self, referrer, test); + set_and_check_static(f->GetDexFieldIndex(), nullptr, self, referrer, test); // Allocate a string object for simplicity. mirror::String* str = mirror::String::AllocFromModifiedUtf8(self, "Test"); - set_and_check_static((*f)->GetDexFieldIndex(), str, self, referrer, test); + set_and_check_static(f->GetDexFieldIndex(), str, self, referrer, test); - set_and_check_static((*f)->GetDexFieldIndex(), nullptr, self, referrer, test); + set_and_check_static(f->GetDexFieldIndex(), nullptr, self, referrer, test); #else UNUSED(f, self, referrer, test); LOG(INFO) << "Skipping setObjstatic as I don't know how to do that on " << kRuntimeISA; @@ -1670,18 +1670,18 @@ static void GetSetObjStatic(Handle<mirror::ArtField>* f, Thread* self, mirror::A #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) -static void set_and_check_instance(Handle<mirror::ArtField>* f, mirror::Object* trg, +static void set_and_check_instance(ArtField* f, mirror::Object* trg, mirror::Object* val, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(trg), reinterpret_cast<size_t>(val), StubTest::GetEntrypoint(self, kQuickSetObjInstance), self, referrer); - size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(trg), 0U, StubTest::GetEntrypoint(self, kQuickGetObjInstance), @@ -1690,11 +1690,11 @@ static void set_and_check_instance(Handle<mirror::ArtField>* f, mirror::Object* EXPECT_EQ(res, reinterpret_cast<size_t>(val)) << "Value " << val; - EXPECT_EQ(val, f->Get()->GetObj(trg)); + EXPECT_EQ(val, f->GetObj(trg)); } #endif -static void GetSetObjInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f, +static void GetSetObjInstance(Handle<mirror::Object>* obj, ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || (defined(__x86_64__) && !defined(__APPLE__)) @@ -1716,20 +1716,20 @@ static void GetSetObjInstance(Handle<mirror::Object>* obj, Handle<mirror::ArtFie // TODO: Complete these tests for 32b architectures. -static void GetSet64Static(Handle<mirror::ArtField>* f, Thread* self, mirror::ArtMethod* referrer, +static void GetSet64Static(ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if (defined(__x86_64__) && !defined(__APPLE__)) || defined(__aarch64__) uint64_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF, 0xFFFFFFFFFFFF }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3UWithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3UWithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), values[i], StubTest::GetEntrypoint(self, kQuickSet64Static), self, referrer); - size_t res = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 0U, 0U, StubTest::GetEntrypoint(self, kQuickGet64Static), self, @@ -1746,27 +1746,27 @@ static void GetSet64Static(Handle<mirror::ArtField>* f, Thread* self, mirror::Ar } -static void GetSet64Instance(Handle<mirror::Object>* obj, Handle<mirror::ArtField>* f, +static void GetSet64Instance(Handle<mirror::Object>* obj, ArtField* f, Thread* self, mirror::ArtMethod* referrer, StubTest* test) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if (defined(__x86_64__) && !defined(__APPLE__)) || defined(__aarch64__) uint64_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF, 0xFFFFFFFFFFFF }; for (size_t i = 0; i < arraysize(values); ++i) { - test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), static_cast<size_t>(values[i]), StubTest::GetEntrypoint(self, kQuickSet64Instance), self, referrer); - int64_t res = f->Get()->GetLong(obj->Get()); + int64_t res = f->GetLong(obj->Get()); EXPECT_EQ(res, static_cast<int64_t>(values[i])) << "Iteration " << i; res++; - f->Get()->SetLong<false>(obj->Get(), res); + f->SetLong<false>(obj->Get(), res); - size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>((*f)->GetDexFieldIndex()), + size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), reinterpret_cast<size_t>(obj->Get()), 0U, StubTest::GetEntrypoint(self, kQuickGet64Instance), @@ -1792,7 +1792,7 @@ static void TestFields(Thread* self, StubTest* test, Primitive::Type test_type) CHECK(o != NULL); ScopedObjectAccess soa(self); - StackHandleScope<5> hs(self); + StackHandleScope<4> hs(self); Handle<mirror::Object> obj(hs.NewHandle(soa.Decode<mirror::Object*>(o))); Handle<mirror::Class> c(hs.NewHandle(obj->GetClass())); // Need a method as a referrer @@ -1801,112 +1801,80 @@ static void TestFields(Thread* self, StubTest* test, Primitive::Type test_type) // Play with it... // Static fields. - { - Handle<mirror::ObjectArray<mirror::ArtField>> fields(hs.NewHandle(c.Get()->GetSFields())); - int32_t num_fields = fields->GetLength(); - for (int32_t i = 0; i < num_fields; ++i) { - StackHandleScope<1> hs2(self); - Handle<mirror::ArtField> f(hs2.NewHandle(fields->Get(i))); - - Primitive::Type type = f->GetTypeAsPrimitiveType(); - switch (type) { - case Primitive::Type::kPrimBoolean: - if (test_type == type) { - GetSetBooleanStatic(&f, self, m.Get(), test); - } - break; - case Primitive::Type::kPrimByte: - if (test_type == type) { - GetSetByteStatic(&f, self, m.Get(), test); - } - break; - case Primitive::Type::kPrimChar: - if (test_type == type) { - GetSetCharStatic(&f, self, m.Get(), test); - } - break; - case Primitive::Type::kPrimShort: - if (test_type == type) { - GetSetShortStatic(&f, self, m.Get(), test); - } - break; - case Primitive::Type::kPrimInt: - if (test_type == type) { - GetSet32Static(&f, self, m.Get(), test); - } - break; - - case Primitive::Type::kPrimLong: - if (test_type == type) { - GetSet64Static(&f, self, m.Get(), test); - } - break; - - case Primitive::Type::kPrimNot: - // Don't try array. - if (test_type == type && f->GetTypeDescriptor()[0] != '[') { - GetSetObjStatic(&f, self, m.Get(), test); - } - break; - - default: - break; // Skip. - } + ArtField* fields = c->GetSFields(); + size_t num_fields = c->NumStaticFields(); + for (size_t i = 0; i < num_fields; ++i) { + ArtField* f = &fields[i]; + Primitive::Type type = f->GetTypeAsPrimitiveType(); + if (test_type != type) { + continue; + } + switch (type) { + case Primitive::Type::kPrimBoolean: + GetSetBooleanStatic(f, self, m.Get(), test); + break; + case Primitive::Type::kPrimByte: + GetSetByteStatic(f, self, m.Get(), test); + break; + case Primitive::Type::kPrimChar: + GetSetCharStatic(f, self, m.Get(), test); + break; + case Primitive::Type::kPrimShort: + GetSetShortStatic(f, self, m.Get(), test); + break; + case Primitive::Type::kPrimInt: + GetSet32Static(f, self, m.Get(), test); + break; + case Primitive::Type::kPrimLong: + GetSet64Static(f, self, m.Get(), test); + break; + case Primitive::Type::kPrimNot: + // Don't try array. + if (f->GetTypeDescriptor()[0] != '[') { + GetSetObjStatic(f, self, m.Get(), test); + } + break; + default: + break; // Skip. } } // Instance fields. - { - Handle<mirror::ObjectArray<mirror::ArtField>> fields(hs.NewHandle(c.Get()->GetIFields())); - int32_t num_fields = fields->GetLength(); - for (int32_t i = 0; i < num_fields; ++i) { - StackHandleScope<1> hs2(self); - Handle<mirror::ArtField> f(hs2.NewHandle(fields->Get(i))); - - Primitive::Type type = f->GetTypeAsPrimitiveType(); - switch (type) { - case Primitive::Type::kPrimBoolean: - if (test_type == type) { - GetSetBooleanInstance(&obj, &f, self, m.Get(), test); - } - break; - case Primitive::Type::kPrimByte: - if (test_type == type) { - GetSetByteInstance(&obj, &f, self, m.Get(), test); - } - break; - case Primitive::Type::kPrimChar: - if (test_type == type) { - GetSetCharInstance(&obj, &f, self, m.Get(), test); - } - break; - case Primitive::Type::kPrimShort: - if (test_type == type) { - GetSetShortInstance(&obj, &f, self, m.Get(), test); - } - break; - case Primitive::Type::kPrimInt: - if (test_type == type) { - GetSet32Instance(&obj, &f, self, m.Get(), test); - } - break; - - case Primitive::Type::kPrimLong: - if (test_type == type) { - GetSet64Instance(&obj, &f, self, m.Get(), test); - } - break; - - case Primitive::Type::kPrimNot: - // Don't try array. - if (test_type == type && f->GetTypeDescriptor()[0] != '[') { - GetSetObjInstance(&obj, &f, self, m.Get(), test); - } - break; - - default: - break; // Skip. - } + fields = c->GetIFields(); + num_fields = c->NumInstanceFields(); + for (size_t i = 0; i < num_fields; ++i) { + ArtField* f = &fields[i]; + Primitive::Type type = f->GetTypeAsPrimitiveType(); + if (test_type != type) { + continue; + } + switch (type) { + case Primitive::Type::kPrimBoolean: + GetSetBooleanInstance(&obj, f, self, m.Get(), test); + break; + case Primitive::Type::kPrimByte: + GetSetByteInstance(&obj, f, self, m.Get(), test); + break; + case Primitive::Type::kPrimChar: + GetSetCharInstance(&obj, f, self, m.Get(), test); + break; + case Primitive::Type::kPrimShort: + GetSetShortInstance(&obj, f, self, m.Get(), test); + break; + case Primitive::Type::kPrimInt: + GetSet32Instance(&obj, f, self, m.Get(), test); + break; + case Primitive::Type::kPrimLong: + GetSet64Instance(&obj, f, self, m.Get(), test); + break; + case Primitive::Type::kPrimNot: + // Don't try array. + if (f->GetTypeDescriptor()[0] != '[') { + GetSetObjInstance(&obj, f, self, m.Get(), test); + } + break; + default: + break; // Skip. } } diff --git a/runtime/mirror/art_field-inl.h b/runtime/art_field-inl.h index 986852f..aeb1273 100644 --- a/runtime/mirror/art_field-inl.h +++ b/runtime/art_field-inl.h @@ -14,57 +14,51 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_MIRROR_ART_FIELD_INL_H_ -#define ART_RUNTIME_MIRROR_ART_FIELD_INL_H_ +#ifndef ART_RUNTIME_ART_FIELD_INL_H_ +#define ART_RUNTIME_ART_FIELD_INL_H_ #include "art_field.h" #include "base/logging.h" #include "class_linker.h" -#include "dex_cache.h" #include "gc/accounting/card_table-inl.h" #include "jvalue.h" -#include "object-inl.h" +#include "mirror/dex_cache.h" +#include "mirror/object-inl.h" #include "primitive.h" #include "thread-inl.h" #include "scoped_thread_state_change.h" #include "well_known_classes.h" namespace art { -namespace mirror { -inline uint32_t ArtField::ClassSize() { - uint32_t vtable_entries = Object::kVTableLength; - return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0); -} - -inline Class* ArtField::GetDeclaringClass() { - Class* result = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_)); - DCHECK(result != NULL); +inline mirror::Class* ArtField::GetDeclaringClass() { + mirror::Class* result = declaring_class_.Read(); + DCHECK(result != nullptr); DCHECK(result->IsLoaded() || result->IsErroneous()); return result; } -inline void ArtField::SetDeclaringClass(Class *new_declaring_class) { - SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ArtField, declaring_class_), new_declaring_class); +inline void ArtField::SetDeclaringClass(mirror::Class* new_declaring_class) { + declaring_class_ = GcRoot<mirror::Class>(new_declaring_class); } inline uint32_t ArtField::GetAccessFlags() { DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); - return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, access_flags_)); + return access_flags_; } inline MemberOffset ArtField::GetOffset() { DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); - return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_))); + return MemberOffset(offset_); } inline MemberOffset ArtField::GetOffsetDuringLinking() { DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); - return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_))); + return MemberOffset(offset_); } -inline uint32_t ArtField::Get32(Object* object) { +inline uint32_t ArtField::Get32(mirror::Object* object) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -74,7 +68,7 @@ inline uint32_t ArtField::Get32(Object* object) { } template<bool kTransactionActive> -inline void ArtField::Set32(Object* object, uint32_t new_value) { +inline void ArtField::Set32(mirror::Object* object, uint32_t new_value) { DCHECK(object != nullptr) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -84,7 +78,7 @@ inline void ArtField::Set32(Object* object, uint32_t new_value) { } } -inline uint64_t ArtField::Get64(Object* object) { +inline uint64_t ArtField::Get64(mirror::Object* object) { DCHECK(object != NULL) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -94,7 +88,7 @@ inline uint64_t ArtField::Get64(Object* object) { } template<bool kTransactionActive> -inline void ArtField::Set64(Object* object, uint64_t new_value) { +inline void ArtField::Set64(mirror::Object* object, uint64_t new_value) { DCHECK(object != NULL) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -104,17 +98,17 @@ inline void ArtField::Set64(Object* object, uint64_t new_value) { } } -inline Object* ArtField::GetObj(Object* object) { +inline mirror::Object* ArtField::GetObj(mirror::Object* object) { DCHECK(object != NULL) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { - return object->GetFieldObjectVolatile<Object>(GetOffset()); + return object->GetFieldObjectVolatile<mirror::Object>(GetOffset()); } - return object->GetFieldObject<Object>(GetOffset()); + return object->GetFieldObject<mirror::Object>(GetOffset()); } template<bool kTransactionActive> -inline void ArtField::SetObj(Object* object, Object* new_value) { +inline void ArtField::SetObj(mirror::Object* object, mirror::Object* new_value) { DCHECK(object != NULL) << PrettyField(this); DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); if (UNLIKELY(IsVolatile())) { @@ -143,46 +137,46 @@ inline void ArtField::SetObj(Object* object, Object* new_value) { object->SetField ## type<kTransactionActive>(GetOffset(), value); \ } -inline uint8_t ArtField::GetBoolean(Object* object) { +inline uint8_t ArtField::GetBoolean(mirror::Object* object) { FIELD_GET(object, Boolean); } template<bool kTransactionActive> -inline void ArtField::SetBoolean(Object* object, uint8_t z) { +inline void ArtField::SetBoolean(mirror::Object* object, uint8_t z) { FIELD_SET(object, Boolean, z); } -inline int8_t ArtField::GetByte(Object* object) { +inline int8_t ArtField::GetByte(mirror::Object* object) { FIELD_GET(object, Byte); } template<bool kTransactionActive> -inline void ArtField::SetByte(Object* object, int8_t b) { +inline void ArtField::SetByte(mirror::Object* object, int8_t b) { FIELD_SET(object, Byte, b); } -inline uint16_t ArtField::GetChar(Object* object) { +inline uint16_t ArtField::GetChar(mirror::Object* object) { FIELD_GET(object, Char); } template<bool kTransactionActive> -inline void ArtField::SetChar(Object* object, uint16_t c) { +inline void ArtField::SetChar(mirror::Object* object, uint16_t c) { FIELD_SET(object, Char, c); } -inline int16_t ArtField::GetShort(Object* object) { +inline int16_t ArtField::GetShort(mirror::Object* object) { FIELD_GET(object, Short); } template<bool kTransactionActive> -inline void ArtField::SetShort(Object* object, int16_t s) { +inline void ArtField::SetShort(mirror::Object* object, int16_t s) { FIELD_SET(object, Short, s); } #undef FIELD_GET #undef FIELD_SET -inline int32_t ArtField::GetInt(Object* object) { +inline int32_t ArtField::GetInt(mirror::Object* object) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); @@ -191,7 +185,7 @@ inline int32_t ArtField::GetInt(Object* object) { } template<bool kTransactionActive> -inline void ArtField::SetInt(Object* object, int32_t i) { +inline void ArtField::SetInt(mirror::Object* object, int32_t i) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); @@ -199,7 +193,7 @@ inline void ArtField::SetInt(Object* object, int32_t i) { Set32<kTransactionActive>(object, i); } -inline int64_t ArtField::GetLong(Object* object) { +inline int64_t ArtField::GetLong(mirror::Object* object) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); @@ -208,7 +202,7 @@ inline int64_t ArtField::GetLong(Object* object) { } template<bool kTransactionActive> -inline void ArtField::SetLong(Object* object, int64_t j) { +inline void ArtField::SetLong(mirror::Object* object, int64_t j) { if (kIsDebugBuild) { Primitive::Type type = GetTypeAsPrimitiveType(); CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); @@ -216,7 +210,7 @@ inline void ArtField::SetLong(Object* object, int64_t j) { Set64<kTransactionActive>(object, j); } -inline float ArtField::GetFloat(Object* object) { +inline float ArtField::GetFloat(mirror::Object* object) { DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetI(Get32(object)); @@ -224,14 +218,14 @@ inline float ArtField::GetFloat(Object* object) { } template<bool kTransactionActive> -inline void ArtField::SetFloat(Object* object, float f) { +inline void ArtField::SetFloat(mirror::Object* object, float f) { DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetF(f); Set32<kTransactionActive>(object, bits.GetI()); } -inline double ArtField::GetDouble(Object* object) { +inline double ArtField::GetDouble(mirror::Object* object) { DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetJ(Get64(object)); @@ -239,20 +233,20 @@ inline double ArtField::GetDouble(Object* object) { } template<bool kTransactionActive> -inline void ArtField::SetDouble(Object* object, double d) { +inline void ArtField::SetDouble(mirror::Object* object, double d) { DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this); JValue bits; bits.SetD(d); Set64<kTransactionActive>(object, bits.GetJ()); } -inline Object* ArtField::GetObject(Object* object) { +inline mirror::Object* ArtField::GetObject(mirror::Object* object) { DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); return GetObj(object); } template<bool kTransactionActive> -inline void ArtField::SetObject(Object* object, Object* l) { +inline void ArtField::SetObject(mirror::Object* object, mirror::Object* l) { DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); SetObj<kTransactionActive>(object, l); } @@ -291,7 +285,7 @@ inline bool ArtField::IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_loc } template <bool kResolve> -inline Class* ArtField::GetType() { +inline mirror::Class* ArtField::GetType() { const uint32_t field_index = GetDexFieldIndex(); auto* declaring_class = GetDeclaringClass(); if (UNLIKELY(declaring_class->IsProxyClass())) { @@ -321,7 +315,7 @@ inline const DexFile* ArtField::GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutato return GetDexCache()->GetDexFile(); } -inline String* ArtField::GetStringName(Thread* self, bool resolve) { +inline mirror::String* ArtField::GetStringName(Thread* self, bool resolve) { auto dex_field_index = GetDexFieldIndex(); CHECK_NE(dex_field_index, DexFile::kDexNoIndex); auto* dex_cache = GetDexCache(); @@ -336,7 +330,6 @@ inline String* ArtField::GetStringName(Thread* self, bool resolve) { return name; } -} // namespace mirror } // namespace art -#endif // ART_RUNTIME_MIRROR_ART_FIELD_INL_H_ +#endif // ART_RUNTIME_ART_FIELD_INL_H_ diff --git a/runtime/mirror/art_field.cc b/runtime/art_field.cc index 83602d4..cdf8967 100644 --- a/runtime/mirror/art_field.cc +++ b/runtime/art_field.cc @@ -18,28 +18,17 @@ #include "art_field-inl.h" #include "gc/accounting/card_table-inl.h" -#include "object-inl.h" -#include "object_array-inl.h" +#include "mirror/object-inl.h" +#include "mirror/object_array-inl.h" #include "runtime.h" #include "scoped_thread_state_change.h" #include "utils.h" #include "well_known_classes.h" namespace art { -namespace mirror { -// TODO: Get global references for these -GcRoot<Class> ArtField::java_lang_reflect_ArtField_; - -void ArtField::SetClass(Class* java_lang_reflect_ArtField) { - CHECK(java_lang_reflect_ArtField_.IsNull()); - CHECK(java_lang_reflect_ArtField != NULL); - java_lang_reflect_ArtField_ = GcRoot<Class>(java_lang_reflect_ArtField); -} - -void ArtField::ResetClass() { - CHECK(!java_lang_reflect_ArtField_.IsNull()); - java_lang_reflect_ArtField_ = GcRoot<Class>(nullptr); +ArtField::ArtField() : access_flags_(0), field_dex_idx_(0), offset_(0) { + declaring_class_ = GcRoot<mirror::Class>(nullptr); } void ArtField::SetOffset(MemberOffset num_bytes) { @@ -52,32 +41,24 @@ void ArtField::SetOffset(MemberOffset num_bytes) { } } // Not called within a transaction. - SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_), num_bytes.Uint32Value()); + offset_ = num_bytes.Uint32Value(); } void ArtField::VisitRoots(RootVisitor* visitor) { - java_lang_reflect_ArtField_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass)); + declaring_class_.VisitRoot(visitor, RootInfo(kRootStickyClass)); } -// TODO: we could speed up the search if fields are ordered by offsets. ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset) { DCHECK(klass != nullptr); - ObjectArray<ArtField>* instance_fields = klass->GetIFields(); - if (instance_fields != nullptr) { - for (int32_t i = 0, e = instance_fields->GetLength(); i < e; ++i) { - mirror::ArtField* field = instance_fields->GetWithoutChecks(i); - if (field->GetOffset().Uint32Value() == field_offset) { - return field; - } + auto* instance_fields = klass->GetIFields(); + for (size_t i = 0, count = klass->NumInstanceFields(); i < count; ++i) { + if (instance_fields[i].GetOffset().Uint32Value() == field_offset) { + return &instance_fields[i]; } } // We did not find field in the class: look into superclass. - if (klass->GetSuperClass() != NULL) { - return FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset); - } else { - return nullptr; - } + return (klass->GetSuperClass() != nullptr) ? + FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset) : nullptr; } -} // namespace mirror } // namespace art diff --git a/runtime/mirror/art_field.h b/runtime/art_field.h index 9d95cb9..5bdbe71 100644 --- a/runtime/mirror/art_field.h +++ b/runtime/art_field.h @@ -14,48 +14,44 @@ * limitations under the License. */ -#ifndef ART_RUNTIME_MIRROR_ART_FIELD_H_ -#define ART_RUNTIME_MIRROR_ART_FIELD_H_ +#ifndef ART_RUNTIME_ART_FIELD_H_ +#define ART_RUNTIME_ART_FIELD_H_ #include <jni.h> #include "gc_root.h" #include "modifiers.h" -#include "object.h" #include "object_callbacks.h" +#include "offsets.h" #include "primitive.h" #include "read_barrier_option.h" namespace art { -struct ArtFieldOffsets; class DexFile; class ScopedObjectAccessAlreadyRunnable; namespace mirror { - +class Class; class DexCache; +class Object; +class String; +} // namespace mirror -// C++ mirror of java.lang.reflect.ArtField -class MANAGED ArtField FINAL : public Object { +class ArtField { public: - // Size of java.lang.reflect.ArtField.class. - static uint32_t ClassSize(); + ArtField(); - // Size of an instance of java.lang.reflect.ArtField not including its value array. - static constexpr uint32_t InstanceSize() { - return sizeof(ArtField); - } + mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetDeclaringClass(mirror::Class *new_declaring_class) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Not called within a transaction. - SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtField, access_flags_), new_access_flags); + access_flags_ = new_access_flags; } bool IsPublic() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -70,13 +66,13 @@ class MANAGED ArtField FINAL : public Object { return (GetAccessFlags() & kAccFinal) != 0; } - uint32_t GetDexFieldIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, field_dex_idx_)); + uint32_t GetDexFieldIndex() { + return field_dex_idx_; } - void SetDexFieldIndex(uint32_t new_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + void SetDexFieldIndex(uint32_t new_idx) { // Not called within a transaction. - SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtField, field_dex_idx_), new_idx); + field_dex_idx_ = new_idx; } // Offset to field within an Object. @@ -91,54 +87,71 @@ class MANAGED ArtField FINAL : public Object { void SetOffset(MemberOffset num_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // field access, null object for static fields - uint8_t GetBoolean(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + uint8_t GetBoolean(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetBoolean(Object* object, uint8_t z) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - int8_t GetByte(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetBoolean(mirror::Object* object, uint8_t z) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + int8_t GetByte(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetByte(Object* object, int8_t b) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - uint16_t GetChar(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetByte(mirror::Object* object, int8_t b) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + uint16_t GetChar(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetChar(Object* object, uint16_t c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - int16_t GetShort(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetChar(mirror::Object* object, uint16_t c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + int16_t GetShort(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetShort(Object* object, int16_t s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - int32_t GetInt(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetShort(mirror::Object* object, int16_t s) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + int32_t GetInt(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetInt(Object* object, int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - int64_t GetLong(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetInt(mirror::Object* object, int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + int64_t GetLong(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetLong(Object* object, int64_t j) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - float GetFloat(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetLong(mirror::Object* object, int64_t j) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + float GetFloat(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetFloat(Object* object, float f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - double GetDouble(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetFloat(mirror::Object* object, float f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + double GetDouble(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetDouble(Object* object, double d) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Object* GetObject(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetDouble(mirror::Object* object, double d) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + mirror::Object* GetObject(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetObject(Object* object, Object* l) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetObject(mirror::Object* object, mirror::Object* l) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Raw field accesses. - uint32_t Get32(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - template<bool kTransactionActive> - void Set32(Object* object, uint32_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - uint64_t Get64(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + uint32_t Get32(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void Set64(Object* object, uint64_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Object* GetObj(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void Set32(mirror::Object* object, uint32_t new_value) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + uint64_t Get64(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<bool kTransactionActive> - void SetObj(Object* object, Object* new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void Set64(mirror::Object* object, uint64_t new_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - static Class* GetJavaLangReflectArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(!java_lang_reflect_ArtField_.IsNull()); - return java_lang_reflect_ArtField_.Read<kReadBarrierOption>(); - } + mirror::Object* GetObj(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void SetClass(Class* java_lang_reflect_ArtField); - static void ResetClass(); - static void VisitRoots(RootVisitor* visitor) + template<bool kTransactionActive> + void SetObj(mirror::Object* object, mirror::Object* new_value) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool IsVolatile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -152,7 +165,8 @@ class MANAGED ArtField FINAL : public Object { const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolves / returns the name from the dex cache. - String* GetStringName(Thread* self, bool resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::String* GetStringName(Thread* self, bool resolve) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const char* GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -161,7 +175,7 @@ class MANAGED ArtField FINAL : public Object { bool IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); template <bool kResolve> - Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::Class* GetType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); size_t FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -169,10 +183,12 @@ class MANAGED ArtField FINAL : public Object { const DexFile* GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + GcRoot<mirror::Class>& DeclaringClassRoot() { + return declaring_class_; + } + private: - // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". - // The class we are a part of - HeapReference<Class> declaring_class_; + GcRoot<mirror::Class> declaring_class_; uint32_t access_flags_; @@ -181,14 +197,8 @@ class MANAGED ArtField FINAL : public Object { // Offset of field within an instance or in the Class' static fields uint32_t offset_; - - static GcRoot<Class> java_lang_reflect_ArtField_; - - friend struct art::ArtFieldOffsets; // for verifying offset information - DISALLOW_IMPLICIT_CONSTRUCTORS(ArtField); }; -} // namespace mirror } // namespace art -#endif // ART_RUNTIME_MIRROR_ART_FIELD_H_ +#endif // ART_RUNTIME_ART_FIELD_H_ diff --git a/runtime/asm_support.h b/runtime/asm_support.h index dba4af8..4c83e88 100644 --- a/runtime/asm_support.h +++ b/runtime/asm_support.h @@ -135,13 +135,13 @@ ADD_TEST_EQ(size_t(MIRROR_OBJECT_HEADER_SIZE), sizeof(art::mirror::Object)) #define MIRROR_CLASS_COMPONENT_TYPE_OFFSET (4 + MIRROR_OBJECT_HEADER_SIZE) ADD_TEST_EQ(MIRROR_CLASS_COMPONENT_TYPE_OFFSET, art::mirror::Class::ComponentTypeOffset().Int32Value()) -#define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (52 + MIRROR_OBJECT_HEADER_SIZE) +#define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (44 + MIRROR_OBJECT_HEADER_SIZE) ADD_TEST_EQ(MIRROR_CLASS_ACCESS_FLAGS_OFFSET, art::mirror::Class::AccessFlagsOffset().Int32Value()) -#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (80 + MIRROR_OBJECT_HEADER_SIZE) +#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (96 + MIRROR_OBJECT_HEADER_SIZE) ADD_TEST_EQ(MIRROR_CLASS_OBJECT_SIZE_OFFSET, art::mirror::Class::ObjectSizeOffset().Int32Value()) -#define MIRROR_CLASS_STATUS_OFFSET (92 + MIRROR_OBJECT_HEADER_SIZE) +#define MIRROR_CLASS_STATUS_OFFSET (108 + MIRROR_OBJECT_HEADER_SIZE) ADD_TEST_EQ(MIRROR_CLASS_STATUS_OFFSET, art::mirror::Class::StatusOffset().Int32Value()) diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc index dd29404..59d38ad 100644 --- a/runtime/base/arena_allocator.cc +++ b/runtime/base/arena_allocator.cc @@ -132,11 +132,10 @@ MallocArena::~MallocArena() { free(reinterpret_cast<void*>(memory_)); } -MemMapArena::MemMapArena(size_t size) { +MemMapArena::MemMapArena(size_t size, bool low_4gb) { std::string error_msg; - map_.reset( - MemMap::MapAnonymous("dalvik-LinearAlloc", nullptr, size, PROT_READ | PROT_WRITE, false, - false, &error_msg)); + map_.reset(MemMap::MapAnonymous( + "LinearAlloc", nullptr, size, PROT_READ | PROT_WRITE, low_4gb, false, &error_msg)); CHECK(map_.get() != nullptr) << error_msg; memory_ = map_->Begin(); size_ = map_->Size(); @@ -156,8 +155,12 @@ void Arena::Reset() { } } -ArenaPool::ArenaPool(bool use_malloc) - : use_malloc_(use_malloc), lock_("Arena pool lock"), free_arenas_(nullptr) { +ArenaPool::ArenaPool(bool use_malloc, bool low_4gb) + : use_malloc_(use_malloc), lock_("Arena pool lock", kArenaPoolLock), free_arenas_(nullptr), + low_4gb_(low_4gb) { + if (low_4gb) { + CHECK(!use_malloc) << "low4gb must use map implementation"; + } if (!use_malloc) { MemMap::Init(); } @@ -182,7 +185,8 @@ Arena* ArenaPool::AllocArena(size_t size) { } } if (ret == nullptr) { - ret = use_malloc_ ? static_cast<Arena*>(new MallocArena(size)) : new MemMapArena(size); + ret = use_malloc_ ? static_cast<Arena*>(new MallocArena(size)) : + new MemMapArena(size, low_4gb_); } ret->Reset(); return ret; @@ -229,6 +233,17 @@ size_t ArenaAllocator::BytesAllocated() const { return ArenaAllocatorStats::BytesAllocated(); } +size_t ArenaAllocator::BytesUsed() const { + size_t total = ptr_ - begin_; + if (arena_head_ != nullptr) { + for (Arena* cur_arena = arena_head_->next_; cur_arena != nullptr; + cur_arena = cur_arena->next_) { + total += cur_arena->GetBytesAllocated(); + } + } + return total; +} + ArenaAllocator::ArenaAllocator(ArenaPool* pool) : pool_(pool), begin_(nullptr), diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h index cc7b856..3a86b61 100644 --- a/runtime/base/arena_allocator.h +++ b/runtime/base/arena_allocator.h @@ -165,7 +165,7 @@ class MallocArena FINAL : public Arena { class MemMapArena FINAL : public Arena { public: - explicit MemMapArena(size_t size = Arena::kDefaultSize); + explicit MemMapArena(size_t size, bool low_4gb); virtual ~MemMapArena() { } void Release() OVERRIDE; @@ -175,7 +175,7 @@ class MemMapArena FINAL : public Arena { class ArenaPool { public: - explicit ArenaPool(bool use_malloc = true); + explicit ArenaPool(bool use_malloc = true, bool low_4gb = false); ~ArenaPool(); Arena* AllocArena(size_t size) LOCKS_EXCLUDED(lock_); void FreeArenaChain(Arena* first) LOCKS_EXCLUDED(lock_); @@ -188,6 +188,7 @@ class ArenaPool { const bool use_malloc_; mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; Arena* free_arenas_ GUARDED_BY(lock_); + const bool low_4gb_; DISALLOW_COPY_AND_ASSIGN(ArenaPool); }; @@ -227,6 +228,9 @@ class ArenaAllocator : private DebugStackRefCounter, private ArenaAllocatorStats void ObtainNewArenaForAllocation(size_t allocation_size); size_t BytesAllocated() const; MemStats GetMemStats() const; + // The BytesUsed method sums up bytes allocated from arenas in arena_head_ and nodes. + // TODO: Change BytesAllocated to this behavior? + size_t BytesUsed() const; private: static constexpr size_t kAlignment = 8; diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h index af00834..6e4b96c 100644 --- a/runtime/base/mutex.h +++ b/runtime/base/mutex.h @@ -73,6 +73,7 @@ enum LockLevel { kRosAllocBulkFreeLock, kAllocSpaceLock, kBumpPointerSpaceBlockLock, + kArenaPoolLock, kDexFileMethodInlinerLock, kDexFileToMethodInlinerMapLock, kMarkSweepMarkStackLock, diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index 2b0167d..f94ebea 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -19,6 +19,7 @@ #include <sys/mman.h> #include <zlib.h> +#include "art_field-inl.h" #include "base/logging.h" #include "base/to_str.h" #include "class_linker.h" @@ -27,7 +28,6 @@ #include "gc/space/space.h" #include "java_vm_ext.h" #include "jni_internal.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -169,7 +169,7 @@ class ScopedCheck { return false; } - mirror::ArtField* f = CheckFieldID(soa, fid); + ArtField* f = CheckFieldID(soa, fid); if (f == nullptr) { return false; } @@ -248,7 +248,7 @@ class ScopedCheck { bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { mirror::Class* c = soa.Decode<mirror::Class*>(java_class); - mirror::ArtField* f = CheckFieldID(soa, fid); + ArtField* f = CheckFieldID(soa, fid); if (f == nullptr) { return false; } @@ -565,7 +565,7 @@ class ScopedCheck { if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) { return false; } - mirror::ArtField* field = soa.DecodeField(fid); + ArtField* field = soa.DecodeField(fid); DCHECK(field != nullptr); // Already checked by Check. if (is_static != field->IsStatic()) { AbortF("attempt to access %s field %s: %p", @@ -817,7 +817,7 @@ class ScopedCheck { } case 'f': { // jfieldID jfieldID fid = arg.f; - mirror::ArtField* f = soa.DecodeField(fid); + ArtField* f = soa.DecodeField(fid); *msg += PrettyField(f); if (!entry) { StringAppendF(msg, " (%p)", fid); @@ -986,14 +986,15 @@ class ScopedCheck { return true; } - mirror::ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid) + ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (fid == nullptr) { AbortF("jfieldID was NULL"); return nullptr; } - mirror::ArtField* f = soa.DecodeField(fid); - if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) { + ArtField* f = soa.DecodeField(fid); + // TODO: Better check here. + if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass())) { Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); AbortF("invalid jfieldID: %p", fid); return nullptr; diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 5198769..87d1c4c 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -17,10 +17,10 @@ #ifndef ART_RUNTIME_CLASS_LINKER_INL_H_ #define ART_RUNTIME_CLASS_LINKER_INL_H_ +#include "art_field.h" #include "class_linker.h" #include "gc_root-inl.h" #include "gc/heap-inl.h" -#include "mirror/art_field.h" #include "mirror/class_loader.h" #include "mirror/dex_cache-inl.h" #include "mirror/iftable.h" @@ -88,7 +88,7 @@ inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, return resolved_type; } -inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, mirror::ArtField* referrer) { +inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx, ArtField* referrer) { mirror::Class* declaring_class = referrer->GetDeclaringClass(); mirror::DexCache* dex_cache_ptr = declaring_class->GetDexCache(); mirror::Class* resolved_type = dex_cache_ptr->GetResolvedType(type_idx); @@ -133,15 +133,19 @@ inline mirror::ArtMethod* ClassLinker::ResolveMethod(Thread* self, uint32_t meth return resolved_method; } -inline mirror::ArtField* ClassLinker::GetResolvedField(uint32_t field_idx, - mirror::Class* field_declaring_class) { - return field_declaring_class->GetDexCache()->GetResolvedField(field_idx); +inline ArtField* ClassLinker::GetResolvedField(uint32_t field_idx, mirror::DexCache* dex_cache) { + return dex_cache->GetResolvedField(field_idx, image_pointer_size_); } -inline mirror::ArtField* ClassLinker::ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer, +inline ArtField* ClassLinker::GetResolvedField( + uint32_t field_idx, mirror::Class* field_declaring_class) { + return GetResolvedField(field_idx, field_declaring_class->GetDexCache()); +} + +inline ArtField* ClassLinker::ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer, bool is_static) { mirror::Class* declaring_class = referrer->GetDeclaringClass(); - mirror::ArtField* resolved_field = GetResolvedField(field_idx, declaring_class); + ArtField* resolved_field = GetResolvedField(field_idx, declaring_class); if (UNLIKELY(resolved_field == NULL)) { StackHandleScope<2> hs(Thread::Current()); Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache())); @@ -187,17 +191,6 @@ inline mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) ifcount * mirror::IfTable::kMax)); } -inline mirror::ObjectArray<mirror::ArtField>* ClassLinker::AllocArtFieldArray(Thread* self, - size_t length) { - gc::Heap* const heap = Runtime::Current()->GetHeap(); - // Can't have movable field arrays for mark compact since we need these arrays to always be valid - // so that we can do Object::VisitReferences in the case where the fields don't fit in the - // reference offsets word. - return mirror::ObjectArray<mirror::ArtField>::Alloc( - self, GetClassRoot(kJavaLangReflectArtFieldArrayClass), length, - kMoveFieldArrays ? heap->GetCurrentAllocator() : heap->GetCurrentNonMovingAllocator()); -} - inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(!class_roots_.IsNull()); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 12fa546..935c401 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -25,6 +25,7 @@ #include <utility> #include <vector> +#include "art_field-inl.h" #include "base/casts.h" #include "base/logging.h" #include "base/scoped_flock.h" @@ -46,11 +47,11 @@ #include "jit/jit.h" #include "jit/jit_code_cache.h" #include "leb128.h" +#include "linear_alloc.h" #include "oat.h" #include "oat_file.h" #include "oat_file_assistant.h" #include "object_lock.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class.h" #include "mirror/class-inl.h" @@ -77,6 +78,8 @@ namespace art { +static constexpr bool kSanityCheckObjects = kIsDebugBuild; + static void ThrowNoClassDefFoundError(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2))) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -186,7 +189,7 @@ static void AddFieldGap(uint32_t gap_start, uint32_t gap_end, FieldGaps* gaps) { template<int n> static void ShuffleForward(size_t* current_field_idx, MemberOffset* field_offset, - std::deque<mirror::ArtField*>* grouped_and_sorted_fields, + std::deque<ArtField*>* grouped_and_sorted_fields, FieldGaps* gaps) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(current_field_idx != nullptr); @@ -196,7 +199,7 @@ static void ShuffleForward(size_t* current_field_idx, DCHECK(IsPowerOfTwo(n)); while (!grouped_and_sorted_fields->empty()) { - mirror::ArtField* field = grouped_and_sorted_fields->front(); + ArtField* field = grouped_and_sorted_fields->front(); Primitive::Type type = field->GetTypeAsPrimitiveType(); if (Primitive::ComponentSize(type) < n) { break; @@ -357,6 +360,13 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b mirror::IntArray::SetArrayClass(int_array_class.Get()); SetClassRoot(kIntArrayClass, int_array_class.Get()); + // Create long array type for AllocDexCache (done in AppendToBootClassPath). + Handle<mirror::Class> long_array_class(hs.NewHandle( + AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize()))); + long_array_class->SetComponentType(GetClassRoot(kPrimitiveLong)); + mirror::LongArray::SetArrayClass(long_array_class.Get()); + SetClassRoot(kLongArrayClass, long_array_class.Get()); + // now that these are registered, we can use AllocClass() and AllocObjectArray // Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache. @@ -366,15 +376,8 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b java_lang_DexCache->SetObjectSize(mirror::DexCache::InstanceSize()); mirror::Class::SetStatus(java_lang_DexCache, mirror::Class::kStatusResolved, self); - // Constructor, Field, Method, and AbstractMethod are necessary so + // Constructor, Method, and AbstractMethod are necessary so // that FindClass can link members. - Handle<mirror::Class> java_lang_reflect_ArtField(hs.NewHandle( - AllocClass(self, java_lang_Class.Get(), mirror::ArtField::ClassSize()))); - CHECK(java_lang_reflect_ArtField.Get() != nullptr); - java_lang_reflect_ArtField->SetObjectSize(mirror::ArtField::InstanceSize()); - SetClassRoot(kJavaLangReflectArtField, java_lang_reflect_ArtField.Get()); - mirror::Class::SetStatus(java_lang_reflect_ArtField, mirror::Class::kStatusResolved, self); - mirror::ArtField::SetClass(java_lang_reflect_ArtField.Get()); Handle<mirror::Class> java_lang_reflect_ArtMethod(hs.NewHandle( AllocClass(self, java_lang_Class.Get(), mirror::ArtMethod::ClassSize()))); @@ -398,12 +401,6 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b object_array_art_method->SetComponentType(java_lang_reflect_ArtMethod.Get()); SetClassRoot(kJavaLangReflectArtMethodArrayClass, object_array_art_method.Get()); - Handle<mirror::Class> object_array_art_field(hs.NewHandle( - AllocClass(self, java_lang_Class.Get(), - mirror::ObjectArray<mirror::ArtField>::ClassSize()))); - object_array_art_field->SetComponentType(java_lang_reflect_ArtField.Get()); - SetClassRoot(kJavaLangReflectArtFieldArrayClass, object_array_art_field.Get()); - // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses // these roots. @@ -471,8 +468,8 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b mirror::Class* found_int_array_class = FindSystemClass(self, "[I"); CHECK_EQ(int_array_class.Get(), found_int_array_class); - SetClassRoot(kLongArrayClass, FindSystemClass(self, "[J")); - mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); + mirror::Class* found_long_array_class = FindSystemClass(self, "[J"); + CHECK_EQ(long_array_class.Get(), found_long_array_class); SetClassRoot(kFloatArrayClass, FindSystemClass(self, "[F")); mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); @@ -513,10 +510,6 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b mirror::Class* Art_method_class = FindSystemClass(self, "Ljava/lang/reflect/ArtMethod;"); CHECK_EQ(java_lang_reflect_ArtMethod.Get(), Art_method_class); - mirror::Class::SetStatus(java_lang_reflect_ArtField, mirror::Class::kStatusNotReady, self); - mirror::Class* Art_field_class = FindSystemClass(self, "Ljava/lang/reflect/ArtField;"); - CHECK_EQ(java_lang_reflect_ArtField.Get(), Art_field_class); - mirror::Class* String_array_class = FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass)); CHECK_EQ(object_array_string.Get(), String_array_class); @@ -525,10 +518,6 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b FindSystemClass(self, GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass)); CHECK_EQ(object_array_art_method.Get(), Art_method_array_class); - mirror::Class* Art_field_array_class = - FindSystemClass(self, GetClassRootDescriptor(kJavaLangReflectArtFieldArrayClass)); - CHECK_EQ(object_array_art_field.Get(), Art_field_array_class); - // End of special init trickery, subsequent classes may be loaded via FindSystemClass. // Create java.lang.reflect.Proxy root. @@ -624,23 +613,23 @@ void ClassLinker::FinishInit(Thread* self) { mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"); - mirror::ArtField* pendingNext = java_lang_ref_Reference->GetInstanceField(0); + ArtField* pendingNext = java_lang_ref_Reference->GetInstanceField(0); CHECK_STREQ(pendingNext->GetName(), "pendingNext"); CHECK_STREQ(pendingNext->GetTypeDescriptor(), "Ljava/lang/ref/Reference;"); - mirror::ArtField* queue = java_lang_ref_Reference->GetInstanceField(1); + ArtField* queue = java_lang_ref_Reference->GetInstanceField(1); CHECK_STREQ(queue->GetName(), "queue"); CHECK_STREQ(queue->GetTypeDescriptor(), "Ljava/lang/ref/ReferenceQueue;"); - mirror::ArtField* queueNext = java_lang_ref_Reference->GetInstanceField(2); + ArtField* queueNext = java_lang_ref_Reference->GetInstanceField(2); CHECK_STREQ(queueNext->GetName(), "queueNext"); CHECK_STREQ(queueNext->GetTypeDescriptor(), "Ljava/lang/ref/Reference;"); - mirror::ArtField* referent = java_lang_ref_Reference->GetInstanceField(3); + ArtField* referent = java_lang_ref_Reference->GetInstanceField(3); CHECK_STREQ(referent->GetName(), "referent"); CHECK_STREQ(referent->GetTypeDescriptor(), "Ljava/lang/Object;"); - mirror::ArtField* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2); + ArtField* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2); CHECK_STREQ(zombie->GetName(), "zombie"); CHECK_STREQ(zombie->GetTypeDescriptor(), "Ljava/lang/Object;"); @@ -802,6 +791,23 @@ void ClassLinker::InitFromImageInterpretOnlyCallback(mirror::Object* obj, void* } } +void SanityCheckObjectsCallback(mirror::Object* obj, void* arg ATTRIBUTE_UNUSED) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(obj != nullptr); + CHECK(obj->GetClass() != nullptr) << "Null class " << obj; + CHECK(obj->GetClass()->GetClass() != nullptr) << "Null class class " << obj; + if (obj->IsClass()) { + auto klass = obj->AsClass(); + ArtField* fields[2] = { klass->GetSFields(), klass->GetIFields() }; + size_t num_fields[2] = { klass->NumStaticFields(), klass->NumInstanceFields() }; + for (size_t i = 0; i < 2; ++i) { + for (size_t j = 0; j < num_fields[i]; ++j) { + CHECK_EQ(fields[i][j].GetDeclaringClass(), klass); + } + } + } +} + void ClassLinker::InitFromImage() { VLOG(startup) << "ClassLinker::InitFromImage entering"; CHECK(!init_done_); @@ -882,6 +888,18 @@ void ClassLinker::InitFromImage() { if (!runtime->IsAotCompiler() && runtime->GetInstrumentation()->InterpretOnly()) { heap->VisitObjects(InitFromImageInterpretOnlyCallback, this); } + if (kSanityCheckObjects) { + for (int32_t i = 0; i < dex_caches->GetLength(); i++) { + auto* dex_cache = dex_caches->Get(i); + for (size_t j = 0; j < dex_cache->NumResolvedFields(); ++j) { + auto* field = dex_cache->GetResolvedField(j, image_pointer_size_); + if (field != nullptr) { + CHECK(field->GetDeclaringClass()->GetClass() != nullptr); + } + } + } + heap->VisitObjects(SanityCheckObjectsCallback, nullptr); + } // reinit class_roots_ mirror::Class::SetClassClass(class_roots->Get(kJavaLangClass)); @@ -894,7 +912,6 @@ void ClassLinker::InitFromImage() { mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField)); mirror::Field::SetArrayClass(GetClassRoot(kJavaLangReflectFieldArrayClass)); mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference)); - mirror::ArtField::SetClass(GetClassRoot(kJavaLangReflectArtField)); mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); mirror::CharArray::SetArrayClass(GetClassRoot(kCharArrayClass)); @@ -913,18 +930,22 @@ void ClassLinker::InitFromImage() { void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) { WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); + BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor( + visitor, RootInfo(kRootStickyClass)); if ((flags & kVisitRootFlagAllRoots) != 0) { - BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor( - visitor, RootInfo(kRootStickyClass)); for (GcRoot<mirror::Class>& root : class_table_) { buffered_visitor.VisitRoot(root); + root.Read()->VisitFieldRoots(buffered_visitor); } + // PreZygote classes can't move so we won't need to update fields' declaring classes. for (GcRoot<mirror::Class>& root : pre_zygote_class_table_) { buffered_visitor.VisitRoot(root); + root.Read()->VisitFieldRoots(buffered_visitor); } } else if ((flags & kVisitRootFlagNewRoots) != 0) { for (auto& root : new_class_roots_) { mirror::Class* old_ref = root.Read<kWithoutReadBarrier>(); + old_ref->VisitFieldRoots(buffered_visitor); root.VisitRoot(visitor, RootInfo(kRootStickyClass)); mirror::Class* new_ref = root.Read<kWithoutReadBarrier>(); if (UNLIKELY(new_ref != old_ref)) { @@ -937,6 +958,7 @@ void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) { } } } + buffered_visitor.Flush(); // Flush before clearing new_class_roots_. if ((flags & kVisitRootFlagClearRootLog) != 0) { new_class_roots_.clear(); } @@ -1077,7 +1099,6 @@ ClassLinker::~ClassLinker() { mirror::Class::ResetClass(); mirror::String::ResetClass(); mirror::Reference::ResetClass(); - mirror::ArtField::ResetClass(); mirror::ArtMethod::ResetClass(); mirror::Field::ResetClass(); mirror::Field::ResetArrayClass(); @@ -1095,7 +1116,7 @@ ClassLinker::~ClassLinker() { } mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) { - gc::Heap* heap = Runtime::Current()->GetHeap(); + gc::Heap* const heap = Runtime::Current()->GetHeap(); StackHandleScope<16> hs(self); Handle<mirror::Class> dex_cache_class(hs.NewHandle(GetClassRoot(kJavaLangDexCache))); Handle<mirror::DexCache> dex_cache( @@ -1125,8 +1146,12 @@ mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_fi if (methods.Get() == nullptr) { return nullptr; } - Handle<mirror::ObjectArray<mirror::ArtField>> - fields(hs.NewHandle(AllocArtFieldArray(self, dex_file.NumFieldIds()))); + Handle<mirror::Array> fields; + if (image_pointer_size_ == 8) { + fields = hs.NewHandle<mirror::Array>(mirror::LongArray::Alloc(self, dex_file.NumFieldIds())); + } else { + fields = hs.NewHandle<mirror::Array>(mirror::IntArray::Alloc(self, dex_file.NumFieldIds())); + } if (fields.Get() == nullptr) { return nullptr; } @@ -1154,11 +1179,6 @@ mirror::Class* ClassLinker::AllocClass(Thread* self, uint32_t class_size) { return AllocClass(self, GetClassRoot(kJavaLangClass), class_size); } -mirror::ArtField* ClassLinker::AllocArtField(Thread* self) { - return down_cast<mirror::ArtField*>( - GetClassRoot(kJavaLangReflectArtField)->AllocNonMovableObject(self)); -} - mirror::ArtMethod* ClassLinker::AllocArtMethod(Thread* self) { return down_cast<mirror::ArtMethod*>( GetClassRoot(kJavaLangReflectArtMethod)->AllocNonMovableObject(self)); @@ -1273,16 +1293,13 @@ mirror::Class* ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlready StackHandleScope<3> hs(self); // The class loader is a PathClassLoader which inherits from BaseDexClassLoader. // We need to get the DexPathList and loop through it. - Handle<mirror::ArtField> cookie_field = - hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie)); - Handle<mirror::ArtField> dex_file_field = - hs.NewHandle( - soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile)); + ArtField* const cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); + ArtField* const dex_file_field = + soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); mirror::Object* dex_path_list = soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)-> GetObject(class_loader.Get()); - if (dex_path_list != nullptr && dex_file_field.Get() != nullptr && - cookie_field.Get() != nullptr) { + if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. mirror::Object* dex_elements_obj = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> @@ -1433,8 +1450,6 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, si klass.Assign(GetClassRoot(kJavaLangRefReference)); } else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) { klass.Assign(GetClassRoot(kJavaLangDexCache)); - } else if (strcmp(descriptor, "Ljava/lang/reflect/ArtField;") == 0) { - klass.Assign(GetClassRoot(kJavaLangReflectArtField)); } else if (strcmp(descriptor, "Ljava/lang/reflect/ArtMethod;") == 0) { klass.Assign(GetClassRoot(kJavaLangReflectArtMethod)); } @@ -1452,16 +1467,10 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, si return nullptr; } klass->SetDexCache(FindDexCache(dex_file)); - LoadClass(self, dex_file, dex_class_def, klass, class_loader.Get()); + + SetupClass(dex_file, dex_class_def, klass, class_loader.Get()); + ObjectLock<mirror::Class> lock(self, klass); - if (self->IsExceptionPending()) { - // An exception occured during load, set status to erroneous while holding klass' lock in case - // notification is necessary. - if (!klass->IsErroneous()) { - mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); - } - return nullptr; - } klass->SetClinitThreadId(self->GetTid()); // Add the newly loaded class to the loaded classes table. @@ -1472,6 +1481,20 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, si return EnsureResolved(self, descriptor, existing); } + // Load the fields and other things after we are inserted in the table. This is so that we don't + // end up allocating unfree-able linear alloc resources and then lose the race condition. The + // other reason is that the field roots are only visited from the class table. So we need to be + // inserted before we allocate / fill in these fields. + LoadClass(self, dex_file, dex_class_def, klass); + if (self->IsExceptionPending()) { + // An exception occured during load, set status to erroneous while holding klass' lock in case + // notification is necessary. + if (!klass->IsErroneous()) { + mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); + } + return nullptr; + } + // Finish loading (if necessary) by finding parents CHECK(!klass->IsLoaded()); if (!LoadSuperAndInterfaces(klass, dex_file)) { @@ -1845,12 +1868,8 @@ void ClassLinker::LinkCode(Handle<mirror::ArtMethod> method, } } - - -void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file, - const DexFile::ClassDef& dex_class_def, - Handle<mirror::Class> klass, - mirror::ClassLoader* class_loader) { +void ClassLinker::SetupClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, + Handle<mirror::Class> klass, mirror::ClassLoader* class_loader) { CHECK(klass.Get() != nullptr); CHECK(klass->GetDexCache() != nullptr); CHECK_EQ(mirror::Class::kStatusNotReady, klass->GetStatus()); @@ -1868,13 +1887,15 @@ void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file, klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def)); klass->SetDexTypeIndex(dex_class_def.class_idx_); CHECK(klass->GetDexCacheStrings() != nullptr); +} +void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file, + const DexFile::ClassDef& dex_class_def, + Handle<mirror::Class> klass) { const uint8_t* class_data = dex_file.GetClassData(dex_class_def); if (class_data == nullptr) { return; // no fields or methods - for example a marker interface } - - bool has_oat_class = false; if (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler()) { OatFile::OatClass oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(), @@ -1888,51 +1909,41 @@ void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file, } } +ArtField* ClassLinker::AllocArtFieldArray(Thread* self, size_t length) { + auto* const la = Runtime::Current()->GetLinearAlloc(); + auto* ptr = reinterpret_cast<ArtField*>(la->AllocArray<ArtField>(self, length)); + CHECK(ptr!= nullptr); + std::uninitialized_fill_n(ptr, length, ArtField()); + return ptr; +} + void ClassLinker::LoadClassMembers(Thread* self, const DexFile& dex_file, const uint8_t* class_data, Handle<mirror::Class> klass, const OatFile::OatClass* oat_class) { - // Load fields. + // Load static fields. ClassDataItemIterator it(dex_file, class_data); - if (it.NumStaticFields() != 0) { - mirror::ObjectArray<mirror::ArtField>* statics = AllocArtFieldArray(self, it.NumStaticFields()); - if (UNLIKELY(statics == nullptr)) { - CHECK(self->IsExceptionPending()); // OOME. - return; - } - klass->SetSFields(statics); - } - if (it.NumInstanceFields() != 0) { - mirror::ObjectArray<mirror::ArtField>* fields = - AllocArtFieldArray(self, it.NumInstanceFields()); - if (UNLIKELY(fields == nullptr)) { - CHECK(self->IsExceptionPending()); // OOME. - return; - } - klass->SetIFields(fields); - } + const size_t num_sfields = it.NumStaticFields(); + ArtField* sfields = num_sfields != 0 ? AllocArtFieldArray(self, num_sfields) : nullptr; for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) { + CHECK_LT(i, num_sfields); self->AllowThreadSuspension(); - StackHandleScope<1> hs(self); - Handle<mirror::ArtField> sfield(hs.NewHandle(AllocArtField(self))); - if (UNLIKELY(sfield.Get() == nullptr)) { - CHECK(self->IsExceptionPending()); // OOME. - return; - } - klass->SetStaticField(i, sfield.Get()); - LoadField(dex_file, it, klass, sfield); - } + LoadField(it, klass, &sfields[i]); + } + klass->SetSFields(sfields); + klass->SetNumStaticFields(num_sfields); + DCHECK_EQ(klass->NumStaticFields(), num_sfields); + // Load instance fields. + const size_t num_ifields = it.NumInstanceFields(); + ArtField* ifields = num_ifields != 0 ? AllocArtFieldArray(self, num_ifields) : nullptr; for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) { + CHECK_LT(i, num_ifields); self->AllowThreadSuspension(); - StackHandleScope<1> hs(self); - Handle<mirror::ArtField> ifield(hs.NewHandle(AllocArtField(self))); - if (UNLIKELY(ifield.Get() == nullptr)) { - CHECK(self->IsExceptionPending()); // OOME. - return; - } - klass->SetInstanceField(i, ifield.Get()); - LoadField(dex_file, it, klass, ifield); + LoadField(it, klass, &ifields[i]); } + klass->SetIFields(ifields); + klass->SetNumInstanceFields(num_ifields); + DCHECK_EQ(klass->NumInstanceFields(), num_ifields); // Load methods. if (it.NumDirectMethods() != 0) { @@ -1995,10 +2006,9 @@ void ClassLinker::LoadClassMembers(Thread* self, const DexFile& dex_file, DCHECK(!it.HasNext()); } -void ClassLinker::LoadField(const DexFile& /*dex_file*/, const ClassDataItemIterator& it, - Handle<mirror::Class> klass, - Handle<mirror::ArtField> dst) { - uint32_t field_idx = it.GetMemberIndex(); +void ClassLinker::LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, + ArtField* dst) { + const uint32_t field_idx = it.GetMemberIndex(); dst->SetDexFieldIndex(field_idx); dst->SetDeclaringClass(klass.Get()); dst->SetAccessFlags(it.GetFieldAccessFlags()); @@ -2282,13 +2292,12 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto } else if (strcmp(descriptor, GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass)) == 0) { new_class.Assign(GetClassRoot(kJavaLangReflectArtMethodArrayClass)); - } else if (strcmp(descriptor, - GetClassRootDescriptor(kJavaLangReflectArtFieldArrayClass)) == 0) { - new_class.Assign(GetClassRoot(kJavaLangReflectArtFieldArrayClass)); } else if (strcmp(descriptor, "[C") == 0) { new_class.Assign(GetClassRoot(kCharArrayClass)); } else if (strcmp(descriptor, "[I") == 0) { new_class.Assign(GetClassRoot(kIntArrayClass)); + } else if (strcmp(descriptor, "[J") == 0) { + new_class.Assign(GetClassRoot(kLongArrayClass)); } } if (new_class.Get() == nullptr) { @@ -2919,32 +2928,20 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, self); // Instance fields are inherited, but we add a couple of static fields... - { - mirror::ObjectArray<mirror::ArtField>* sfields = AllocArtFieldArray(self, 2); - if (UNLIKELY(sfields == nullptr)) { - CHECK(self->IsExceptionPending()); // OOME. - return nullptr; - } - klass->SetSFields(sfields); - } + const size_t num_fields = 2; + ArtField* sfields = AllocArtFieldArray(self, num_fields); + klass->SetSFields(sfields); + klass->SetNumStaticFields(num_fields); + // 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by // our proxy, so Class.getInterfaces doesn't return the flattened set. - Handle<mirror::ArtField> interfaces_sfield(hs.NewHandle(AllocArtField(self))); - if (UNLIKELY(interfaces_sfield.Get() == nullptr)) { - CHECK(self->IsExceptionPending()); // OOME. - return nullptr; - } - klass->SetStaticField(0, interfaces_sfield.Get()); + ArtField* interfaces_sfield = &sfields[0]; interfaces_sfield->SetDexFieldIndex(0); interfaces_sfield->SetDeclaringClass(klass.Get()); interfaces_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal); + // 2. Create a static field 'throws' that holds exceptions thrown by our methods. - Handle<mirror::ArtField> throws_sfield(hs.NewHandle(AllocArtField(self))); - if (UNLIKELY(throws_sfield.Get() == nullptr)) { - CHECK(self->IsExceptionPending()); // OOME. - return nullptr; - } - klass->SetStaticField(1, throws_sfield.Get()); + ArtField* throws_sfield = &sfields[1]; throws_sfield->SetDexFieldIndex(1); throws_sfield->SetDeclaringClass(klass.Get()); throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal); @@ -3332,11 +3329,11 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass, // Eagerly fill in static fields so that the we don't have to do as many expensive // Class::FindStaticField in ResolveField. for (size_t i = 0; i < num_static_fields; ++i) { - mirror::ArtField* field = klass->GetStaticField(i); + ArtField* field = klass->GetStaticField(i); const uint32_t field_idx = field->GetDexFieldIndex(); - mirror::ArtField* resolved_field = dex_cache->GetResolvedField(field_idx); + ArtField* resolved_field = dex_cache->GetResolvedField(field_idx, image_pointer_size_); if (resolved_field == nullptr) { - dex_cache->SetResolvedField(field_idx, field); + dex_cache->SetResolvedField(field_idx, field, image_pointer_size_); } else { DCHECK_EQ(field, resolved_field); } @@ -3350,9 +3347,8 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass, DCHECK(field_it.HasNextStaticField()); CHECK(can_init_statics); for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) { - StackHandleScope<1> hs2(self); - Handle<mirror::ArtField> field(hs2.NewHandle( - ResolveField(dex_file, field_it.GetMemberIndex(), dex_cache, class_loader, true))); + ArtField* field = ResolveField( + dex_file, field_it.GetMemberIndex(), dex_cache, class_loader, true); if (Runtime::Current()->IsActiveTransaction()) { value_it.ReadValueToField<true>(field); } else { @@ -3586,21 +3582,17 @@ bool ClassLinker::EnsureInitialized(Thread* self, Handle<mirror::Class> c, bool } void ClassLinker::FixupTemporaryDeclaringClass(mirror::Class* temp_class, mirror::Class* new_class) { - mirror::ObjectArray<mirror::ArtField>* fields = new_class->GetIFields(); - if (fields != nullptr) { - for (int index = 0; index < fields->GetLength(); index ++) { - if (fields->Get(index)->GetDeclaringClass() == temp_class) { - fields->Get(index)->SetDeclaringClass(new_class); - } + ArtField* fields = new_class->GetIFields(); + for (size_t i = 0, count = new_class->NumInstanceFields(); i < count; i++) { + if (fields[i].GetDeclaringClass() == temp_class) { + fields[i].SetDeclaringClass(new_class); } } fields = new_class->GetSFields(); - if (fields != nullptr) { - for (int index = 0; index < fields->GetLength(); index ++) { - if (fields->Get(index)->GetDeclaringClass() == temp_class) { - fields->Get(index)->SetDeclaringClass(new_class); - } + for (size_t i = 0, count = new_class->NumStaticFields(); i < count; i++) { + if (fields[i].GetDeclaringClass() == temp_class) { + fields[i].SetDeclaringClass(new_class); } } @@ -4567,7 +4559,7 @@ struct LinkFieldsComparator { explicit LinkFieldsComparator() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { } // No thread safety analysis as will be called from STL. Checked lock held in constructor. - bool operator()(mirror::ArtField* field1, mirror::ArtField* field2) + bool operator()(ArtField* field1, ArtField* field2) NO_THREAD_SAFETY_ANALYSIS { // First come reference fields, then 64-bit, then 32-bit, and then 16-bit, then finally 8-bit. Primitive::Type type1 = field1->GetTypeAsPrimitiveType(); @@ -4600,11 +4592,8 @@ struct LinkFieldsComparator { bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_static, size_t* class_size) { self->AllowThreadSuspension(); - size_t num_fields = - is_static ? klass->NumStaticFields() : klass->NumInstanceFields(); - - mirror::ObjectArray<mirror::ArtField>* fields = - is_static ? klass->GetSFields() : klass->GetIFields(); + const size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields(); + ArtField* const fields = is_static ? klass->GetSFields() : klass->GetIFields(); // Initialize field_offset MemberOffset field_offset(0); @@ -4623,13 +4612,11 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ // we want a relatively stable order so that adding new fields // minimizes disruption of C++ version such as Class and Method. - std::deque<mirror::ArtField*> grouped_and_sorted_fields; + std::deque<ArtField*> grouped_and_sorted_fields; const char* old_no_suspend_cause = self->StartAssertNoThreadSuspension( "Naked ArtField references in deque"); for (size_t i = 0; i < num_fields; i++) { - mirror::ArtField* f = fields->Get(i); - CHECK(f != nullptr) << PrettyClass(klass.Get()); - grouped_and_sorted_fields.push_back(f); + grouped_and_sorted_fields.push_back(&fields[i]); } std::sort(grouped_and_sorted_fields.begin(), grouped_and_sorted_fields.end(), LinkFieldsComparator()); @@ -4640,7 +4627,7 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ FieldGaps gaps; for (; current_field < num_fields; current_field++) { - mirror::ArtField* field = grouped_and_sorted_fields.front(); + ArtField* field = grouped_and_sorted_fields.front(); Primitive::Type type = field->GetTypeAsPrimitiveType(); bool isPrimitive = type != Primitive::kPrimNot; if (isPrimitive) { @@ -4674,7 +4661,7 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ // We know there are no non-reference fields in the Reference classes, and we know // that 'referent' is alphabetically last, so this is easy... CHECK_EQ(num_reference_fields, num_fields) << PrettyClass(klass.Get()); - CHECK_STREQ(fields->Get(num_fields - 1)->GetName(), "referent") << PrettyClass(klass.Get()); + CHECK_STREQ(fields[num_fields - 1].GetName(), "referent") << PrettyClass(klass.Get()); --num_reference_fields; } @@ -4713,16 +4700,12 @@ bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_ sizeof(mirror::HeapReference<mirror::Object>)); MemberOffset current_ref_offset = start_ref_offset; for (size_t i = 0; i < num_fields; i++) { - mirror::ArtField* field = fields->Get(i); - if ((false)) { // enable to debug field layout - LOG(INFO) << "LinkFields: " << (is_static ? "static" : "instance") - << " class=" << PrettyClass(klass.Get()) - << " field=" << PrettyField(field) - << " offset=" - << field->GetField32(mirror::ArtField::OffsetOffset()); - } + ArtField* field = &fields[i]; + VLOG(class_linker) << "LinkFields: " << (is_static ? "static" : "instance") + << " class=" << PrettyClass(klass.Get()) << " field=" << PrettyField(field) << " offset=" + << field->GetOffset(); if (i != 0) { - mirror::ArtField* prev_field = fields->Get(i - 1u); + ArtField* const prev_field = &fields[i - 1]; // NOTE: The field names can be the same. This is not possible in the Java language // but it's valid Java/dex bytecode and for example proguard can generate such bytecode. CHECK_LE(strcmp(prev_field->GetName(), field->GetName()), 0); @@ -4994,12 +4977,11 @@ mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, uint32_t } } -mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t field_idx, - Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader, - bool is_static) { +ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t field_idx, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader, bool is_static) { DCHECK(dex_cache.Get() != nullptr); - mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx); + ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_); if (resolved != nullptr) { return resolved; } @@ -5032,16 +5014,15 @@ mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t fi return nullptr; } } - dex_cache->SetResolvedField(field_idx, resolved); + dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); return resolved; } -mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, - uint32_t field_idx, - Handle<mirror::DexCache> dex_cache, - Handle<mirror::ClassLoader> class_loader) { +ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, uint32_t field_idx, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader) { DCHECK(dex_cache.Get() != nullptr); - mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx); + ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_); if (resolved != nullptr) { return resolved; } @@ -5060,7 +5041,7 @@ mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_)); resolved = mirror::Class::FindField(self, klass, name, type); if (resolved != nullptr) { - dex_cache->SetResolvedField(field_idx, resolved); + dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); } else { ThrowNoSuchFieldError("", klass.Get(), type, name); } @@ -5190,12 +5171,10 @@ const char* ClassLinker::GetClassRootDescriptor(ClassRoot class_root) { "Ljava/lang/String;", "Ljava/lang/DexCache;", "Ljava/lang/ref/Reference;", - "Ljava/lang/reflect/ArtField;", "Ljava/lang/reflect/ArtMethod;", "Ljava/lang/reflect/Field;", "Ljava/lang/reflect/Proxy;", "[Ljava/lang/String;", - "[Ljava/lang/reflect/ArtField;", "[Ljava/lang/reflect/ArtMethod;", "[Ljava/lang/reflect/Field;", "Ljava/lang/ClassLoader;", @@ -5310,12 +5289,12 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi } // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex. - StackHandleScope<11> hs(self); + StackHandleScope<10> hs(self); - Handle<mirror::ArtField> h_dex_elements_field = - hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)); + ArtField* dex_elements_field = + soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements); - mirror::Class* dex_elements_class = h_dex_elements_field->GetType<true>(); + mirror::Class* dex_elements_class = dex_elements_field->GetType<true>(); DCHECK(dex_elements_class != nullptr); DCHECK(dex_elements_class->IsArrayClass()); Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements(hs.NewHandle( @@ -5323,14 +5302,12 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi Handle<mirror::Class> h_dex_element_class = hs.NewHandle(dex_elements_class->GetComponentType()); - Handle<mirror::ArtField> h_element_file_field = - hs.NewHandle( - soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile)); - DCHECK_EQ(h_dex_element_class.Get(), h_element_file_field->GetDeclaringClass()); + ArtField* element_file_field = + soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); + DCHECK_EQ(h_dex_element_class.Get(), element_file_field->GetDeclaringClass()); - Handle<mirror::ArtField> h_cookie_field = - hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie)); - DCHECK_EQ(h_cookie_field->GetDeclaringClass(), h_element_file_field->GetType<false>()); + ArtField* cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); + DCHECK_EQ(cookie_field->GetDeclaringClass(), element_file_field->GetType<false>()); // Fill the elements array. int32_t index = 0; @@ -5342,13 +5319,13 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi h_long_array->Set(0, reinterpret_cast<intptr_t>(dex_file)); Handle<mirror::Object> h_dex_file = hs2.NewHandle( - h_cookie_field->GetDeclaringClass()->AllocObject(self)); + cookie_field->GetDeclaringClass()->AllocObject(self)); DCHECK(h_dex_file.Get() != nullptr); - h_cookie_field->SetObject<false>(h_dex_file.Get(), h_long_array.Get()); + cookie_field->SetObject<false>(h_dex_file.Get(), h_long_array.Get()); Handle<mirror::Object> h_element = hs2.NewHandle(h_dex_element_class->AllocObject(self)); DCHECK(h_element.Get() != nullptr); - h_element_file_field->SetObject<false>(h_element.Get(), h_dex_file.Get()); + element_file_field->SetObject<false>(h_element.Get(), h_dex_file.Get()); h_dex_elements->Set(index, h_element.Get()); index++; @@ -5357,10 +5334,10 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi // Create DexPathList. Handle<mirror::Object> h_dex_path_list = hs.NewHandle( - h_dex_elements_field->GetDeclaringClass()->AllocObject(self)); + dex_elements_field->GetDeclaringClass()->AllocObject(self)); DCHECK(h_dex_path_list.Get() != nullptr); // Set elements. - h_dex_elements_field->SetObject<false>(h_dex_path_list.Get(), h_dex_elements.Get()); + dex_elements_field->SetObject<false>(h_dex_path_list.Get(), h_dex_elements.Get()); // Create PathClassLoader. Handle<mirror::Class> h_path_class_class = hs.NewHandle( @@ -5369,20 +5346,20 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi h_path_class_class->AllocObject(self)); DCHECK(h_path_class_loader.Get() != nullptr); // Set DexPathList. - Handle<mirror::ArtField> h_path_list_field = hs.NewHandle( - soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)); - DCHECK(h_path_list_field.Get() != nullptr); - h_path_list_field->SetObject<false>(h_path_class_loader.Get(), h_dex_path_list.Get()); + ArtField* path_list_field = + soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList); + DCHECK(path_list_field != nullptr); + path_list_field->SetObject<false>(h_path_class_loader.Get(), h_dex_path_list.Get()); // Make a pretend boot-classpath. // TODO: Should we scan the image? - Handle<mirror::ArtField> h_parent_field = hs.NewHandle( + ArtField* const parent_field = mirror::Class::FindField(self, hs.NewHandle(h_path_class_loader->GetClass()), "parent", - "Ljava/lang/ClassLoader;")); - DCHECK(h_parent_field.Get() != nullptr); + "Ljava/lang/ClassLoader;"); + DCHECK(parent_field!= nullptr); mirror::Object* boot_cl = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self); - h_parent_field->SetObject<false>(h_path_class_loader.Get(), boot_cl); + parent_field->SetObject<false>(h_path_class_loader.Get(), boot_cl); // Make it a global ref and return. ScopedLocalRef<jobject> local_ref( diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 577fec2..2427462 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -70,12 +70,10 @@ class ClassLinker { kJavaLangString, kJavaLangDexCache, kJavaLangRefReference, - kJavaLangReflectArtField, kJavaLangReflectArtMethod, kJavaLangReflectField, kJavaLangReflectProxy, kJavaLangStringArrayClass, - kJavaLangReflectArtFieldArrayClass, kJavaLangReflectArtMethodArrayClass, kJavaLangReflectFieldArrayClass, kJavaLangClassLoader, @@ -201,7 +199,7 @@ class ClassLinker { mirror::Class* ResolveType(uint16_t type_idx, mirror::ArtMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::Class* ResolveType(uint16_t type_idx, mirror::ArtField* referrer) + mirror::Class* ResolveType(uint16_t type_idx, ArtField* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a type with the given ID from the DexFile, storing the @@ -232,10 +230,11 @@ class ClassLinker { InvokeType type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ArtField* GetResolvedField(uint32_t field_idx, mirror::Class* field_declaring_class) + ArtField* GetResolvedField(uint32_t field_idx, mirror::Class* field_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ArtField* ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer, - bool is_static) + ArtField* GetResolvedField(uint32_t field_idx, mirror::DexCache* dex_cache) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ArtField* ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer, bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Resolve a field with a given ID from the DexFile, storing the @@ -243,7 +242,7 @@ class ClassLinker { // in ResolveType. What is unique is the is_static argument which is // used to determine if we are resolving a static or non-static // field. - mirror::ArtField* ResolveField(const DexFile& dex_file, + ArtField* ResolveField(const DexFile& dex_file, uint32_t field_idx, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, @@ -254,7 +253,7 @@ class ClassLinker { // result in DexCache. The ClassLinker and ClassLoader are used as // in ResolveType. No is_static argument is provided so that Java // field resolution semantics are followed. - mirror::ArtField* ResolveFieldJLS(const DexFile& dex_file, uint32_t field_idx, + ArtField* ResolveFieldJLS(const DexFile& dex_file, uint32_t field_idx, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -354,7 +353,7 @@ class ClassLinker { mirror::IfTable* AllocIfTable(Thread* self, size_t ifcount) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ObjectArray<mirror::ArtField>* AllocArtFieldArray(Thread* self, size_t length) + ArtField* AllocArtFieldArray(Thread* self, size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::ObjectArray<mirror::StackTraceElement>* AllocStackTraceElementArray(Thread* self, @@ -485,7 +484,6 @@ class ClassLinker { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::DexCache* AllocDexCache(Thread* self, const DexFile& dex_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ArtField* AllocArtField(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::Class* CreatePrimitiveClass(Thread* self, Primitive::Type type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -507,15 +505,21 @@ class ClassLinker { uint32_t SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def); + // Setup the classloader, class def index, type idx so that we can insert this class in the class + // table. + void SetupClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, + Handle<mirror::Class> klass, mirror::ClassLoader* class_loader) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void LoadClass(Thread* self, const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, - Handle<mirror::Class> klass, mirror::ClassLoader* class_loader) + Handle<mirror::Class> klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void LoadClassMembers(Thread* self, const DexFile& dex_file, const uint8_t* class_data, Handle<mirror::Class> klass, const OatFile::OatClass* oat_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it, - Handle<mirror::Class> klass, Handle<mirror::ArtField> dst) + void LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, + ArtField* dst) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::ArtMethod* LoadMethod(Thread* self, const DexFile& dex_file, diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 3f6c5a0..a31a785 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -19,14 +19,13 @@ #include <memory> #include <string> +#include "art_field-inl.h" #include "class_linker-inl.h" #include "common_runtime_test.h" #include "dex_file.h" #include "entrypoints/entrypoint_utils-inl.h" #include "gc/heap.h" #include "mirror/accessible_object.h" -#include "mirror/art_field-inl.h" -#include "mirror/art_method.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/dex_cache.h" @@ -173,10 +172,9 @@ class ClassLinkerTest : public CommonRuntimeTest { method->GetDeclaringClass()->GetDexCache()->GetResolvedTypes())); } - void AssertField(mirror::Class* klass, mirror::ArtField* field) + void AssertField(mirror::Class* klass, ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { EXPECT_TRUE(field != nullptr); - EXPECT_TRUE(field->GetClass() != nullptr); EXPECT_EQ(klass, field->GetDeclaringClass()); EXPECT_TRUE(field->GetName() != nullptr); EXPECT_TRUE(field->GetType<true>() != nullptr); @@ -262,30 +260,27 @@ class ClassLinkerTest : public CommonRuntimeTest { } for (size_t i = 0; i < klass->NumInstanceFields(); i++) { - mirror::ArtField* field = klass->GetInstanceField(i); + ArtField* field = klass->GetInstanceField(i); AssertField(klass.Get(), field); EXPECT_FALSE(field->IsStatic()); } for (size_t i = 0; i < klass->NumStaticFields(); i++) { - mirror::ArtField* field = klass->GetStaticField(i); + ArtField* field = klass->GetStaticField(i); AssertField(klass.Get(), field); EXPECT_TRUE(field->IsStatic()); } // Confirm that all instances field offsets are packed together at the start. EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields()); - StackHandleScope<1> hs(Thread::Current()); - MutableHandle<mirror::ArtField> fhandle = hs.NewHandle<mirror::ArtField>(nullptr); MemberOffset start_ref_offset = klass->GetFirstReferenceInstanceFieldOffset(); MemberOffset end_ref_offset(start_ref_offset.Uint32Value() + klass->NumReferenceInstanceFields() * sizeof(mirror::HeapReference<mirror::Object>)); MemberOffset current_ref_offset = start_ref_offset; for (size_t i = 0; i < klass->NumInstanceFields(); i++) { - mirror::ArtField* field = klass->GetInstanceField(i); - fhandle.Assign(field); - mirror::Class* field_type = fhandle->GetType<true>(); + ArtField* field = klass->GetInstanceField(i); + mirror::Class* field_type = field->GetType<true>(); ASSERT_TRUE(field_type != nullptr); if (!field->IsPrimitiveType()) { ASSERT_TRUE(!field_type->IsPrimitive()); @@ -293,7 +288,7 @@ class ClassLinkerTest : public CommonRuntimeTest { if (current_ref_offset.Uint32Value() == end_ref_offset.Uint32Value()) { // While Reference.referent is not primitive, the ClassLinker // treats it as such so that the garbage collector won't scan it. - EXPECT_EQ(PrettyField(fhandle.Get()), + EXPECT_EQ(PrettyField(field), "java.lang.Object java.lang.ref.Reference.referent"); } else { current_ref_offset = MemberOffset(current_ref_offset.Uint32Value() + @@ -425,7 +420,7 @@ struct CheckOffsets { } for (size_t i = 0; i < offsets.size(); i++) { - mirror::ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i); + ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i); StringPiece field_name(field->GetName()); if (field_name != offsets[i].java_name) { error = true; @@ -434,7 +429,7 @@ struct CheckOffsets { if (error) { for (size_t i = 0; i < offsets.size(); i++) { CheckOffset& offset = offsets[i]; - mirror::ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i); + ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i); StringPiece field_name(field->GetName()); if (field_name != offsets[i].java_name) { LOG(ERROR) << "JAVA FIELD ORDER MISMATCH NEXT LINE:"; @@ -448,7 +443,7 @@ struct CheckOffsets { for (size_t i = 0; i < offsets.size(); i++) { CheckOffset& offset = offsets[i]; - mirror::ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i); + ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i); if (field->GetOffset().Uint32Value() != offset.cpp_offset) { error = true; } @@ -456,7 +451,7 @@ struct CheckOffsets { if (error) { for (size_t i = 0; i < offsets.size(); i++) { CheckOffset& offset = offsets[i]; - mirror::ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i); + ArtField* field = is_static ? klass->GetStaticField(i) : klass->GetInstanceField(i); if (field->GetOffset().Uint32Value() != offset.cpp_offset) { LOG(ERROR) << "OFFSET MISMATCH NEXT LINE:"; } @@ -486,15 +481,6 @@ struct ObjectOffsets : public CheckOffsets<mirror::Object> { }; }; -struct ArtFieldOffsets : public CheckOffsets<mirror::ArtField> { - ArtFieldOffsets() : CheckOffsets<mirror::ArtField>(false, "Ljava/lang/reflect/ArtField;") { - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, access_flags_), "accessFlags")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, declaring_class_), "declaringClass")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, field_dex_idx_), "fieldDexIndex")); - offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtField, offset_), "offset")); - }; -}; - struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> { ArtMethodOffsets() : CheckOffsets<mirror::ArtMethod>(false, "Ljava/lang/reflect/ArtMethod;") { offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags")); @@ -522,8 +508,10 @@ struct ClassOffsets : public CheckOffsets<mirror::Class> { offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_instance_fields_), "numInstanceFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_), "numReferenceInstanceFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_), "numReferenceStaticFields")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_static_fields_), "numStaticFields")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, object_size_), "objectSize")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_), "primitiveType")); offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_), "referenceInstanceOffsets")); @@ -629,7 +617,6 @@ struct FieldOffsets : public CheckOffsets<mirror::Field> { TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) { ScopedObjectAccess soa(Thread::Current()); EXPECT_TRUE(ObjectOffsets().Check()); - EXPECT_TRUE(ArtFieldOffsets().Check()); EXPECT_TRUE(ArtMethodOffsets().Check()); EXPECT_TRUE(ClassOffsets().Check()); EXPECT_TRUE(StringOffsets().Check()); @@ -844,21 +831,21 @@ TEST_F(ClassLinkerTest, ValidateBoxedTypes) { NullHandle<mirror::ClassLoader> class_loader; mirror::Class* c; c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Boolean;", class_loader); - EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName()); + EXPECT_STREQ("value", c->GetIFields()[0].GetName()); c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Byte;", class_loader); - EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName()); + EXPECT_STREQ("value", c->GetIFields()[0].GetName()); c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Character;", class_loader); - EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName()); + EXPECT_STREQ("value", c->GetIFields()[0].GetName()); c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Double;", class_loader); - EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName()); + EXPECT_STREQ("value", c->GetIFields()[0].GetName()); c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Float;", class_loader); - EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName()); + EXPECT_STREQ("value", c->GetIFields()[0].GetName()); c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Integer;", class_loader); - EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName()); + EXPECT_STREQ("value", c->GetIFields()[0].GetName()); c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Long;", class_loader); - EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName()); + EXPECT_STREQ("value", c->GetIFields()[0].GetName()); c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Short;", class_loader); - EXPECT_STREQ("value", c->GetIFields()->Get(0)->GetName()); + EXPECT_STREQ("value", c->GetIFields()[0].GetName()); } TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) { @@ -892,49 +879,47 @@ TEST_F(ClassLinkerTest, StaticFields) { EXPECT_EQ(9U, statics->NumStaticFields()); - mirror::ArtField* s0 = mirror::Class::FindStaticField(soa.Self(), statics, "s0", "Z"); - std::string temp; - EXPECT_STREQ(s0->GetClass()->GetDescriptor(&temp), "Ljava/lang/reflect/ArtField;"); + ArtField* s0 = mirror::Class::FindStaticField(soa.Self(), statics, "s0", "Z"); EXPECT_EQ(s0->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean); EXPECT_EQ(true, s0->GetBoolean(statics.Get())); s0->SetBoolean<false>(statics.Get(), false); - mirror::ArtField* s1 = mirror::Class::FindStaticField(soa.Self(), statics, "s1", "B"); + ArtField* s1 = mirror::Class::FindStaticField(soa.Self(), statics, "s1", "B"); EXPECT_EQ(s1->GetTypeAsPrimitiveType(), Primitive::kPrimByte); EXPECT_EQ(5, s1->GetByte(statics.Get())); s1->SetByte<false>(statics.Get(), 6); - mirror::ArtField* s2 = mirror::Class::FindStaticField(soa.Self(), statics, "s2", "C"); + ArtField* s2 = mirror::Class::FindStaticField(soa.Self(), statics, "s2", "C"); EXPECT_EQ(s2->GetTypeAsPrimitiveType(), Primitive::kPrimChar); EXPECT_EQ('a', s2->GetChar(statics.Get())); s2->SetChar<false>(statics.Get(), 'b'); - mirror::ArtField* s3 = mirror::Class::FindStaticField(soa.Self(), statics, "s3", "S"); + ArtField* s3 = mirror::Class::FindStaticField(soa.Self(), statics, "s3", "S"); EXPECT_EQ(s3->GetTypeAsPrimitiveType(), Primitive::kPrimShort); EXPECT_EQ(-536, s3->GetShort(statics.Get())); s3->SetShort<false>(statics.Get(), -535); - mirror::ArtField* s4 = mirror::Class::FindStaticField(soa.Self(), statics, "s4", "I"); + ArtField* s4 = mirror::Class::FindStaticField(soa.Self(), statics, "s4", "I"); EXPECT_EQ(s4->GetTypeAsPrimitiveType(), Primitive::kPrimInt); EXPECT_EQ(2000000000, s4->GetInt(statics.Get())); s4->SetInt<false>(statics.Get(), 2000000001); - mirror::ArtField* s5 = mirror::Class::FindStaticField(soa.Self(), statics, "s5", "J"); + ArtField* s5 = mirror::Class::FindStaticField(soa.Self(), statics, "s5", "J"); EXPECT_EQ(s5->GetTypeAsPrimitiveType(), Primitive::kPrimLong); EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(statics.Get())); s5->SetLong<false>(statics.Get(), INT64_C(0x34567890abcdef12)); - mirror::ArtField* s6 = mirror::Class::FindStaticField(soa.Self(), statics, "s6", "F"); + ArtField* s6 = mirror::Class::FindStaticField(soa.Self(), statics, "s6", "F"); EXPECT_EQ(s6->GetTypeAsPrimitiveType(), Primitive::kPrimFloat); EXPECT_DOUBLE_EQ(0.5, s6->GetFloat(statics.Get())); s6->SetFloat<false>(statics.Get(), 0.75); - mirror::ArtField* s7 = mirror::Class::FindStaticField(soa.Self(), statics, "s7", "D"); + ArtField* s7 = mirror::Class::FindStaticField(soa.Self(), statics, "s7", "D"); EXPECT_EQ(s7->GetTypeAsPrimitiveType(), Primitive::kPrimDouble); EXPECT_DOUBLE_EQ(16777217.0, s7->GetDouble(statics.Get())); s7->SetDouble<false>(statics.Get(), 16777219); - mirror::ArtField* s8 = mirror::Class::FindStaticField(soa.Self(), statics, "s8", + ArtField* s8 = mirror::Class::FindStaticField(soa.Self(), statics, "s8", "Ljava/lang/String;"); EXPECT_EQ(s8->GetTypeAsPrimitiveType(), Primitive::kPrimNot); EXPECT_TRUE(s8->GetObject(statics.Get())->AsString()->Equals("android")); @@ -1006,13 +991,13 @@ TEST_F(ClassLinkerTest, Interfaces) { EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1)); EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2)); - mirror::ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo", + ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo", "Ljava/lang/String;"); - mirror::ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo", + ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo", "Ljava/lang/String;"); - mirror::ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo", + ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo", "Ljava/lang/String;"); - mirror::ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo", + ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo", "Ljava/lang/String;"); ASSERT_TRUE(Afoo != nullptr); EXPECT_EQ(Afoo, Bfoo); @@ -1110,9 +1095,6 @@ TEST_F(ClassLinkerTest, ValidatePredefinedClassSizes) { c = class_linker_->FindClass(soa.Self(), "Ljava/lang/DexCache;", class_loader); EXPECT_EQ(c->GetClassSize(), mirror::DexCache::ClassSize()); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/reflect/ArtField;", class_loader); - EXPECT_EQ(c->GetClassSize(), mirror::ArtField::ClassSize()); - c = class_linker_->FindClass(soa.Self(), "Ljava/lang/reflect/ArtMethod;", class_loader); EXPECT_EQ(c->GetClassSize(), mirror::ArtMethod::ClassSize()); } diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index d400010..60b7fa2 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -398,7 +398,7 @@ std::vector<const DexFile*> CommonRuntimeTest::GetDexFiles(jobject jclass_loader ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<4> hs(Thread::Current()); + StackHandleScope<2> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader = hs.NewHandle( soa.Decode<mirror::ClassLoader*>(jclass_loader)); @@ -409,16 +409,13 @@ std::vector<const DexFile*> CommonRuntimeTest::GetDexFiles(jobject jclass_loader // The class loader is a PathClassLoader which inherits from BaseDexClassLoader. // We need to get the DexPathList and loop through it. - Handle<mirror::ArtField> cookie_field = - hs.NewHandle(soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie)); - Handle<mirror::ArtField> dex_file_field = - hs.NewHandle( - soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile)); + ArtField* cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); + ArtField* dex_file_field = + soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); mirror::Object* dex_path_list = soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)-> GetObject(class_loader.Get()); - if (dex_path_list != nullptr && dex_file_field.Get() != nullptr && - cookie_field.Get() != nullptr) { + if (dex_path_list != nullptr && dex_file_field!= nullptr && cookie_field != nullptr) { // DexPathList has an array dexElements of Elements[] which each contain a dex file. mirror::Object* dex_elements_obj = soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc index 36de221..407746f 100644 --- a/runtime/common_throws.cc +++ b/runtime/common_throws.cc @@ -18,6 +18,7 @@ #include <sstream> +#include "art_field-inl.h" #include "base/logging.h" #include "class_linker-inl.h" #include "dex_file-inl.h" @@ -160,7 +161,7 @@ void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* a ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str()); } -void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) { +void ThrowIllegalAccessErrorField(mirror::Class* referrer, ArtField* accessed) { std::ostringstream msg; msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '" << PrettyDescriptor(referrer) << "'"; @@ -168,7 +169,7 @@ void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* acc } void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer, - mirror::ArtField* accessed) { + ArtField* accessed) { std::ostringstream msg; msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '" << PrettyMethod(referrer) << "'"; @@ -226,7 +227,7 @@ void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMetho msg.str().c_str()); } -void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static, +void ThrowIncompatibleClassChangeErrorField(ArtField* resolved_field, bool is_static, mirror::ArtMethod* referrer) { std::ostringstream msg; msg << "Expected '" << PrettyField(resolved_field) << "' to be a " @@ -314,7 +315,7 @@ void ThrowNoSuchMethodError(uint32_t method_idx) { // NullPointerException -void ThrowNullPointerExceptionForFieldAccess(mirror::ArtField* field, bool is_read) { +void ThrowNullPointerExceptionForFieldAccess(ArtField* field, bool is_read) { std::ostringstream msg; msg << "Attempt to " << (is_read ? "read from" : "write to") << " field '" << PrettyField(field, true) << "' on a null object reference"; @@ -394,7 +395,7 @@ void ThrowNullPointerExceptionFromDexPC() { case Instruction::IGET_BYTE: case Instruction::IGET_CHAR: case Instruction::IGET_SHORT: { - mirror::ArtField* field = + ArtField* field = Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false); ThrowNullPointerExceptionForFieldAccess(field, true /* read */); break; @@ -408,7 +409,7 @@ void ThrowNullPointerExceptionFromDexPC() { case Instruction::IGET_OBJECT_QUICK: { // Since we replaced the field index, we ask the verifier to tell us which // field is accessed at this location. - mirror::ArtField* field = + ArtField* field = verifier::MethodVerifier::FindAccessedFieldAtDexPc(method, throw_dex_pc); if (field != NULL) { // NPE with precise message. @@ -426,7 +427,7 @@ void ThrowNullPointerExceptionFromDexPC() { case Instruction::IPUT_BYTE: case Instruction::IPUT_CHAR: case Instruction::IPUT_SHORT: { - mirror::ArtField* field = + ArtField* field = Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false); ThrowNullPointerExceptionForFieldAccess(field, false /* write */); break; @@ -440,7 +441,7 @@ void ThrowNullPointerExceptionFromDexPC() { case Instruction::IPUT_OBJECT_QUICK: { // Since we replaced the field index, we ask the verifier to tell us which // field is accessed at this location. - mirror::ArtField* field = + ArtField* field = verifier::MethodVerifier::FindAccessedFieldAtDexPc(method, throw_dex_pc); if (field != NULL) { // NPE with precise message. diff --git a/runtime/common_throws.h b/runtime/common_throws.h index 9e749e3..df95cf9 100644 --- a/runtime/common_throws.h +++ b/runtime/common_throws.h @@ -22,11 +22,11 @@ namespace art { namespace mirror { - class ArtField; class ArtMethod; class Class; class Object; } // namespace mirror +class ArtField; class Signature; class StringPiece; @@ -81,10 +81,10 @@ void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirr void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR; -void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) +void ThrowIllegalAccessErrorField(mirror::Class* referrer, ArtField* accessed) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR; -void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer, mirror::ArtField* accessed) +void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer, ArtField* accessed) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR; void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) @@ -112,7 +112,7 @@ void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMetho mirror::ArtMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR; -void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static, +void ThrowIncompatibleClassChangeErrorField(ArtField* resolved_field, bool is_static, mirror::ArtMethod* referrer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR; @@ -160,7 +160,7 @@ void ThrowNoSuchMethodError(uint32_t method_idx) // NullPointerException -void ThrowNullPointerExceptionForFieldAccess(mirror::ArtField* field, +void ThrowNullPointerExceptionForFieldAccess(ArtField* field, bool is_read) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR; diff --git a/runtime/debugger.cc b/runtime/debugger.cc index a909a1a..12fe863 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -21,6 +21,7 @@ #include <set> #include "arch/context.h" +#include "art_field-inl.h" #include "class_linker.h" #include "class_linker-inl.h" #include "dex_file-inl.h" @@ -30,7 +31,6 @@ #include "gc/space/space-inl.h" #include "handle_scope.h" #include "jdwp/object_registry.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class.h" #include "mirror/class-inl.h" @@ -266,14 +266,14 @@ class DebugInstrumentationListener FINAL : public instrumentation::Instrumentati } void FieldRead(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method, - uint32_t dex_pc, mirror::ArtField* field) + uint32_t dex_pc, ArtField* field) OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { UNUSED(thread); Dbg::PostFieldAccessEvent(method, dex_pc, this_object, field); } void FieldWritten(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object, - mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field, + mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field, const JValue& field_value) OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Dbg::PostFieldModificationEvent(method, dex_pc, this_object, field, &field_value); @@ -1336,8 +1336,7 @@ JDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t return JDWP::ERR_NONE; } -JDWP::FieldId Dbg::ToFieldId(const mirror::ArtField* f) { - CHECK(!kMovingFields); +JDWP::FieldId Dbg::ToFieldId(const ArtField* f) { return static_cast<JDWP::FieldId>(reinterpret_cast<uintptr_t>(f)); } @@ -1347,10 +1346,9 @@ static JDWP::MethodId ToMethodId(const mirror::ArtMethod* m) return static_cast<JDWP::MethodId>(reinterpret_cast<uintptr_t>(m)); } -static mirror::ArtField* FromFieldId(JDWP::FieldId fid) +static ArtField* FromFieldId(JDWP::FieldId fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - CHECK(!kMovingFields); - return reinterpret_cast<mirror::ArtField*>(static_cast<uintptr_t>(fid)); + return reinterpret_cast<ArtField*>(static_cast<uintptr_t>(fid)); } static mirror::ArtMethod* FromMethodId(JDWP::MethodId mid) @@ -1387,8 +1385,8 @@ bool Dbg::MatchType(mirror::Class* event_class, JDWP::RefTypeId class_id) { } bool Dbg::MatchField(JDWP::RefTypeId expected_type_id, JDWP::FieldId expected_field_id, - mirror::ArtField* event_field) { - mirror::ArtField* expected_field = FromFieldId(expected_field_id); + ArtField* event_field) { + ArtField* expected_field = FromFieldId(expected_field_id); if (expected_field != event_field) { return false; } @@ -1423,7 +1421,7 @@ std::string Dbg::GetMethodName(JDWP::MethodId method_id) { } std::string Dbg::GetFieldName(JDWP::FieldId field_id) { - mirror::ArtField* f = FromFieldId(field_id); + ArtField* f = FromFieldId(field_id); if (f == nullptr) { return "NULL"; } @@ -1510,7 +1508,7 @@ JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_ge expandBufAdd4BE(pReply, instance_field_count + static_field_count); for (size_t i = 0; i < instance_field_count + static_field_count; ++i) { - mirror::ArtField* f = (i < instance_field_count) ? c->GetInstanceField(i) : c->GetStaticField(i - instance_field_count); + ArtField* f = (i < instance_field_count) ? c->GetInstanceField(i) : c->GetStaticField(i - instance_field_count); expandBufAddFieldId(pReply, ToFieldId(f)); expandBufAddUtf8String(pReply, f->GetName()); expandBufAddUtf8String(pReply, f->GetTypeDescriptor()); @@ -1680,7 +1678,7 @@ void Dbg::OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return void Dbg::OutputFieldValue(JDWP::FieldId field_id, const JValue* field_value, JDWP::ExpandBuf* pReply) { - mirror::ArtField* f = FromFieldId(field_id); + ArtField* f = FromFieldId(field_id); JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor()); OutputJValue(tag, field_value, pReply); } @@ -1723,7 +1721,7 @@ static JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::Obje if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } - mirror::ArtField* f = FromFieldId(field_id); + ArtField* f = FromFieldId(field_id); mirror::Class* receiver_class = c; if (receiver_class == nullptr && o != nullptr) { @@ -1785,7 +1783,7 @@ static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) { return JDWP::ERR_INVALID_OBJECT; } - mirror::ArtField* f = FromFieldId(field_id); + ArtField* f = FromFieldId(field_id); // The RI only enforces the static/non-static mismatch in one direction. // TODO: should we change the tests and check both? @@ -1822,11 +1820,10 @@ static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId if (v != nullptr) { mirror::Class* field_type; { - StackHandleScope<3> hs(Thread::Current()); + StackHandleScope<2> hs(Thread::Current()); HandleWrapper<mirror::Object> h_v(hs.NewHandleWrapper(&v)); - HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f)); HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o)); - field_type = h_f->GetType<true>(); + field_type = f->GetType<true>(); } if (!field_type->IsAssignableFrom(v->GetClass())) { return JDWP::ERR_INVALID_OBJECT; @@ -1904,7 +1901,7 @@ JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string* name) // We still need to report the zombie threads' names, so we can't just call Thread::GetThreadName. mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error); CHECK(thread_object != nullptr) << error; - mirror::ArtField* java_lang_Thread_name_field = + ArtField* java_lang_Thread_name_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); mirror::String* s = reinterpret_cast<mirror::String*>(java_lang_Thread_name_field->GetObject(thread_object)); @@ -1935,7 +1932,7 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* p } else if (error == JDWP::ERR_NONE) { mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread); CHECK(c != nullptr); - mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_group); + ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_group); CHECK(f != nullptr); mirror::Object* group = f->GetObject(thread_object); CHECK(group != nullptr); @@ -1976,7 +1973,7 @@ JDWP::JdwpError Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id, JDWP::Ex return error; } ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroupName"); - mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name); + ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name); CHECK(f != nullptr); mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group)); @@ -1995,7 +1992,7 @@ JDWP::JdwpError Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id, JDWP:: mirror::Object* parent; { ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroupParent"); - mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_parent); + ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_parent); CHECK(f != nullptr); parent = f->GetObject(thread_group); } @@ -2010,7 +2007,7 @@ static void GetChildThreadGroups(ScopedObjectAccessUnchecked& soa, mirror::Objec CHECK(thread_group != nullptr); // Get the ArrayList<ThreadGroup> "groups" out of this thread group... - mirror::ArtField* groups_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_groups); + ArtField* groups_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_groups); mirror::Object* groups_array_list = groups_field->GetObject(thread_group); { // The "groups" field is declared as a java.util.List: check it really is @@ -2022,8 +2019,8 @@ static void GetChildThreadGroups(ScopedObjectAccessUnchecked& soa, mirror::Objec } // Get the array and size out of the ArrayList<ThreadGroup>... - mirror::ArtField* array_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_array); - mirror::ArtField* size_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_size); + ArtField* array_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_array); + ArtField* size_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_size); mirror::ObjectArray<mirror::Object>* groups_array = array_field->GetObject(groups_array_list)->AsObjectArray<mirror::Object>(); const int32_t size = size_field->GetInt(groups_array_list); @@ -2069,7 +2066,7 @@ JDWP::JdwpError Dbg::GetThreadGroupChildren(JDWP::ObjectId thread_group_id, JDWP::ObjectId Dbg::GetSystemThreadGroupId() { ScopedObjectAccessUnchecked soa(Thread::Current()); - mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); + ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup); mirror::Object* group = f->GetObject(f->GetDeclaringClass()); return gRegistry->Add(group); } @@ -2166,7 +2163,7 @@ static bool IsInDesiredThreadGroup(ScopedObjectAccessUnchecked& soa, if (desired_thread_group == nullptr) { return true; } - mirror::ArtField* thread_group_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_group); + ArtField* thread_group_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_group); DCHECK(thread_group_field != nullptr); mirror::Object* group = thread_group_field->GetObject(peer); return (group == desired_thread_group); @@ -2771,7 +2768,7 @@ void Dbg::PostLocationEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* th } void Dbg::PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc, - mirror::Object* this_object, mirror::ArtField* f) { + mirror::Object* this_object, ArtField* f) { if (!IsDebuggerActive()) { return; } @@ -2784,7 +2781,7 @@ void Dbg::PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc, } void Dbg::PostFieldModificationEvent(mirror::ArtMethod* m, int dex_pc, - mirror::Object* this_object, mirror::ArtField* f, + mirror::Object* this_object, ArtField* f, const JValue* field_value) { if (!IsDebuggerActive()) { return; diff --git a/runtime/debugger.h b/runtime/debugger.h index dd7f9c5..c287121 100644 --- a/runtime/debugger.h +++ b/runtime/debugger.h @@ -37,13 +37,13 @@ namespace art { namespace mirror { -class ArtField; class ArtMethod; class Class; class Object; class Throwable; } // namespace mirror class AllocRecord; +class ArtField; class ObjectRegistry; class ScopedObjectAccessUnchecked; class StackVisitor; @@ -340,7 +340,7 @@ class Dbg { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static bool MatchField(JDWP::RefTypeId expected_type_id, JDWP::FieldId expected_field_id, - mirror::ArtField* event_field) + ArtField* event_field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static bool MatchInstance(JDWP::ObjectId expected_instance_id, mirror::Object* event_instance) @@ -525,10 +525,10 @@ class Dbg { kMethodExit = 0x08, }; static void PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object, - mirror::ArtField* f) + ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void PostFieldModificationEvent(mirror::ArtMethod* m, int dex_pc, - mirror::Object* this_object, mirror::ArtField* f, + mirror::Object* this_object, ArtField* f, const JValue* field_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void PostException(mirror::Throwable* exception) @@ -706,7 +706,7 @@ class Dbg { static JDWP::JdwpTypeTag GetTypeTag(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static JDWP::FieldId ToFieldId(const mirror::ArtField* f) + static JDWP::FieldId ToFieldId(const ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void SetJdwpLocation(JDWP::JdwpLocation* location, mirror::ArtMethod* m, uint32_t dex_pc) diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc index 8685d8e..03a47a3 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -27,6 +27,7 @@ #include <memory> #include <sstream> +#include "art_field-inl.h" #include "base/logging.h" #include "base/stringprintf.h" #include "class_linker.h" @@ -34,7 +35,6 @@ #include "dex_file_verifier.h" #include "globals.h" #include "leb128.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/string.h" #include "os.h" @@ -1210,7 +1210,7 @@ void EncodedStaticFieldValueIterator::Next() { } template<bool kTransactionActive> -void EncodedStaticFieldValueIterator::ReadValueToField(Handle<mirror::ArtField> field) const { +void EncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const { switch (type_) { case kBoolean: field->SetBoolean<kTransactionActive>(field->GetDeclaringClass(), jval_.z); break; case kByte: field->SetByte<kTransactionActive>(field->GetDeclaringClass(), jval_.b); break; @@ -1222,13 +1222,11 @@ void EncodedStaticFieldValueIterator::ReadValueToField(Handle<mirror::ArtField> case kDouble: field->SetDouble<kTransactionActive>(field->GetDeclaringClass(), jval_.d); break; case kNull: field->SetObject<kTransactionActive>(field->GetDeclaringClass(), NULL); break; case kString: { - CHECK(!kMovingFields); mirror::String* resolved = linker_->ResolveString(dex_file_, jval_.i, *dex_cache_); field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved); break; } case kType: { - CHECK(!kMovingFields); mirror::Class* resolved = linker_->ResolveType(dex_file_, jval_.i, *dex_cache_, *class_loader_); field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved); @@ -1237,8 +1235,8 @@ void EncodedStaticFieldValueIterator::ReadValueToField(Handle<mirror::ArtField> default: UNIMPLEMENTED(FATAL) << ": type " << type_; } } -template void EncodedStaticFieldValueIterator::ReadValueToField<true>(Handle<mirror::ArtField> field) const; -template void EncodedStaticFieldValueIterator::ReadValueToField<false>(Handle<mirror::ArtField> field) const; +template void EncodedStaticFieldValueIterator::ReadValueToField<true>(ArtField* field) const; +template void EncodedStaticFieldValueIterator::ReadValueToField<false>(ArtField* field) const; CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address) { handler_.address_ = -1; diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 8e2d6c2..5bdd9b6 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -37,11 +37,11 @@ namespace art { // TODO: remove dependencies on mirror classes, primarily by moving // EncodedStaticFieldValueIterator to its own file. namespace mirror { - class ArtField; class ArtMethod; class ClassLoader; class DexCache; } // namespace mirror +class ArtField; class ClassLinker; class MemMap; class OatDexFile; @@ -1298,7 +1298,7 @@ class EncodedStaticFieldValueIterator { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); template<bool kTransactionActive> - void ReadValueToField(Handle<mirror::ArtField> field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void ReadValueToField(ArtField* field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool HasNext() const { return pos_ < array_size_; } diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 8a13d34..cbfba12 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -252,7 +252,7 @@ inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass, } template<FindFieldType type, bool access_check> -inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer, +inline ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer, Thread* self, size_t expected_size) { bool is_primitive; bool is_set; @@ -269,7 +269,7 @@ inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod default: is_primitive = true; is_set = true; is_static = true; break; } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - mirror::ArtField* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static); + ArtField* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static); if (UNLIKELY(resolved_field == nullptr)) { DCHECK(self->IsExceptionPending()); // Throw exception and unwind. return nullptr; // Failure. @@ -324,7 +324,7 @@ inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod // Explicit template declarations of FindFieldFromCode for all field access types. #define EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \ template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \ -mirror::ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \ +ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \ mirror::ArtMethod* referrer, \ Thread* self, size_t expected_size) \ @@ -469,11 +469,11 @@ EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(kInterface); #undef EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL // Fast path field resolution that can't initialize classes or throw exceptions. -inline mirror::ArtField* FindFieldFast(uint32_t field_idx, +inline ArtField* FindFieldFast(uint32_t field_idx, mirror::ArtMethod* referrer, FindFieldType type, size_t expected_size) { - mirror::ArtField* resolved_field = - referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx); + ArtField* resolved_field = + referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx, sizeof(void*)); if (UNLIKELY(resolved_field == nullptr)) { return nullptr; } diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc index 70e2851..1d8df68 100644 --- a/runtime/entrypoints/entrypoint_utils.cc +++ b/runtime/entrypoints/entrypoint_utils.cc @@ -16,11 +16,11 @@ #include "entrypoints/entrypoint_utils.h" +#include "art_field-inl.h" #include "base/mutex.h" #include "class_linker-inl.h" #include "dex_file-inl.h" #include "gc/accounting/card_table-inl.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index 77eec46..8d419f8 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -30,14 +30,14 @@ namespace art { namespace mirror { - class Class; class Array; - class ArtField; class ArtMethod; + class Class; class Object; class String; } // namespace mirror +class ArtField; class ScopedObjectAccessAlreadyRunnable; class Thread; @@ -132,7 +132,7 @@ enum FindFieldType { }; template<FindFieldType type, bool access_check> -inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer, +inline ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer, Thread* self, size_t expected_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -143,7 +143,7 @@ inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Fast path field resolution that can't initialize classes or throw exceptions. -inline mirror::ArtField* FindFieldFast(uint32_t field_idx, +inline ArtField* FindFieldFast(uint32_t field_idx, mirror::ArtMethod* referrer, FindFieldType type, size_t expected_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc index 22bf939..b5a7c09 100644 --- a/runtime/entrypoints/quick/quick_field_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc @@ -14,10 +14,10 @@ * limitations under the License. */ +#include "art_field-inl.h" #include "callee_save_frame.h" #include "dex_file-inl.h" #include "entrypoints/entrypoint_utils-inl.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" @@ -29,8 +29,7 @@ extern "C" int8_t artGetByteStaticFromCode(uint32_t field_idx, mirror::ArtMethod Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, - sizeof(int8_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t)); if (LIKELY(field != nullptr)) { return field->GetByte(field->GetDeclaringClass()); } @@ -45,8 +44,7 @@ extern "C" uint8_t artGetBooleanStaticFromCode(uint32_t field_idx, mirror::ArtMe Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, - sizeof(int8_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t)); if (LIKELY(field != nullptr)) { return field->GetBoolean(field->GetDeclaringClass()); } @@ -61,8 +59,7 @@ extern "C" int16_t artGetShortStaticFromCode(uint32_t field_idx, mirror::ArtMeth Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, - sizeof(int16_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t)); if (LIKELY(field != nullptr)) { return field->GetShort(field->GetDeclaringClass()); } @@ -78,8 +75,7 @@ extern "C" uint16_t artGetCharStaticFromCode(uint32_t field_idx, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, - sizeof(int16_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t)); if (LIKELY(field != nullptr)) { return field->GetChar(field->GetDeclaringClass()); } @@ -95,8 +91,7 @@ extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, - sizeof(int32_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int32_t)); if (LIKELY(field != nullptr)) { return field->Get32(field->GetDeclaringClass()); } @@ -112,8 +107,7 @@ extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, - sizeof(int64_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int64_t)); if (LIKELY(field != nullptr)) { return field->Get64(field->GetDeclaringClass()); } @@ -129,8 +123,8 @@ extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead, - sizeof(mirror::HeapReference<mirror::Object>)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectRead, + sizeof(mirror::HeapReference<mirror::Object>)); if (LIKELY(field != nullptr)) { return field->GetObj(field->GetDeclaringClass()); } @@ -146,8 +140,7 @@ extern "C" int8_t artGetByteInstanceFromCode(uint32_t field_idx, mirror::Object* mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, - sizeof(int8_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t)); if (LIKELY(field != nullptr && obj != nullptr)) { return field->GetByte(obj); } @@ -167,8 +160,7 @@ extern "C" uint8_t artGetBooleanInstanceFromCode(uint32_t field_idx, mirror::Obj mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, - sizeof(int8_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t)); if (LIKELY(field != nullptr && obj != nullptr)) { return field->GetBoolean(obj); } @@ -187,8 +179,7 @@ extern "C" int16_t artGetShortInstanceFromCode(uint32_t field_idx, mirror::Objec mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, - sizeof(int16_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t)); if (LIKELY(field != nullptr && obj != nullptr)) { return field->GetShort(obj); } @@ -208,8 +199,7 @@ extern "C" uint16_t artGetCharInstanceFromCode(uint32_t field_idx, mirror::Objec mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, - sizeof(int16_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t)); if (LIKELY(field != nullptr && obj != nullptr)) { return field->GetChar(obj); } @@ -229,8 +219,7 @@ extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object* mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, - sizeof(int32_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t)); if (LIKELY(field != nullptr && obj != nullptr)) { return field->Get32(obj); } @@ -250,8 +239,7 @@ extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object* mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, - sizeof(int64_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t)); if (LIKELY(field != nullptr && obj != nullptr)) { return field->Get64(obj); } @@ -272,13 +260,13 @@ extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror: Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, - sizeof(mirror::HeapReference<mirror::Object>)); + ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, + sizeof(mirror::HeapReference<mirror::Object>)); if (LIKELY(field != nullptr && obj != nullptr)) { return field->GetObj(obj); } - field = FindFieldFromCode<InstanceObjectRead, true>(field_idx, referrer, self, - sizeof(mirror::HeapReference<mirror::Object>)); + field = FindFieldFromCode<InstanceObjectRead, true>( + field_idx, referrer, self, sizeof(mirror::HeapReference<mirror::Object>)); if (LIKELY(field != nullptr)) { if (UNLIKELY(obj == nullptr)) { ThrowNullPointerExceptionForFieldAccess(field, true); @@ -293,8 +281,7 @@ extern "C" int artSet8StaticFromCode(uint32_t field_idx, uint32_t new_value, mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, - sizeof(int8_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int8_t)); if (LIKELY(field != nullptr)) { Primitive::Type type = field->GetTypeAsPrimitiveType(); // Compiled code can't use transactional mode. @@ -325,8 +312,7 @@ extern "C" int artSet16StaticFromCode(uint32_t field_idx, uint16_t new_value, mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, - sizeof(int16_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int16_t)); if (LIKELY(field != nullptr)) { Primitive::Type type = field->GetTypeAsPrimitiveType(); // Compiled code can't use transactional mode. @@ -357,8 +343,7 @@ extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value, mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, - sizeof(int32_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t)); if (LIKELY(field != nullptr)) { // Compiled code can't use transactional mode. field->Set32<false>(field->GetDeclaringClass(), new_value); @@ -377,8 +362,7 @@ extern "C" int artSet64StaticFromCode(uint32_t field_idx, mirror::ArtMethod* ref uint64_t new_value, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, - sizeof(int64_t)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t)); if (LIKELY(field != nullptr)) { // Compiled code can't use transactional mode. field->Set64<false>(field->GetDeclaringClass(), new_value); @@ -397,8 +381,8 @@ extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_v mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, - sizeof(mirror::HeapReference<mirror::Object>)); + ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, + sizeof(mirror::HeapReference<mirror::Object>)); if (LIKELY(field != nullptr)) { if (LIKELY(!field->IsPrimitiveType())) { // Compiled code can't use transactional mode. @@ -420,8 +404,7 @@ extern "C" int artSet8InstanceFromCode(uint32_t field_idx, mirror::Object* obj, mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, - sizeof(int8_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t)); if (LIKELY(field != nullptr && obj != nullptr)) { Primitive::Type type = field->GetTypeAsPrimitiveType(); // Compiled code can't use transactional mode. @@ -460,8 +443,7 @@ extern "C" int artSet16InstanceFromCode(uint32_t field_idx, mirror::Object* obj, mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, - sizeof(int16_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int16_t)); if (LIKELY(field != nullptr && obj != nullptr)) { Primitive::Type type = field->GetTypeAsPrimitiveType(); // Compiled code can't use transactional mode. @@ -501,8 +483,7 @@ extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj, mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, - sizeof(int32_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t)); if (LIKELY(field != nullptr && obj != nullptr)) { // Compiled code can't use transactional mode. field->Set32<false>(obj, new_value); @@ -530,8 +511,7 @@ extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj, mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, - sizeof(int64_t)); + ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int64_t)); if (LIKELY(field != nullptr && obj != nullptr)) { // Compiled code can't use transactional mode. field->Set64<false>(obj, new_value); @@ -556,8 +536,8 @@ extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj mirror::ArtMethod* referrer, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); - mirror::ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, - sizeof(mirror::HeapReference<mirror::Object>)); + ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, + sizeof(mirror::HeapReference<mirror::Object>)); if (LIKELY(field != nullptr && obj != nullptr)) { // Compiled code can't use transactional mode. field->SetObj<false>(obj, new_value); diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc index a3fac58..cd3f910 100644 --- a/runtime/gc/accounting/mod_union_table.cc +++ b/runtime/gc/accounting/mod_union_table.cc @@ -28,7 +28,6 @@ #include "gc/heap.h" #include "gc/space/space.h" #include "gc/space/image_space.h" -#include "mirror/art_field-inl.h" #include "mirror/object-inl.h" #include "mirror/class-inl.h" #include "mirror/object_array-inl.h" diff --git a/runtime/gc/accounting/remembered_set.cc b/runtime/gc/accounting/remembered_set.cc index b16a146..eeb385e 100644 --- a/runtime/gc/accounting/remembered_set.cc +++ b/runtime/gc/accounting/remembered_set.cc @@ -26,7 +26,6 @@ #include "gc/collector/semi_space.h" #include "gc/heap.h" #include "gc/space/space.h" -#include "mirror/art_field-inl.h" #include "mirror/object-inl.h" #include "mirror/class-inl.h" #include "mirror/object_array-inl.h" diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc index ad8d988..2da8325 100644 --- a/runtime/gc/accounting/space_bitmap.cc +++ b/runtime/gc/accounting/space_bitmap.cc @@ -16,12 +16,12 @@ #include "space_bitmap-inl.h" +#include "art_field-inl.h" #include "base/stringprintf.h" #include "dex_file-inl.h" #include "mem_map.h" #include "mirror/object-inl.h" #include "mirror/class.h" -#include "mirror/art_field.h" #include "mirror/object_array.h" namespace art { @@ -190,15 +190,13 @@ void SpaceBitmap<kAlignment>::WalkInstanceFields(SpaceBitmap<kAlignment>* visite WalkInstanceFields(visited, callback, obj, super, arg); } // Walk instance fields - mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields(); - if (fields != NULL) { - for (int32_t i = 0; i < fields->GetLength(); i++) { - mirror::ArtField* field = fields->Get(i); - if (!field->IsPrimitiveType()) { - mirror::Object* value = field->GetObj(obj); - if (value != NULL) { - WalkFieldsInOrder(visited, callback, value, arg); - } + auto* fields = klass->GetIFields(); + for (size_t i = 0, count = klass->NumInstanceFields(); i < count; ++i) { + ArtField* field = &fields[i]; + if (!field->IsPrimitiveType()) { + mirror::Object* value = field->GetObj(obj); + if (value != nullptr) { + WalkFieldsInOrder(visited, callback, value, arg); } } } @@ -219,15 +217,13 @@ void SpaceBitmap<kAlignment>::WalkFieldsInOrder(SpaceBitmap<kAlignment>* visited WalkInstanceFields(visited, callback, obj, klass, arg); // Walk static fields of a Class if (obj->IsClass()) { - mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields(); - if (fields != NULL) { - for (int32_t i = 0; i < fields->GetLength(); i++) { - mirror::ArtField* field = fields->Get(i); - if (!field->IsPrimitiveType()) { - mirror::Object* value = field->GetObj(NULL); - if (value != NULL) { - WalkFieldsInOrder(visited, callback, value, arg); - } + auto* sfields = klass->GetSFields(); + for (size_t i = 0, count = klass->NumStaticFields(); i < count; ++i) { + ArtField* field = &sfields[i]; + if (!field->IsPrimitiveType()) { + mirror::Object* value = field->GetObj(nullptr); + if (value != nullptr) { + WalkFieldsInOrder(visited, callback, value, arg); } } } diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index 6a68880..eabb1c2 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -16,12 +16,12 @@ #include "concurrent_copying.h" +#include "art_field-inl.h" #include "gc/accounting/heap_bitmap-inl.h" #include "gc/accounting/space_bitmap-inl.h" #include "gc/space/image_space.h" #include "gc/space/space.h" #include "intern_table.h" -#include "mirror/art_field-inl.h" #include "mirror/object-inl.h" #include "scoped_thread_state_change.h" #include "thread-inl.h" diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc index 8902df8..3c247cd 100644 --- a/runtime/gc/collector/mark_compact.cc +++ b/runtime/gc/collector/mark_compact.cc @@ -35,8 +35,6 @@ #include "jni_internal.h" #include "mark_sweep-inl.h" #include "monitor.h" -#include "mirror/art_field.h" -#include "mirror/art_field-inl.h" #include "mirror/class-inl.h" #include "mirror/class_loader.h" #include "mirror/dex_cache.h" diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h index 104ed36..4e3845e 100644 --- a/runtime/gc/collector/mark_sweep-inl.h +++ b/runtime/gc/collector/mark_sweep-inl.h @@ -17,10 +17,9 @@ #ifndef ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_INL_H_ #define ART_RUNTIME_GC_COLLECTOR_MARK_SWEEP_INL_H_ -#include "gc/collector/mark_sweep.h" +#include "mark_sweep.h" #include "gc/heap.h" -#include "mirror/art_field.h" #include "mirror/class-inl.h" #include "mirror/object_array-inl.h" #include "mirror/reference.h" diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index 79d1034..ed2e295 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -39,7 +39,6 @@ #include "gc/space/large_object_space.h" #include "gc/space/space-inl.h" #include "mark_sweep-inl.h" -#include "mirror/art_field-inl.h" #include "mirror/object-inl.h" #include "runtime.h" #include "scoped_thread_state_change.h" diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index b9153c1..83da5a8 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -23,6 +23,7 @@ #include <memory> #include <vector> +#include "art_field-inl.h" #include "base/allocator.h" #include "base/dumpable.h" #include "base/histogram-inl.h" @@ -58,7 +59,6 @@ #include "heap-inl.h" #include "image.h" #include "intern_table.h" -#include "mirror/art_field-inl.h" #include "mirror/class-inl.h" #include "mirror/object.h" #include "mirror/object-inl.h" @@ -233,7 +233,7 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max CHECK_GT(oat_file_end_addr, image_space->End()); requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize); } else { - LOG(WARNING) << "Could not create image space with image file '" << image_file_name << "'. " + LOG(ERROR) << "Could not create image space with image file '" << image_file_name << "'. " << "Attempting to fall back to imageless running. Error was: " << error_msg; } } @@ -482,7 +482,7 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max non_moving_space_->GetMemMap()); if (!no_gap) { MemMap::DumpMaps(LOG(ERROR)); - LOG(FATAL) << "There's a gap between the image space and the main space"; + LOG(FATAL) << "There's a gap between the image space and the non-moving space"; } } if (running_on_valgrind_) { @@ -2708,12 +2708,12 @@ class VerifyReferenceCardVisitor { // Print which field of the object is dead. if (!obj->IsObjectArray()) { mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass(); - CHECK(klass != NULL); - mirror::ObjectArray<mirror::ArtField>* fields = is_static ? klass->GetSFields() - : klass->GetIFields(); - CHECK(fields != NULL); - for (int32_t i = 0; i < fields->GetLength(); ++i) { - mirror::ArtField* cur = fields->Get(i); + CHECK(klass != nullptr); + auto* fields = is_static ? klass->GetSFields() : klass->GetIFields(); + auto num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields(); + CHECK_EQ(fields == nullptr, num_fields == 0u); + for (size_t i = 0; i < num_fields; ++i) { + ArtField* cur = &fields[i]; if (cur->GetOffset().Int32Value() == offset.Int32Value()) { LOG(ERROR) << (is_static ? "Static " : "") << "field in the live stack is " << PrettyField(cur); diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 1fb3252..e28e8d7 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -43,8 +43,9 @@ namespace space { Atomic<uint32_t> ImageSpace::bitmap_index_(0); ImageSpace::ImageSpace(const std::string& image_filename, const char* image_location, - MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap) - : MemMapSpace(image_filename, mem_map, mem_map->Begin(), mem_map->End(), mem_map->End(), + MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap, + uint8_t* end) + : MemMapSpace(image_filename, mem_map, mem_map->Begin(), end, end, kGcRetentionPolicyNeverCollect), image_location_(image_location) { DCHECK(live_bitmap != nullptr); @@ -642,10 +643,10 @@ ImageSpace* ImageSpace::Create(const char* image_location, void ImageSpace::VerifyImageAllocations() { uint8_t* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment); while (current < End()) { - DCHECK_ALIGNED(current, kObjectAlignment); - mirror::Object* obj = reinterpret_cast<mirror::Object*>(current); - CHECK(live_bitmap_->Test(obj)); + CHECK_ALIGNED(current, kObjectAlignment); + auto* obj = reinterpret_cast<mirror::Object*>(current); CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class"; + CHECK(live_bitmap_->Test(obj)) << PrettyTypeOf(obj); if (kUseBakerOrBrooksReadBarrier) { obj->AssertReadBarrierPointer(); } @@ -675,7 +676,6 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat *error_msg = StringPrintf("Invalid image header in '%s'", image_filename); return nullptr; } - // Check that the file is large enough. uint64_t image_file_size = static_cast<uint64_t>(file->GetLength()); if (image_header.GetImageSize() > image_file_size) { @@ -683,23 +683,18 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat image_file_size, image_header.GetImageSize()); return nullptr; } - if (image_header.GetBitmapOffset() + image_header.GetImageBitmapSize() != image_file_size) { - *error_msg = StringPrintf("Image file too small for image bitmap: %" PRIu64 " vs. %zu.", - image_file_size, - image_header.GetBitmapOffset() + image_header.GetImageBitmapSize()); + auto end_of_bitmap = image_header.GetImageBitmapOffset() + image_header.GetImageBitmapSize(); + if (end_of_bitmap != image_file_size) { + *error_msg = StringPrintf( + "Image file size does not equal end of bitmap: size=%" PRIu64 " vs. %zu.", image_file_size, + end_of_bitmap); return nullptr; } // Note: The image header is part of the image due to mmap page alignment required of offset. - std::unique_ptr<MemMap> map(MemMap::MapFileAtAddress(image_header.GetImageBegin(), - image_header.GetImageSize(), - PROT_READ | PROT_WRITE, - MAP_PRIVATE, - file->Fd(), - 0, - false, - image_filename, - error_msg)); + std::unique_ptr<MemMap> map(MemMap::MapFileAtAddress( + image_header.GetImageBegin(), image_header.GetImageSize() + image_header.GetArtFieldsSize(), + PROT_READ | PROT_WRITE, MAP_PRIVATE, file->Fd(), 0, false, image_filename, error_msg)); if (map.get() == NULL) { DCHECK(!error_msg->empty()); return nullptr; @@ -710,7 +705,7 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat std::unique_ptr<MemMap> image_map( MemMap::MapFileAtAddress(nullptr, image_header.GetImageBitmapSize(), PROT_READ, MAP_PRIVATE, - file->Fd(), image_header.GetBitmapOffset(), + file->Fd(), image_header.GetImageBitmapOffset(), false, image_filename, error_msg)); @@ -730,8 +725,9 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat return nullptr; } + uint8_t* const image_end = map->Begin() + image_header.GetImageSize(); std::unique_ptr<ImageSpace> space(new ImageSpace(image_filename, image_location, - map.release(), bitmap.release())); + map.release(), bitmap.release(), image_end)); // VerifyImageAllocations() will be called later in Runtime::Init() // as some class roots like ArtMethod::java_lang_reflect_ArtMethod_ diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h index d7f8057..9ae2af4 100644 --- a/runtime/gc/space/image_space.h +++ b/runtime/gc/space/image_space.h @@ -145,7 +145,7 @@ class ImageSpace : public MemMapSpace { std::unique_ptr<accounting::ContinuousSpaceBitmap> live_bitmap_; ImageSpace(const std::string& name, const char* image_location, - MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap); + MemMap* mem_map, accounting::ContinuousSpaceBitmap* live_bitmap, uint8_t* end); // The OatFile associated with the image during early startup to // reserve space contiguous to the image. It is later released to diff --git a/runtime/globals.h b/runtime/globals.h index ac8751c..4d7fd2e 100644 --- a/runtime/globals.h +++ b/runtime/globals.h @@ -71,8 +71,6 @@ static constexpr bool kMarkCompactSupport = false && kMovingCollector; static constexpr bool kMoveFieldArrays = !kMarkCompactSupport; // True if we allow moving classes. static constexpr bool kMovingClasses = !kMarkCompactSupport; -// True if we allow moving fields. -static constexpr bool kMovingFields = false; // True if we allow moving methods. static constexpr bool kMovingMethods = false; diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc index cdb3e2a..23af25d 100644 --- a/runtime/hprof/hprof.cc +++ b/runtime/hprof/hprof.cc @@ -37,6 +37,7 @@ #include <set> +#include "art_field-inl.h" #include "base/logging.h" #include "base/stringprintf.h" #include "base/unix_file/fd_file.h" @@ -51,7 +52,6 @@ #include "globals.h" #include "jdwp/jdwp.h" #include "jdwp/jdwp_priv.h" -#include "mirror/art_field-inl.h" #include "mirror/class.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -999,7 +999,7 @@ void Hprof::DumpHeapClass(mirror::Class* klass) { __ AddClassStaticsId(klass); for (size_t i = 0; i < sFieldCount; ++i) { - mirror::ArtField* f = klass->GetStaticField(i); + ArtField* f = klass->GetStaticField(i); size_t size; HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size); @@ -1038,7 +1038,7 @@ void Hprof::DumpHeapClass(mirror::Class* klass) { int iFieldCount = klass->IsObjectClass() ? 0 : klass->NumInstanceFields(); __ AddU2((uint16_t)iFieldCount); for (int i = 0; i < iFieldCount; ++i) { - mirror::ArtField* f = klass->GetInstanceField(i); + ArtField* f = klass->GetInstanceField(i); __ AddStringId(LookupStringId(f->GetName())); HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), nullptr); __ AddU1(t); @@ -1102,7 +1102,7 @@ void Hprof::DumpHeapInstanceObject(mirror::Object* obj, mirror::Class* klass) { while (!klass->IsObjectClass()) { int ifieldCount = klass->NumInstanceFields(); for (int i = 0; i < ifieldCount; ++i) { - mirror::ArtField* f = klass->GetInstanceField(i); + ArtField* f = klass->GetInstanceField(i); size_t size; auto t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size); switch (t) { diff --git a/runtime/image.cc b/runtime/image.cc index 3cb2580..2d8c1c4 100644 --- a/runtime/image.cc +++ b/runtime/image.cc @@ -24,10 +24,12 @@ namespace art { const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; -const uint8_t ImageHeader::kImageVersion[] = { '0', '1', '4', '\0' }; +const uint8_t ImageHeader::kImageVersion[] = { '0', '1', '5', '\0' }; ImageHeader::ImageHeader(uint32_t image_begin, uint32_t image_size, + uint32_t art_fields_offset, + uint32_t art_fields_size, uint32_t image_bitmap_offset, uint32_t image_bitmap_size, uint32_t image_roots, @@ -39,6 +41,8 @@ ImageHeader::ImageHeader(uint32_t image_begin, bool compile_pic) : image_begin_(image_begin), image_size_(image_size), + art_fields_offset_(art_fields_offset), + art_fields_size_(art_fields_size), image_bitmap_offset_(image_bitmap_offset), image_bitmap_size_(image_bitmap_size), oat_checksum_(oat_checksum), diff --git a/runtime/image.h b/runtime/image.h index 3c527b8..613414a 100644 --- a/runtime/image.h +++ b/runtime/image.h @@ -32,6 +32,8 @@ class PACKED(4) ImageHeader { ImageHeader(uint32_t image_begin, uint32_t image_size_, + uint32_t art_fields_offset, + uint32_t art_fields_size, uint32_t image_bitmap_offset, uint32_t image_bitmap_size, uint32_t image_roots, @@ -53,6 +55,14 @@ class PACKED(4) ImageHeader { return static_cast<uint32_t>(image_size_); } + size_t GetArtFieldsOffset() const { + return art_fields_offset_; + } + + size_t GetArtFieldsSize() const { + return art_fields_size_; + } + size_t GetImageBitmapOffset() const { return image_bitmap_offset_; } @@ -89,10 +99,6 @@ class PACKED(4) ImageHeader { return patch_delta_; } - size_t GetBitmapOffset() const { - return RoundUp(image_size_, kPageSize); - } - static std::string GetOatLocationFromImageLocation(const std::string& image) { std::string oat_filename = image; if (oat_filename.length() <= 3) { @@ -140,6 +146,12 @@ class PACKED(4) ImageHeader { // Image size, not page aligned. uint32_t image_size_; + // ArtField array offset. + uint32_t art_fields_offset_; + + // ArtField size in bytes. + uint32_t art_fields_size_; + // Image bitmap offset in the file. uint32_t image_bitmap_offset_; diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 680b563..f8c0e83 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -929,7 +929,7 @@ void Instrumentation::BackwardBranchImpl(Thread* thread, mirror::ArtMethod* meth void Instrumentation::FieldReadEventImpl(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method, uint32_t dex_pc, - mirror::ArtField* field) const { + ArtField* field) const { if (HasFieldReadListeners()) { std::shared_ptr<std::list<InstrumentationListener*>> original(field_read_listeners_); for (InstrumentationListener* listener : *original.get()) { @@ -940,7 +940,7 @@ void Instrumentation::FieldReadEventImpl(Thread* thread, mirror::Object* this_ob void Instrumentation::FieldWriteEventImpl(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method, uint32_t dex_pc, - mirror::ArtField* field, const JValue& field_value) const { + ArtField* field, const JValue& field_value) const { if (HasFieldWriteListeners()) { std::shared_ptr<std::list<InstrumentationListener*>> original(field_write_listeners_); for (InstrumentationListener* listener : *original.get()) { diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h index 77314c6..41821a6 100644 --- a/runtime/instrumentation.h +++ b/runtime/instrumentation.h @@ -30,12 +30,12 @@ namespace art { namespace mirror { - class ArtField; class ArtMethod; class Class; class Object; class Throwable; } // namespace mirror +class ArtField; union JValue; class Thread; @@ -82,11 +82,11 @@ struct InstrumentationListener { // Call-back for when we read from a field. virtual void FieldRead(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method, - uint32_t dex_pc, mirror::ArtField* field) = 0; + uint32_t dex_pc, ArtField* field) = 0; // Call-back for when we write into a field. virtual void FieldWritten(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method, - uint32_t dex_pc, mirror::ArtField* field, const JValue& field_value) = 0; + uint32_t dex_pc, ArtField* field, const JValue& field_value) = 0; // Call-back when an exception is caught. virtual void ExceptionCaught(Thread* thread, mirror::Throwable* exception_object) @@ -301,7 +301,7 @@ class Instrumentation { // Inform listeners that we read a field (only supported by the interpreter). void FieldReadEvent(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method, uint32_t dex_pc, - mirror::ArtField* field) const + ArtField* field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (UNLIKELY(HasFieldReadListeners())) { FieldReadEventImpl(thread, this_object, method, dex_pc, field); @@ -311,7 +311,7 @@ class Instrumentation { // Inform listeners that we write a field (only supported by the interpreter). void FieldWriteEvent(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method, uint32_t dex_pc, - mirror::ArtField* field, const JValue& field_value) const + ArtField* field, const JValue& field_value) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (UNLIKELY(HasFieldWriteListeners())) { FieldWriteEventImpl(thread, this_object, method, dex_pc, field, field_value); @@ -377,11 +377,11 @@ class Instrumentation { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void FieldReadEventImpl(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method, uint32_t dex_pc, - mirror::ArtField* field) const + ArtField* field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void FieldWriteEventImpl(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method, uint32_t dex_pc, - mirror::ArtField* field, const JValue& field_value) const + ArtField* field, const JValue& field_value) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Read barrier-aware utility functions for accessing deoptimized_methods_ diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 375d644..3ae611b 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -281,11 +281,10 @@ bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction // object in the destructor. Class* field_class; { - StackHandleScope<3> hs(self); - HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f)); + StackHandleScope<2> hs(self); HandleWrapper<mirror::Object> h_reg(hs.NewHandleWrapper(®)); HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj)); - field_class = h_f->GetType<true>(); + field_class = f->GetType<true>(); } if (!reg->VerifierInstanceOf(field_class)) { // This should never happen. diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index 2f8bf55..0e0d56a 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -24,6 +24,7 @@ #include <iostream> #include <sstream> +#include "art_field-inl.h" #include "base/logging.h" #include "base/macros.h" #include "class_linker-inl.h" @@ -32,7 +33,6 @@ #include "dex_instruction-inl.h" #include "entrypoints/entrypoint_utils-inl.h" #include "handle_scope-inl.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -41,7 +41,6 @@ #include "thread.h" #include "well_known_classes.h" -using ::art::mirror::ArtField; using ::art::mirror::ArtMethod; using ::art::mirror::Array; using ::art::mirror::BooleanArray; diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 9af8102..dd8c57b 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -208,20 +208,22 @@ static void UnstartedClassGetDeclaredField( // going the reflective Dex way. mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass(); mirror::String* name2 = shadow_frame->GetVRegReference(arg_offset + 1)->AsString(); - mirror::ArtField* found = nullptr; - mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields(); - for (int32_t i = 0; i < fields->GetLength() && found == nullptr; ++i) { - mirror::ArtField* f = fields->Get(i); + ArtField* found = nullptr; + ArtField* fields = klass->GetIFields(); + for (int32_t i = 0, count = klass->NumInstanceFields(); i < count; ++i) { + ArtField* f = &fields[i]; if (name2->Equals(f->GetName())) { found = f; + break; } } if (found == nullptr) { fields = klass->GetSFields(); - for (int32_t i = 0; i < fields->GetLength() && found == nullptr; ++i) { - mirror::ArtField* f = fields->Get(i); + for (int32_t i = 0, count = klass->NumStaticFields(); i < count; ++i) { + ArtField* f = &fields[i]; if (name2->Equals(f->GetName())) { found = f; + break; } } } diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h index 31c9a0b..a503b17 100644 --- a/runtime/jdwp/jdwp.h +++ b/runtime/jdwp/jdwp.h @@ -33,11 +33,11 @@ struct iovec; namespace art { +class ArtField; union JValue; class Thread; namespace mirror { - class ArtField; class ArtMethod; class Class; class Object; @@ -207,7 +207,7 @@ struct JdwpState { * "fieldValue" is non-null for field modification events only. * "is_modification" is true for field modification, false for field access. */ - void PostFieldEvent(const EventLocation* pLoc, mirror::ArtField* field, mirror::Object* thisPtr, + void PostFieldEvent(const EventLocation* pLoc, ArtField* field, mirror::Object* thisPtr, const JValue* fieldValue, bool is_modification) LOCKS_EXCLUDED(event_list_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc index c9a4483..ccf8bff 100644 --- a/runtime/jdwp/jdwp_event.cc +++ b/runtime/jdwp/jdwp_event.cc @@ -21,6 +21,7 @@ #include <string.h> #include <unistd.h> +#include "art_field-inl.h" #include "base/logging.h" #include "base/stringprintf.h" #include "debugger.h" @@ -28,7 +29,6 @@ #include "jdwp/jdwp_expand_buf.h" #include "jdwp/jdwp_priv.h" #include "jdwp/object_registry.h" -#include "mirror/art_field-inl.h" #include "scoped_thread_state_change.h" #include "thread-inl.h" @@ -119,7 +119,7 @@ struct ModBasket { mirror::Class* locationClass; /* ClassOnly */ mirror::Class* exceptionClass; /* ExceptionOnly */ bool caught; /* ExceptionOnly */ - mirror::ArtField* field; /* FieldOnly */ + ArtField* field; /* FieldOnly */ mirror::Object* thisPtr; /* InstanceOnly */ /* nothing for StepOnly -- handled differently */ }; @@ -914,7 +914,7 @@ void JdwpState::PostLocationEvent(const EventLocation* pLoc, mirror::Object* thi SendRequestAndPossiblySuspend(pReq, suspend_policy, thread_id); } -void JdwpState::PostFieldEvent(const EventLocation* pLoc, mirror::ArtField* field, +void JdwpState::PostFieldEvent(const EventLocation* pLoc, ArtField* field, mirror::Object* this_object, const JValue* fieldValue, bool is_modification) { DCHECK(pLoc != nullptr); diff --git a/runtime/jit/jit_instrumentation.h b/runtime/jit/jit_instrumentation.h index 425d2d3..9d5d74f 100644 --- a/runtime/jit/jit_instrumentation.h +++ b/runtime/jit/jit_instrumentation.h @@ -31,12 +31,12 @@ namespace art { namespace mirror { - class ArtField; class ArtMethod; class Class; class Object; class Throwable; } // namespace mirror +class ArtField; union JValue; class Thread; @@ -77,10 +77,10 @@ class JitInstrumentationListener : public instrumentation::InstrumentationListen mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/) OVERRIDE { } virtual void FieldRead(Thread* /*thread*/, mirror::Object* /*this_object*/, mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/, - mirror::ArtField* /*field*/) OVERRIDE { } + ArtField* /*field*/) OVERRIDE { } virtual void FieldWritten(Thread* /*thread*/, mirror::Object* /*this_object*/, mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/, - mirror::ArtField* /*field*/, const JValue& /*field_value*/) + ArtField* /*field*/, const JValue& /*field_value*/) OVERRIDE { } virtual void ExceptionCaught(Thread* /*thread*/, mirror::Throwable* /*exception_object*/) OVERRIDE { } diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 9ec64d4..8a5461b 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -23,6 +23,7 @@ #include <utility> #include <vector> +#include "art_field-inl.h" #include "atomic.h" #include "base/allocator.h" #include "base/logging.h" @@ -37,7 +38,6 @@ #include "interpreter/interpreter.h" #include "jni_env_ext.h" #include "java_vm_ext.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/class_loader.h" @@ -184,7 +184,7 @@ static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, con if (c.Get() == nullptr) { return nullptr; } - mirror::ArtField* field = nullptr; + ArtField* field = nullptr; mirror::Class* field_type; ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); if (sig[1] != '\0') { @@ -379,7 +379,7 @@ class JNI { static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) { CHECK_NON_NULL_ARGUMENT(fid); ScopedObjectAccess soa(env); - mirror::ArtField* f = soa.DecodeField(fid); + ArtField* f = soa.DecodeField(fid); return soa.AddLocalReference<jobject>(mirror::Field::CreateFromArtField(soa.Self(), f, true)); } @@ -1203,14 +1203,14 @@ class JNI { CHECK_NON_NULL_ARGUMENT(fid); ScopedObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(obj); - mirror::ArtField* f = soa.DecodeField(fid); + ArtField* f = soa.DecodeField(fid); return soa.AddLocalReference<jobject>(f->GetObject(o)); } static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) { CHECK_NON_NULL_ARGUMENT(fid); ScopedObjectAccess soa(env); - mirror::ArtField* f = soa.DecodeField(fid); + ArtField* f = soa.DecodeField(fid); return soa.AddLocalReference<jobject>(f->GetObject(f->GetDeclaringClass())); } @@ -1220,7 +1220,7 @@ class JNI { ScopedObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(java_object); mirror::Object* v = soa.Decode<mirror::Object*>(java_value); - mirror::ArtField* f = soa.DecodeField(fid); + ArtField* f = soa.DecodeField(fid); f->SetObject<false>(o, v); } @@ -1228,7 +1228,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); ScopedObjectAccess soa(env); mirror::Object* v = soa.Decode<mirror::Object*>(java_value); - mirror::ArtField* f = soa.DecodeField(fid); + ArtField* f = soa.DecodeField(fid); f->SetObject<false>(f->GetDeclaringClass(), v); } @@ -1237,13 +1237,13 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \ ScopedObjectAccess soa(env); \ mirror::Object* o = soa.Decode<mirror::Object*>(instance); \ - mirror::ArtField* f = soa.DecodeField(fid); \ + ArtField* f = soa.DecodeField(fid); \ return f->Get ##fn (o) #define GET_STATIC_PRIMITIVE_FIELD(fn) \ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \ ScopedObjectAccess soa(env); \ - mirror::ArtField* f = soa.DecodeField(fid); \ + ArtField* f = soa.DecodeField(fid); \ return f->Get ##fn (f->GetDeclaringClass()) #define SET_PRIMITIVE_FIELD(fn, instance, value) \ @@ -1251,13 +1251,13 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \ ScopedObjectAccess soa(env); \ mirror::Object* o = soa.Decode<mirror::Object*>(instance); \ - mirror::ArtField* f = soa.DecodeField(fid); \ + ArtField* f = soa.DecodeField(fid); \ f->Set ##fn <false>(o, value) #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \ ScopedObjectAccess soa(env); \ - mirror::ArtField* f = soa.DecodeField(fid); \ + ArtField* f = soa.DecodeField(fid); \ f->Set ##fn <false>(f->GetDeclaringClass(), value) static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) { diff --git a/runtime/linear_alloc.cc b/runtime/linear_alloc.cc new file mode 100644 index 0000000..fe6bee6 --- /dev/null +++ b/runtime/linear_alloc.cc @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015 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 "linear_alloc.h" + +#include "thread-inl.h" + +namespace art { + +LinearAlloc::LinearAlloc(ArenaPool* pool) : lock_("linear alloc"), allocator_(pool) { +} + +void* LinearAlloc::Alloc(Thread* self, size_t size) { + MutexLock mu(self, lock_); + return allocator_.Alloc(size); +} + +size_t LinearAlloc::GetUsedMemory() const { + MutexLock mu(Thread::Current(), lock_); + return allocator_.BytesUsed(); +} + +} // namespace art diff --git a/runtime/linear_alloc.h b/runtime/linear_alloc.h new file mode 100644 index 0000000..6d8eda6 --- /dev/null +++ b/runtime/linear_alloc.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_LINEAR_ALLOC_H_ +#define ART_RUNTIME_LINEAR_ALLOC_H_ + +#include "base/arena_allocator.h" + +namespace art { + +class ArenaPool; + +// TODO: Support freeing if we add poor man's class unloading. +class LinearAlloc { + public: + explicit LinearAlloc(ArenaPool* pool); + + void* Alloc(Thread* self, size_t size); + + // Allocate and construct an array of structs of type T. + template<class T> + T* AllocArray(Thread* self, size_t elements) { + return reinterpret_cast<T*>(Alloc(self, elements * sizeof(T))); + } + + // Return the number of bytes used in the allocator. + size_t GetUsedMemory() const; + + private: + mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; + ArenaAllocator allocator_ GUARDED_BY(lock_); +}; + +} // namespace art + +#endif // ART_RUNTIME_LINEAR_ALLOC_H_ diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc index 588615f..edd2888 100644 --- a/runtime/mem_map.cc +++ b/runtime/mem_map.cc @@ -622,7 +622,7 @@ void MemMap::DumpMaps(std::ostream& os) { } void MemMap::DumpMapsLocked(std::ostream& os) { - os << maps_; + os << *maps_; } bool MemMap::HasMemMap(MemMap* map) { diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h index 6452f31..8b3418d 100644 --- a/runtime/mirror/array-inl.h +++ b/runtime/mirror/array-inl.h @@ -203,7 +203,7 @@ inline void PrimitiveArray<T>::VisitRoots(RootVisitor* visitor) { template<typename T> inline PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) { Array* raw_array = Array::Alloc<true>(self, GetArrayClass(), length, - ComponentSizeShiftWidth<sizeof(T)>(), + ComponentSizeShiftWidth(sizeof(T)), Runtime::Current()->GetHeap()->GetCurrentAllocator()); return down_cast<PrimitiveArray<T>*>(raw_array); } diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h index 115fcf2..832ad68 100644 --- a/runtime/mirror/array.h +++ b/runtime/mirror/array.h @@ -54,7 +54,7 @@ class MANAGED Array : public Object { } void SetLength(int32_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - CHECK_GE(length, 0); + DCHECK_GE(length, 0); // We use non transactional version since we can't undo this write. We also disable checking // since it would fail during a transaction. SetField32<false, false, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Array, length_), length); diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc index edbbb4a..92aea1f 100644 --- a/runtime/mirror/art_method.cc +++ b/runtime/mirror/art_method.cc @@ -53,7 +53,7 @@ GcRoot<Class> ArtMethod::java_lang_reflect_ArtMethod_; ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject jlr_method) { - mirror::ArtField* f = + ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod); mirror::ArtMethod* method = f->GetObject(soa.Decode<mirror::Object*>(jlr_method))->AsArtMethod(); DCHECK(method != nullptr); diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index c368dc6..5b72e5a 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -397,9 +397,9 @@ inline void Class::SetIfTable(IfTable* new_iftable) { SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable); } -inline ObjectArray<ArtField>* Class::GetIFields() { +inline ArtField* Class::GetIFields() { DCHECK(IsLoaded() || IsErroneous()); - return GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); + return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); } inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() { @@ -432,55 +432,46 @@ inline MemberOffset Class::GetFirstReferenceStaticFieldOffsetDuringLinking() { return MemberOffset(base); } -inline void Class::SetIFields(ObjectArray<ArtField>* new_ifields) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK(NULL == GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_))); - SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields); +inline void Class::SetIFields(ArtField* new_ifields) { + DCHECK(GetIFieldsUnchecked() == nullptr); + return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields); } -inline ObjectArray<ArtField>* Class::GetSFields() { - DCHECK(IsLoaded() || IsErroneous()) << GetStatus(); - return GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)); +inline void Class::SetIFieldsUnchecked(ArtField* new_ifields) { + SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields); } -inline void Class::SetSFields(ObjectArray<ArtField>* new_sfields) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - DCHECK((IsRetired() && new_sfields == nullptr) || - (NULL == GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)))); - SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields); +inline ArtField* Class::GetSFieldsUnchecked() { + return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)); } -inline uint32_t Class::NumStaticFields() { - return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0; +inline ArtField* Class::GetIFieldsUnchecked() { + return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); } - -inline ArtField* Class::GetStaticField(uint32_t i) // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetSFields()->GetWithoutChecks(i); +inline ArtField* Class::GetSFields() { + DCHECK(IsLoaded() || IsErroneous()) << GetStatus(); + return GetSFieldsUnchecked(); } -inline void Class::SetStaticField(uint32_t i, ArtField* f) // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectArray<ArtField>* sfields= GetFieldObject<ObjectArray<ArtField>>( - OFFSET_OF_OBJECT_MEMBER(Class, sfields_)); - sfields->Set<false>(i, f); +inline void Class::SetSFields(ArtField* new_sfields) { + DCHECK((IsRetired() && new_sfields == nullptr) || + GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)) == nullptr); + SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields); } -inline uint32_t Class::NumInstanceFields() { - return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0; +inline void Class::SetSFieldsUnchecked(ArtField* new_sfields) { + SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields); } -inline ArtField* Class::GetInstanceField(uint32_t i) { // TODO: uint16_t - DCHECK_NE(NumInstanceFields(), 0U); - return GetIFields()->GetWithoutChecks(i); +inline ArtField* Class::GetStaticField(uint32_t i) { + DCHECK_LT(i, NumStaticFields()); + return &GetSFields()[i]; } -inline void Class::SetInstanceField(uint32_t i, ArtField* f) // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ObjectArray<ArtField>* ifields= GetFieldObject<ObjectArray<ArtField>>( - OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); - ifields->Set<false>(i, f); +inline ArtField* Class::GetInstanceField(uint32_t i) { + DCHECK_LT(i, NumInstanceFields()); + return &GetIFields()[i]; } template<VerifyObjectFlags kVerifyFlags> @@ -513,14 +504,12 @@ inline uint32_t Class::GetAccessFlags() { DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() || IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() || this == String::GetJavaLangString() || - this == ArtField::GetJavaLangReflectArtField() || this == ArtMethod::GetJavaLangReflectArtMethod()) << "IsIdxLoaded=" << IsIdxLoaded<kVerifyFlags>() << " IsRetired=" << IsRetired<kVerifyFlags>() << " IsErroneous=" << IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() << " IsString=" << (this == String::GetJavaLangString()) - << " IsArtField=" << (this == ArtField::GetJavaLangReflectArtField()) << " IsArtMethod=" << (this == ArtMethod::GetJavaLangReflectArtMethod()) << " descriptor=" << PrettyDescriptor(this); return GetField32<kVerifyFlags>(AccessFlagsOffset()); @@ -691,11 +680,6 @@ inline void Class::VisitEmbeddedImtAndVTable(const Visitor& visitor) { } template<ReadBarrierOption kReadBarrierOption> -inline bool Class::IsArtFieldClass() const { - return this == ArtField::GetJavaLangReflectArtField<kReadBarrierOption>(); -} - -template<ReadBarrierOption kReadBarrierOption> inline bool Class::IsArtMethodClass() const { return this == ArtMethod::GetJavaLangReflectArtMethod<kReadBarrierOption>(); } @@ -741,35 +725,35 @@ inline void Class::AssertInitializedOrInitializingInThread(Thread* self) { inline ObjectArray<Class>* Class::GetInterfaces() { CHECK(IsProxyClass()); // First static field. - DCHECK(GetSFields()->Get(0)->IsArtField()); - DCHECK_STREQ(GetSFields()->Get(0)->GetName(), "interfaces"); - MemberOffset field_offset = GetSFields()->Get(0)->GetOffset(); + auto* field = GetStaticField(0); + DCHECK_STREQ(field->GetName(), "interfaces"); + MemberOffset field_offset = field->GetOffset(); return GetFieldObject<ObjectArray<Class>>(field_offset); } inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() { CHECK(IsProxyClass()); // Second static field. - DCHECK(GetSFields()->Get(1)->IsArtField()); - DCHECK_STREQ(GetSFields()->Get(1)->GetName(), "throws"); - MemberOffset field_offset = GetSFields()->Get(1)->GetOffset(); + auto* field = GetStaticField(1); + DCHECK_STREQ(field->GetName(), "throws"); + MemberOffset field_offset = field->GetOffset(); return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset); } inline MemberOffset Class::GetDisableIntrinsicFlagOffset() { CHECK(IsReferenceClass()); // First static field - DCHECK(GetSFields()->Get(0)->IsArtField()); - DCHECK_STREQ(GetSFields()->Get(0)->GetName(), "disableIntrinsic"); - return GetSFields()->Get(0)->GetOffset(); + auto* field = GetStaticField(0); + DCHECK_STREQ(field->GetName(), "disableIntrinsic"); + return field->GetOffset(); } inline MemberOffset Class::GetSlowPathFlagOffset() { CHECK(IsReferenceClass()); // Second static field - DCHECK(GetSFields()->Get(1)->IsArtField()); - DCHECK_STREQ(GetSFields()->Get(1)->GetName(), "slowPathEnabled"); - return GetSFields()->Get(1)->GetOffset(); + auto* field = GetStaticField(1); + DCHECK_STREQ(field->GetName(), "slowPathEnabled"); + return field->GetOffset(); } inline bool Class::GetSlowPathEnabled() { @@ -827,6 +811,24 @@ inline ObjectArray<String>* Class::GetDexCacheStrings() { return GetFieldObject<ObjectArray<String>>(DexCacheStringsOffset()); } +template<class Visitor> +void mirror::Class::VisitFieldRoots(Visitor& visitor) { + ArtField* const sfields = GetSFieldsUnchecked(); + for (size_t i = 0, count = NumStaticFields(); i < count; ++i) { + if (kIsDebugBuild && GetStatus() != kStatusRetired) { + CHECK_EQ(sfields[i].GetDeclaringClass(), this); + } + visitor.VisitRoot(sfields[i].DeclaringClassRoot().AddressWithoutBarrier()); + } + ArtField* const ifields = GetIFieldsUnchecked(); + for (size_t i = 0, count = NumInstanceFields(); i < count; ++i) { + if (kIsDebugBuild && GetStatus() != kStatusRetired) { + CHECK_EQ(ifields[i].GetDeclaringClass(), this); + } + visitor.VisitRoot(ifields[i].DeclaringClassRoot().AddressWithoutBarrier()); + } +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index b82a58f..92493bc 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -35,6 +35,7 @@ namespace art { +class ArtField; struct ClassOffsets; template<class T> class Handle; template<class T> class Handle; @@ -44,7 +45,6 @@ template<size_t kNumReferences> class PACKED(4) StackHandleScope; namespace mirror { -class ArtField; class ArtMethod; class ClassLoader; class DexCache; @@ -420,9 +420,6 @@ class MANAGED Class FINAL : public Object { bool IsThrowableClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - bool IsArtFieldClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> bool IsArtMethodClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> @@ -823,17 +820,22 @@ class MANAGED Class FINAL : public Object { ALWAYS_INLINE void SetIfTable(IfTable* new_iftable) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Get instance fields of the class (See also GetSFields). - ObjectArray<ArtField>* GetIFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ArtField* GetIFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetIFields(ObjectArray<ArtField>* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetIFields(ArtField* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - uint32_t NumInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Unchecked edition has no verification flags. + void SetIFieldsUnchecked(ArtField* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ArtField* GetInstanceField(uint32_t i) // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + uint32_t NumInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_instance_fields_)); + } - void SetInstanceField(uint32_t i, ArtField* f) // TODO: uint16_t - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetNumInstanceFields(uint32_t num) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_instance_fields_), num); + } + + ArtField* GetInstanceField(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns the number of instance fields containing reference types. uint32_t NumReferenceInstanceFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -884,17 +886,23 @@ class MANAGED Class FINAL : public Object { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Gets the static fields of the class. - ObjectArray<ArtField>* GetSFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ArtField* GetSFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetSFields(ObjectArray<ArtField>* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetSFields(ArtField* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - uint32_t NumStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Unchecked edition has no verification flags. + void SetSFieldsUnchecked(ArtField* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // TODO: uint16_t - ArtField* GetStaticField(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + uint32_t NumStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_static_fields_)); + } + + void SetNumStaticFields(uint32_t num) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_static_fields_), num); + } // TODO: uint16_t - void SetStaticField(uint32_t i, ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ArtField* GetStaticField(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Find a static or instance field using the JLS resolution order static ArtField* FindField(Thread* self, Handle<Class> klass, const StringPiece& name, @@ -974,6 +982,10 @@ class MANAGED Class FINAL : public Object { static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<class Visitor> + // Visit field roots. + void VisitFieldRoots(Visitor& visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // When class is verified, set the kAccPreverified flag on each method. void SetPreverifiedFlagOnAllMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -1079,6 +1091,10 @@ class MANAGED Class FINAL : public Object { void CheckObjectAlloc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Unchecked editions is for root visiting. + ArtField* GetSFieldsUnchecked() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ArtField* GetIFieldsUnchecked() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // defining class loader, or NULL for the "bootstrap" system loader HeapReference<ClassLoader> class_loader_; @@ -1096,18 +1112,6 @@ class MANAGED Class FINAL : public Object { // static, private, and <init> methods HeapReference<ObjectArray<ArtMethod>> direct_methods_; - // instance fields - // - // These describe the layout of the contents of an Object. - // Note that only the fields directly declared by this class are - // listed in ifields; fields declared by a superclass are listed in - // the superclass's Class.ifields. - // - // All instance fields that refer to objects are guaranteed to be at - // the beginning of the field list. num_reference_instance_fields_ - // specifies the number of reference fields. - HeapReference<ObjectArray<ArtField>> ifields_; - // The interface table (iftable_) contains pairs of a interface class and an array of the // interface methods. There is one pair per interface supported by this class. That means one // pair for each interface we support directly, indirectly via superclass, or indirectly via a @@ -1124,9 +1128,6 @@ class MANAGED Class FINAL : public Object { // Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName HeapReference<String> name_; - // Static fields - HeapReference<ObjectArray<ArtField>> sfields_; - // The superclass, or NULL if this is java.lang.Object, an interface or primitive type. HeapReference<Class> super_class_; @@ -1143,8 +1144,22 @@ class MANAGED Class FINAL : public Object { HeapReference<ObjectArray<ArtMethod>> vtable_; // Access flags; low 16 bits are defined by VM spec. + // Note: Shuffled back. uint32_t access_flags_; + // instance fields + // + // These describe the layout of the contents of an Object. + // Note that only the fields directly declared by this class are + // listed in ifields; fields declared by a superclass are listed in + // the superclass's Class.ifields. + // + // ArtField arrays are allocated as an array of fields, and not an array of fields pointers. + uint64_t ifields_; + + // Static fields + uint64_t sfields_; + // Total size of the Class instance; used when allocating storage on gc heap. // See also object_size_. uint32_t class_size_; @@ -1160,12 +1175,18 @@ class MANAGED Class FINAL : public Object { // TODO: really 16bits int32_t dex_type_idx_; + // Number of static fields. + uint32_t num_instance_fields_; + // Number of instance fields that are object refs. uint32_t num_reference_instance_fields_; // Number of static fields that are object refs, uint32_t num_reference_static_fields_; + // Number of static fields. + uint32_t num_static_fields_; + // Total object size; used when allocating storage on gc heap. // (For interfaces and abstract classes this will be zero.) // See also class_size_. diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h index 6758e22..1cb437e 100644 --- a/runtime/mirror/dex_cache-inl.h +++ b/runtime/mirror/dex_cache-inl.h @@ -19,6 +19,7 @@ #include "dex_cache.h" +#include "art_field-inl.h" #include "base/logging.h" #include "mirror/class.h" #include "runtime.h" @@ -35,12 +36,11 @@ inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ArtMethod* method = GetResolvedMethods()->Get(method_idx); // Hide resolution trampoline methods from the caller - if (method != NULL && method->IsRuntimeMethod()) { - DCHECK(method == Runtime::Current()->GetResolutionMethod()); - return NULL; - } else { - return method; + if (method != nullptr && method->IsRuntimeMethod()) { + DCHECK_EQ(method, Runtime::Current()->GetResolutionMethod()); + return nullptr; } + return method; } inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) { @@ -49,6 +49,34 @@ inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) { GetResolvedTypes()->Set(type_idx, resolved); } +inline ArtField* DexCache::GetResolvedField(uint32_t idx, size_t ptr_size) { + ArtField* field = nullptr; + if (ptr_size == 8) { + field = reinterpret_cast<ArtField*>( + static_cast<uintptr_t>(GetResolvedFields()->AsLongArray()->GetWithoutChecks(idx))); + } else { + DCHECK_EQ(ptr_size, 4u); + field = reinterpret_cast<ArtField*>( + static_cast<uintptr_t>(GetResolvedFields()->AsIntArray()->GetWithoutChecks(idx))); + } + if (field == nullptr || field->GetDeclaringClass()->IsErroneous()) { + return nullptr; + } + return field; +} + +inline void DexCache::SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size) { + if (ptr_size == 8) { + GetResolvedFields()->AsLongArray()->Set( + idx, static_cast<uint64_t>(reinterpret_cast<uintptr_t>(field))); + } else { + DCHECK_EQ(ptr_size, 4u); + CHECK_LE(reinterpret_cast<uintptr_t>(field), 0xFFFFFFFF); + GetResolvedFields()->AsIntArray()->Set( + idx, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(field))); + } +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc index d6c11e8..ade8bd2 100644 --- a/runtime/mirror/dex_cache.cc +++ b/runtime/mirror/dex_cache.cc @@ -36,7 +36,7 @@ void DexCache::Init(const DexFile* dex_file, ObjectArray<String>* strings, ObjectArray<Class>* resolved_types, ObjectArray<ArtMethod>* resolved_methods, - ObjectArray<ArtField>* resolved_fields) { + Array* resolved_fields) { CHECK(dex_file != nullptr); CHECK(location != nullptr); CHECK(strings != nullptr); @@ -44,19 +44,18 @@ void DexCache::Init(const DexFile* dex_file, CHECK(resolved_methods != nullptr); CHECK(resolved_fields != nullptr); - SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, dex_file_), dex_file); + SetDexFile(dex_file); SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location); SetFieldObject<false>(StringsOffset(), strings); + SetFieldObject<false>(ResolvedFieldsOffset(), resolved_fields); SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), resolved_types); SetFieldObject<false>(ResolvedMethodsOffset(), resolved_methods); - SetFieldObject<false>(ResolvedFieldsOffset(), resolved_fields); Runtime* runtime = Runtime::Current(); if (runtime->HasResolutionMethod()) { // Initialize the resolve methods array to contain trampolines for resolution. ArtMethod* trampoline = runtime->GetResolutionMethod(); - size_t length = resolved_methods->GetLength(); - for (size_t i = 0; i < length; i++) { + for (size_t i = 0, length = resolved_methods->GetLength(); i < length; i++) { resolved_methods->SetWithoutChecks<false>(i, trampoline); } } diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h index c548c03..7e30b89 100644 --- a/runtime/mirror/dex_cache.h +++ b/runtime/mirror/dex_cache.h @@ -50,7 +50,7 @@ class MANAGED DexCache FINAL : public Object { ObjectArray<String>* strings, ObjectArray<Class>* types, ObjectArray<ArtMethod>* methods, - ObjectArray<ArtField>* fields) + Array* fields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void Fixup(ArtMethod* trampoline) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -116,23 +116,16 @@ class MANAGED DexCache FINAL : public Object { GetResolvedMethods()->Set(method_idx, resolved); } - ArtField* GetResolvedField(uint32_t field_idx) ALWAYS_INLINE - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ArtField* field = GetResolvedFields()->Get(field_idx); - if (UNLIKELY(field == nullptr || field->GetDeclaringClass()->IsErroneous())) { - return nullptr; - } else { - return field; - } - } + // Pointer sized variant, used for patching. + ArtField* GetResolvedField(uint32_t idx, size_t ptr_size) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - void SetResolvedField(uint32_t field_idx, ArtField* resolved) ALWAYS_INLINE - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - GetResolvedFields()->Set(field_idx, resolved); - } + // Pointer sized variant, used for patching. + void SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); ObjectArray<String>* GetStrings() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetFieldObject< ObjectArray<String>>(StringsOffset()); + return GetFieldObject<ObjectArray<String>>(StringsOffset()); } ObjectArray<Class>* GetResolvedTypes() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -145,9 +138,8 @@ class MANAGED DexCache FINAL : public Object { return GetFieldObject< ObjectArray<ArtMethod>>(ResolvedMethodsOffset()); } - ObjectArray<ArtField>* GetResolvedFields() ALWAYS_INLINE - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return GetFieldObject<ObjectArray<ArtField>>(ResolvedFieldsOffset()); + Array* GetResolvedFields() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return GetFieldObject<Array>(ResolvedFieldsOffset()); } const DexFile* GetDexFile() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -162,7 +154,8 @@ class MANAGED DexCache FINAL : public Object { private: HeapReference<Object> dex_; HeapReference<String> location_; - HeapReference<ObjectArray<ArtField>> resolved_fields_; + // Either an int array or long array (64 bit). + HeapReference<Object> resolved_fields_; HeapReference<ObjectArray<ArtMethod>> resolved_methods_; HeapReference<ObjectArray<Class>> resolved_types_; HeapReference<ObjectArray<String>> strings_; diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc index 53e5534..1d6846b 100644 --- a/runtime/mirror/dex_cache_test.cc +++ b/runtime/mirror/dex_cache_test.cc @@ -47,7 +47,7 @@ TEST_F(DexCacheTest, Open) { EXPECT_LE(0, dex_cache->GetStrings()->GetLength()); EXPECT_LE(0, dex_cache->GetResolvedTypes()->GetLength()); EXPECT_LE(0, dex_cache->GetResolvedMethods()->GetLength()); - EXPECT_LE(0, dex_cache->GetResolvedFields()->GetLength()); + EXPECT_LE(0u, dex_cache->NumResolvedFields()); EXPECT_EQ(java_lang_dex_file_->NumStringIds(), static_cast<uint32_t>(dex_cache->GetStrings()->GetLength())); @@ -55,8 +55,7 @@ TEST_F(DexCacheTest, Open) { static_cast<uint32_t>(dex_cache->GetResolvedTypes()->GetLength())); EXPECT_EQ(java_lang_dex_file_->NumMethodIds(), static_cast<uint32_t>(dex_cache->GetResolvedMethods()->GetLength())); - EXPECT_EQ(java_lang_dex_file_->NumFieldIds(), - static_cast<uint32_t>(dex_cache->GetResolvedFields()->GetLength())); + EXPECT_EQ(java_lang_dex_file_->NumFieldIds(), dex_cache->NumResolvedFields()); } } // namespace mirror diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h index 24ebc48..7db1811 100644 --- a/runtime/mirror/field-inl.h +++ b/runtime/mirror/field-inl.h @@ -27,9 +27,8 @@ namespace art { namespace mirror { template <bool kTransactionActive> -inline mirror::Field* Field::CreateFromArtField(Thread* self, mirror::ArtField* field, +inline mirror::Field* Field::CreateFromArtField(Thread* self, ArtField* field, bool force_resolve) { - CHECK(!kMovingFields); // Try to resolve type before allocating since this is a thread suspension point. mirror::Class* type = field->GetType<true>(); @@ -57,13 +56,13 @@ inline mirror::Field* Field::CreateFromArtField(Thread* self, mirror::ArtField* return nullptr; } auto dex_field_index = field->GetDexFieldIndex(); - auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index); + auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index, sizeof(void*)); if (resolved_field != nullptr) { DCHECK_EQ(resolved_field, field); } else { // We rely on the field being resolved so that we can back to the ArtField // (i.e. FromReflectedMethod). - field->GetDexCache()->SetResolvedField(dex_field_index, field); + field->GetDexCache()->SetResolvedField(dex_field_index, field, sizeof(void*)); } ret->SetType<kTransactionActive>(type); ret->SetDeclaringClass<kTransactionActive>(field->GetDeclaringClass()); diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc index 82cc26e..70311bb 100644 --- a/runtime/mirror/field.cc +++ b/runtime/mirror/field.cc @@ -55,7 +55,7 @@ void Field::VisitRoots(RootVisitor* visitor) { ArtField* Field::GetArtField() { mirror::DexCache* const dex_cache = GetDeclaringClass()->GetDexCache(); - mirror::ArtField* const art_field = dex_cache->GetResolvedField(GetDexFieldIndex()); + ArtField* const art_field = dex_cache->GetResolvedField(GetDexFieldIndex(), sizeof(void*)); CHECK(art_field != nullptr); return art_field; } diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h index cea06f5..9988f84 100644 --- a/runtime/mirror/field.h +++ b/runtime/mirror/field.h @@ -25,11 +25,11 @@ namespace art { +class ArtField; struct FieldOffsets; namespace mirror { -class ArtField; class Class; class String; @@ -93,10 +93,10 @@ class MANAGED Field : public AccessibleObject { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Slow, try to use only for PrettyField and such. - mirror::ArtField* GetArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ArtField* GetArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); template <bool kTransactionActive = false> - static mirror::Field* CreateFromArtField(Thread* self, mirror::ArtField* field, + static mirror::Field* CreateFromArtField(Thread* self, ArtField* field, bool force_resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h index d690163..af0e856 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -225,18 +225,6 @@ inline bool Object::IsArrayInstance() { } template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> -inline bool Object::IsArtField() { - return GetClass<kVerifyFlags, kReadBarrierOption>()-> - template IsArtFieldClass<kReadBarrierOption>(); -} - -template<VerifyObjectFlags kVerifyFlags> -inline ArtField* Object::AsArtField() { - DCHECK(IsArtField<kVerifyFlags>()); - return down_cast<ArtField*>(this); -} - -template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> inline bool Object::IsArtMethod() { return GetClass<kVerifyFlags, kReadBarrierOption>()-> template IsArtMethodClass<kReadBarrierOption>(); @@ -318,8 +306,8 @@ inline ShortArray* Object::AsShortSizedArray() { template<VerifyObjectFlags kVerifyFlags> inline IntArray* Object::AsIntArray() { constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); - DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); - DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() || + CHECK(GetClass<kVerifyFlags>()->IsArrayClass()); + CHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() || GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); return down_cast<IntArray*>(this); } @@ -327,8 +315,8 @@ inline IntArray* Object::AsIntArray() { template<VerifyObjectFlags kVerifyFlags> inline LongArray* Object::AsLongArray() { constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); - DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); - DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() || + CHECK(GetClass<kVerifyFlags>()->IsArrayClass()); + CHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() || GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); return down_cast<LongArray*>(this); } @@ -403,7 +391,6 @@ inline size_t Object::SizeOf() { } DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>()); - DCHECK(!(IsArtField<kNewFlags, kReadBarrierOption>()) || result == sizeof(ArtField)); return result; } diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index 57ac46f..04d0cd8 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -204,22 +204,19 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val return; } for (Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) { - ObjectArray<ArtField>* fields = cur->GetIFields(); - if (fields != NULL) { - size_t num_ifields = fields->GetLength(); - for (size_t i = 0; i < num_ifields; ++i) { - StackHandleScope<1> hs(Thread::Current()); - Handle<Object> h_object(hs.NewHandle(new_value)); - ArtField* field = fields->Get(i); - if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { - CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot); - // TODO: resolve the field type for moving GC. - mirror::Class* field_type = field->GetType<!kMovingCollector>(); - if (field_type != nullptr) { - CHECK(field_type->IsAssignableFrom(new_value->GetClass())); - } - return; + ArtField* fields = cur->GetIFields(); + for (size_t i = 0, count = cur->NumInstanceFields(); i < count; ++i) { + StackHandleScope<1> hs(Thread::Current()); + Handle<Object> h_object(hs.NewHandle(new_value)); + ArtField* field = &fields[i]; + if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { + CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot); + // TODO: resolve the field type for moving GC. + mirror::Class* field_type = field->GetType<!kMovingCollector>(); + if (field_type != nullptr) { + CHECK(field_type->IsAssignableFrom(new_value->GetClass())); } + return; } } } @@ -228,20 +225,17 @@ void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_val return; } if (IsClass()) { - ObjectArray<ArtField>* fields = AsClass()->GetSFields(); - if (fields != NULL) { - size_t num_sfields = fields->GetLength(); - for (size_t i = 0; i < num_sfields; ++i) { - ArtField* field = fields->Get(i); - if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { - CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot); - // TODO: resolve the field type for moving GC. - mirror::Class* field_type = field->GetType<!kMovingCollector>(); - if (field_type != nullptr) { - CHECK(field_type->IsAssignableFrom(new_value->GetClass())); - } - return; + ArtField* fields = AsClass()->GetSFields(); + for (size_t i = 0, count = AsClass()->NumStaticFields(); i < count; ++i) { + ArtField* field = &fields[i]; + if (field->GetOffset().Int32Value() == field_offset.Int32Value()) { + CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot); + // TODO: resolve the field type for moving GC. + mirror::Class* field_type = field->GetType<!kMovingCollector>(); + if (field_type != nullptr) { + CHECK(field_type->IsAssignableFrom(new_value->GetClass())); } + return; } } } diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h index cfc8549..bfd5d4d 100644 --- a/runtime/mirror/object.h +++ b/runtime/mirror/object.h @@ -24,6 +24,7 @@ namespace art { +class ArtField; class ImageWriter; class LockWord; class Monitor; @@ -33,7 +34,6 @@ class VoidFunctor; namespace mirror { -class ArtField; class ArtMethod; class Array; class Class; @@ -191,12 +191,6 @@ class MANAGED LOCKABLE Object { template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - bool IsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - ArtField* AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h index 80d5135..30bc1cd 100644 --- a/runtime/mirror/object_array-inl.h +++ b/runtime/mirror/object_array-inl.h @@ -22,7 +22,6 @@ #include "array-inl.h" #include "base/stringprintf.h" #include "gc/heap.h" -#include "mirror/art_field.h" #include "mirror/class.h" #include "runtime.h" #include "handle_scope-inl.h" @@ -36,13 +35,13 @@ template<class T> inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class, int32_t length, gc::AllocatorType allocator_type) { Array* array = Array::Alloc<true>(self, object_array_class, length, - ComponentSizeShiftWidth<sizeof(HeapReference<Object>)>(), + ComponentSizeShiftWidth(sizeof(HeapReference<Object>)), allocator_type); if (UNLIKELY(array == nullptr)) { return nullptr; } else { DCHECK_EQ(array->GetClass()->GetComponentSizeShift(), - ComponentSizeShiftWidth<sizeof(HeapReference<Object>)>()); + ComponentSizeShiftWidth(sizeof(HeapReference<Object>))); return array->AsObjectArray<T>(); } } diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc index 1ce298d..747a008 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -722,14 +722,12 @@ TEST_F(ObjectTest, FindStaticField) { "Ljava/util/Comparator;") == NULL); // Right name and type. - Handle<ArtField> f1(hs.NewHandle( - c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"))); - Handle<ArtField> f2(hs.NewHandle( - mirror::Class::FindStaticField(soa.Self(), c, "CASE_INSENSITIVE_ORDER", - "Ljava/util/Comparator;"))); - EXPECT_TRUE(f1.Get() != NULL); - EXPECT_TRUE(f2.Get() != NULL); - EXPECT_EQ(f1.Get(), f2.Get()); + ArtField* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); + ArtField* f2 = mirror::Class::FindStaticField(soa.Self(), c, "CASE_INSENSITIVE_ORDER", + "Ljava/util/Comparator;"); + EXPECT_TRUE(f1 != NULL); + EXPECT_TRUE(f2 != NULL); + EXPECT_EQ(f1, f2); // TODO: test static fields via superclasses. // TODO: test static fields via interfaces. diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 760038a..1a6adf8 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -313,8 +313,8 @@ static void PreloadDexCachesResolveType(Thread* self, mirror::DexCache* dex_cach static void PreloadDexCachesResolveField(Handle<mirror::DexCache> dex_cache, uint32_t field_idx, bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtField* field = dex_cache->GetResolvedField(field_idx); - if (field != NULL) { + ArtField* field = dex_cache->GetResolvedField(field_idx, sizeof(void*)); + if (field != nullptr) { return; } const DexFile* dex_file = dex_cache->GetDexFile(); @@ -334,7 +334,7 @@ static void PreloadDexCachesResolveField(Handle<mirror::DexCache> dex_cache, uin return; } // LOG(INFO) << "VMRuntime.preloadDexCaches resolved field " << PrettyField(field); - dex_cache->SetResolvedField(field_idx, field); + dex_cache->SetResolvedField(field_idx, field, sizeof(void*)); } // Based on ClassLinker::ResolveMethod. @@ -437,7 +437,7 @@ static void PreloadDexCachesStatsFilled(DexCacheStats* filled) } } for (size_t j = 0; j < dex_cache->NumResolvedFields(); j++) { - mirror::ArtField* field = dex_cache->GetResolvedField(j); + ArtField* field = linker->GetResolvedField(j, dex_cache); if (field != NULL) { filled->num_fields++; } diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index b657aec..5ad18f8 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -16,12 +16,12 @@ #include "java_lang_Class.h" +#include "art_field-inl.h" #include "class_linker.h" #include "common_throws.h" #include "dex_file-inl.h" #include "jni_internal.h" #include "nth_caller_visitor.h" -#include "mirror/art_field-inl.h" #include "mirror/class-inl.h" #include "mirror/class_loader.h" #include "mirror/field-inl.h" @@ -119,33 +119,33 @@ static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) { static mirror::ObjectArray<mirror::Field>* GetDeclaredFields( Thread* self, mirror::Class* klass, bool public_only, bool force_resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - StackHandleScope<3> hs(self); - auto h_ifields = hs.NewHandle(klass->GetIFields()); - auto h_sfields = hs.NewHandle(klass->GetSFields()); - const int32_t num_ifields = h_ifields.Get() != nullptr ? h_ifields->GetLength() : 0; - const int32_t num_sfields = h_sfields.Get() != nullptr ? h_sfields->GetLength() : 0; - int32_t array_size = num_ifields + num_sfields; + StackHandleScope<1> hs(self); + auto* ifields = klass->GetIFields(); + auto* sfields = klass->GetSFields(); + const auto num_ifields = klass->NumInstanceFields(); + const auto num_sfields = klass->NumStaticFields(); + size_t array_size = num_ifields + num_sfields; if (public_only) { // Lets go subtract all the non public fields. - for (int32_t i = 0; i < num_ifields; ++i) { - if (!h_ifields->GetWithoutChecks(i)->IsPublic()) { + for (size_t i = 0; i < num_ifields; ++i) { + if (!ifields[i].IsPublic()) { --array_size; } } - for (int32_t i = 0; i < num_sfields; ++i) { - if (!h_sfields->GetWithoutChecks(i)->IsPublic()) { + for (size_t i = 0; i < num_sfields; ++i) { + if (!sfields[i].IsPublic()) { --array_size; } } } - int32_t array_idx = 0; + size_t array_idx = 0; auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc( self, mirror::Field::ArrayClass(), array_size)); if (object_array.Get() == nullptr) { return nullptr; } - for (int32_t i = 0; i < num_ifields; ++i) { - auto* art_field = h_ifields->GetWithoutChecks(i); + for (size_t i = 0; i < num_ifields; ++i) { + auto* art_field = &ifields[i]; if (!public_only || art_field->IsPublic()) { auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve); if (field == nullptr) { @@ -158,8 +158,8 @@ static mirror::ObjectArray<mirror::Field>* GetDeclaredFields( object_array->SetWithoutChecks<false>(array_idx++, field); } } - for (int32_t i = 0; i < num_sfields; ++i) { - auto* art_field = h_sfields->GetWithoutChecks(i); + for (size_t i = 0; i < num_sfields; ++i) { + auto* art_field = &sfields[i]; if (!public_only || art_field->IsPublic()) { auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve); if (field == nullptr) { @@ -197,17 +197,16 @@ static jobjectArray Class_getPublicDeclaredFields(JNIEnv* env, jobject javaThis) // Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use // the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly // fast. -ALWAYS_INLINE static inline mirror::ArtField* FindFieldByName( - Thread* self ATTRIBUTE_UNUSED, mirror::String* name, - mirror::ObjectArray<mirror::ArtField>* fields) +ALWAYS_INLINE static inline ArtField* FindFieldByName( + Thread* self ATTRIBUTE_UNUSED, mirror::String* name, ArtField* fields, size_t num_fields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - uint32_t low = 0; - uint32_t high = fields->GetLength(); + size_t low = 0; + size_t high = num_fields; const uint16_t* const data = name->GetCharArray()->GetData() + name->GetOffset(); const size_t length = name->GetLength(); while (low < high) { auto mid = (low + high) / 2; - mirror::ArtField* const field = fields->GetWithoutChecks(mid); + ArtField* const field = &fields[mid]; int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field->GetName(), data, length); // Alternate approach, only a few % faster at the cost of more allocations. // int result = field->GetStringName(self, true)->CompareTo(name); @@ -220,8 +219,8 @@ ALWAYS_INLINE static inline mirror::ArtField* FindFieldByName( } } if (kIsDebugBuild) { - for (int32_t i = 0; i < fields->GetLength(); ++i) { - CHECK_NE(fields->GetWithoutChecks(i)->GetName(), name->ToModifiedUtf8()); + for (size_t i = 0; i < num_fields; ++i) { + CHECK_NE(fields[i].GetName(), name->ToModifiedUtf8()); } } return nullptr; @@ -231,18 +230,14 @@ ALWAYS_INLINE static inline mirror::Field* GetDeclaredField( Thread* self, mirror::Class* c, mirror::String* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { auto* instance_fields = c->GetIFields(); - if (instance_fields != nullptr) { - auto* art_field = FindFieldByName(self, name, instance_fields); - if (art_field != nullptr) { - return mirror::Field::CreateFromArtField(self, art_field, true); - } + auto* art_field = FindFieldByName(self, name, instance_fields, c->NumInstanceFields()); + if (art_field != nullptr) { + return mirror::Field::CreateFromArtField(self, art_field, true); } auto* static_fields = c->GetSFields(); - if (static_fields != nullptr) { - auto* art_field = FindFieldByName(self, name, static_fields); - if (art_field != nullptr) { - return mirror::Field::CreateFromArtField(self, art_field, true); - } + art_field = FindFieldByName(self, name, static_fields, c->NumStaticFields()); + if (art_field != nullptr) { + return mirror::Field::CreateFromArtField(self, art_field, true); } return nullptr; } diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc index 1ffcbdf..681b261 100644 --- a/runtime/native/java_lang_reflect_Array.cc +++ b/runtime/native/java_lang_reflect_Array.cc @@ -63,7 +63,7 @@ static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementCl DCHECK(array_class->IsObjectArrayClass()); mirror::Array* new_array = mirror::Array::Alloc<true>( soa.Self(), array_class, length, - ComponentSizeShiftWidth<sizeof(mirror::HeapReference<mirror::Object>)>(), + ComponentSizeShiftWidth(sizeof(mirror::HeapReference<mirror::Object>)), runtime->GetHeap()->GetCurrentAllocator()); return soa.AddLocalReference<jobject>(new_array); } diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc index 765f548..5e1a4c5 100644 --- a/runtime/native/java_lang_reflect_Constructor.cc +++ b/runtime/native/java_lang_reflect_Constructor.cc @@ -57,8 +57,6 @@ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectA bool movable = true; if (!kMovingMethods && c->IsArtMethodClass()) { movable = false; - } else if (!kMovingFields && c->IsArtFieldClass()) { - movable = false; } else if (!kMovingClasses && c->IsClassClass()) { movable = false; } diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index d2362a2..37c6353 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -25,11 +25,11 @@ #include <backtrace/BacktraceMap.h> #include <gtest/gtest.h> +#include "art_field-inl.h" #include "class_linker.h" #include "common_runtime_test.h" #include "compiler_callbacks.h" #include "mem_map.h" -#include "mirror/art_field-inl.h" #include "os.h" #include "scoped_thread_state_change.h" #include "thread-inl.h" @@ -959,25 +959,25 @@ TEST_F(OatFileAssistantTest, DexOptStatusValues) { ASSERT_FALSE(dexfile.Get() == nullptr); linker->EnsureInitialized(soa.Self(), dexfile, true, true); - mirror::ArtField* no_dexopt_needed = mirror::Class::FindStaticField( + ArtField* no_dexopt_needed = mirror::Class::FindStaticField( soa.Self(), dexfile, "NO_DEXOPT_NEEDED", "I"); ASSERT_FALSE(no_dexopt_needed == nullptr); EXPECT_EQ(no_dexopt_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, no_dexopt_needed->GetInt(dexfile.Get())); - mirror::ArtField* dex2oat_needed = mirror::Class::FindStaticField( + ArtField* dex2oat_needed = mirror::Class::FindStaticField( soa.Self(), dexfile, "DEX2OAT_NEEDED", "I"); ASSERT_FALSE(dex2oat_needed == nullptr); EXPECT_EQ(dex2oat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, dex2oat_needed->GetInt(dexfile.Get())); - mirror::ArtField* patchoat_needed = mirror::Class::FindStaticField( + ArtField* patchoat_needed = mirror::Class::FindStaticField( soa.Self(), dexfile, "PATCHOAT_NEEDED", "I"); ASSERT_FALSE(patchoat_needed == nullptr); EXPECT_EQ(patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, patchoat_needed->GetInt(dexfile.Get())); - mirror::ArtField* self_patchoat_needed = mirror::Class::FindStaticField( + ArtField* self_patchoat_needed = mirror::Class::FindStaticField( soa.Self(), dexfile, "SELF_PATCHOAT_NEEDED", "I"); ASSERT_FALSE(self_patchoat_needed == nullptr); EXPECT_EQ(self_patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); diff --git a/runtime/primitive.h b/runtime/primitive.h index 32bfdaf..3818487 100644 --- a/runtime/primitive.h +++ b/runtime/primitive.h @@ -27,21 +27,11 @@ namespace art { static constexpr size_t kObjectReferenceSize = 4; -template<size_t kComponentSize> -size_t ComponentSizeShiftWidth() { - switch (kComponentSize) { - case 1: - return 0U; - case 2: - return 1U; - case 4: - return 2U; - case 8: - return 3U; - default: - LOG(FATAL) << "Unexpected component size : " << kComponentSize; - return 0U; - } +constexpr size_t ComponentSizeShiftWidth(size_t component_size) { + return component_size == 1u ? 0u : + component_size == 2u ? 1u : + component_size == 4u ? 2u : + component_size == 8u ? 3u : 0u; } class Primitive { @@ -95,7 +85,7 @@ class Primitive { case kPrimFloat: return 2; case kPrimLong: case kPrimDouble: return 3; - case kPrimNot: return ComponentSizeShiftWidth<kObjectReferenceSize>(); + case kPrimNot: return ComponentSizeShiftWidth(kObjectReferenceSize); default: LOG(FATAL) << "Invalid type " << static_cast<int>(type); return 0; diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc index cb97049..a3156b4 100644 --- a/runtime/proxy_test.cc +++ b/runtime/proxy_test.cc @@ -17,8 +17,8 @@ #include <jni.h> #include <vector> +#include "art_field-inl.h" #include "common_compiler_test.h" -#include "mirror/art_field-inl.h" #include "scoped_thread_state_change.h" namespace art { @@ -165,14 +165,12 @@ TEST_F(ProxyTest, ProxyFieldHelper) { ASSERT_TRUE(proxyClass->IsProxyClass()); ASSERT_TRUE(proxyClass->IsInitialized()); - Handle<mirror::ObjectArray<mirror::ArtField>> instance_fields( - hs.NewHandle(proxyClass->GetIFields())); - EXPECT_TRUE(instance_fields.Get() == nullptr); + ArtField* instance_fields = proxyClass->GetIFields(); + EXPECT_TRUE(instance_fields == nullptr); - Handle<mirror::ObjectArray<mirror::ArtField>> static_fields( - hs.NewHandle(proxyClass->GetSFields())); - ASSERT_TRUE(static_fields.Get() != nullptr); - ASSERT_EQ(2, static_fields->GetLength()); + ArtField* static_fields = proxyClass->GetSFields(); + ASSERT_TRUE(static_fields != nullptr); + ASSERT_EQ(2u, proxyClass->NumStaticFields()); Handle<mirror::Class> interfacesFieldClass( hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Class;"))); @@ -182,21 +180,21 @@ TEST_F(ProxyTest, ProxyFieldHelper) { ASSERT_TRUE(throwsFieldClass.Get() != nullptr); // Test "Class[] interfaces" field. - MutableHandle<mirror::ArtField> fhandle = hs.NewHandle(static_fields->Get(0)); - EXPECT_EQ("interfaces", std::string(fhandle->GetName())); - EXPECT_EQ("[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor())); - EXPECT_EQ(interfacesFieldClass.Get(), fhandle->GetType<true>()); + ArtField* field = &static_fields[0]; + EXPECT_STREQ("interfaces", field->GetName()); + EXPECT_STREQ("[Ljava/lang/Class;", field->GetTypeDescriptor()); + EXPECT_EQ(interfacesFieldClass.Get(), field->GetType<true>()); std::string temp; - EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp))); - EXPECT_FALSE(fhandle->IsPrimitiveType()); + EXPECT_STREQ("L$Proxy1234;", field->GetDeclaringClass()->GetDescriptor(&temp)); + EXPECT_FALSE(field->IsPrimitiveType()); // Test "Class[][] throws" field. - fhandle.Assign(static_fields->Get(1)); - EXPECT_EQ("throws", std::string(fhandle->GetName())); - EXPECT_EQ("[[Ljava/lang/Class;", std::string(fhandle->GetTypeDescriptor())); - EXPECT_EQ(throwsFieldClass.Get(), fhandle->GetType<true>()); - EXPECT_EQ("L$Proxy1234;", std::string(fhandle->GetDeclaringClass()->GetDescriptor(&temp))); - EXPECT_FALSE(fhandle->IsPrimitiveType()); + field = &static_fields[1]; + EXPECT_STREQ("throws", field->GetName()); + EXPECT_STREQ("[[Ljava/lang/Class;", field->GetTypeDescriptor()); + EXPECT_EQ(throwsFieldClass.Get(), field->GetType<true>()); + EXPECT_STREQ("L$Proxy1234;", field->GetDeclaringClass()->GetDescriptor(&temp)); + EXPECT_FALSE(field->IsPrimitiveType()); } } // namespace art diff --git a/runtime/quick/inline_method_analyser.cc b/runtime/quick/inline_method_analyser.cc index 44e2844..efaa0ac 100644 --- a/runtime/quick/inline_method_analyser.cc +++ b/runtime/quick/inline_method_analyser.cc @@ -15,18 +15,14 @@ */ #include "inline_method_analyser.h" + +#include "art_field-inl.h" #include "dex_file-inl.h" #include "dex_instruction.h" #include "dex_instruction-inl.h" -#include "mirror/art_field.h" -#include "mirror/art_field-inl.h" -#include "mirror/art_method.h" #include "mirror/art_method-inl.h" -#include "mirror/class.h" #include "mirror/class-inl.h" -#include "mirror/dex_cache.h" #include "mirror/dex_cache-inl.h" -#include "verifier/method_verifier.h" #include "verifier/method_verifier-inl.h" /* @@ -331,7 +327,7 @@ bool InlineMethodAnalyser::ComputeSpecialAccessorInfo(uint32_t field_idx, bool i mirror::DexCache* dex_cache = verifier->GetDexCache(); uint32_t method_idx = verifier->GetMethodReference().dex_method_index; mirror::ArtMethod* method = dex_cache->GetResolvedMethod(method_idx); - mirror::ArtField* field = dex_cache->GetResolvedField(field_idx); + ArtField* field = Runtime::Current()->GetClassLinker()->GetResolvedField(field_idx, dex_cache); if (method == nullptr || field == nullptr || field->IsStatic()) { return false; } diff --git a/runtime/read_barrier.h b/runtime/read_barrier.h index 471b37c..52d83a2 100644 --- a/runtime/read_barrier.h +++ b/runtime/read_barrier.h @@ -30,7 +30,6 @@ namespace art { namespace mirror { - class ArtField; class ArtMethod; class Object; template<typename MirrorType> class HeapReference; diff --git a/runtime/reflection.cc b/runtime/reflection.cc index 4e94de4..3e1315c 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -16,16 +16,15 @@ #include "reflection-inl.h" +#include "art_field-inl.h" #include "class_linker.h" #include "common_throws.h" #include "dex_file-inl.h" #include "entrypoints/entrypoint_utils.h" #include "jni_internal.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/object_array-inl.h" -#include "mirror/object_array.h" #include "nth_caller_visitor.h" #include "scoped_thread_state_change.h" #include "stack.h" @@ -238,13 +237,13 @@ class ArgArray { #define DO_FIRST_ARG(match_descriptor, get_fn, append) { \ if (LIKELY(arg != nullptr && arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \ - mirror::ArtField* primitive_field = arg->GetClass()->GetIFields()->Get(0); \ + ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ append(primitive_field-> get_fn(arg)); #define DO_ARG(match_descriptor, get_fn, append) \ } else if (LIKELY(arg != nullptr && \ arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \ - mirror::ArtField* primitive_field = arg->GetClass()->GetIFields()->Get(0); \ + ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ append(primitive_field-> get_fn(arg)); #define DO_FAIL(expected) \ @@ -692,7 +691,7 @@ mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) { return result.GetL(); } -static std::string UnboxingFailureKind(mirror::ArtField* f) +static std::string UnboxingFailureKind(ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (f != nullptr) { return "field " + PrettyField(f, false); @@ -701,7 +700,7 @@ static std::string UnboxingFailureKind(mirror::ArtField* f) } static bool UnboxPrimitive(mirror::Object* o, - mirror::Class* dst_class, mirror::ArtField* f, + mirror::Class* dst_class, ArtField* f, JValue* unboxed_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { bool unbox_for_result = (f == nullptr); @@ -742,8 +741,8 @@ static bool UnboxPrimitive(mirror::Object* o, JValue boxed_value; mirror::Class* klass = o->GetClass(); mirror::Class* src_class = nullptr; - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - mirror::ArtField* primitive_field = o->GetClass()->GetIFields()->Get(0); + ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); + ArtField* primitive_field = &klass->GetIFields()[0]; if (klass->DescriptorEquals("Ljava/lang/Boolean;")) { src_class = class_linker->FindPrimitiveClass('Z'); boxed_value.SetZ(primitive_field->GetBoolean(o)); @@ -782,7 +781,7 @@ static bool UnboxPrimitive(mirror::Object* o, boxed_value, unboxed_value); } -bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, mirror::ArtField* f, +bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, ArtField* f, JValue* unboxed_value) { DCHECK(f != nullptr); return UnboxPrimitive(o, dst_class, f, unboxed_value); diff --git a/runtime/reflection.h b/runtime/reflection.h index ff970e5..c2d406a 100644 --- a/runtime/reflection.h +++ b/runtime/reflection.h @@ -23,18 +23,18 @@ namespace art { namespace mirror { - class ArtField; class ArtMethod; class Class; class Object; } // namespace mirror +class ArtField; union JValue; class ScopedObjectAccessAlreadyRunnable; class ShadowFrame; mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); -bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, mirror::ArtField* f, +bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, ArtField* f, JValue* unboxed_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue* unboxed_value) diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 1cd0a96..66d38ce 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -48,6 +48,7 @@ #include "arch/x86/registers_x86.h" #include "arch/x86_64/quick_method_frame_info_x86_64.h" #include "arch/x86_64/registers_x86_64.h" +#include "art_field-inl.h" #include "asm_support.h" #include "atomic.h" #include "base/arena_allocator.h" @@ -70,8 +71,8 @@ #include "interpreter/interpreter.h" #include "jit/jit.h" #include "jni_internal.h" +#include "linear_alloc.h" #include "mirror/array.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/class_loader.h" @@ -257,7 +258,9 @@ Runtime::~Runtime() { VLOG(jit) << "Deleting jit"; jit_.reset(nullptr); } + linear_alloc_.reset(); arena_pool_.reset(); + low_4gb_arena_pool_.reset(); // Shutdown the fault manager if it was initialized. fault_manager.Shutdown(); @@ -441,7 +444,7 @@ static jobject CreateSystemClassLoader(Runtime* runtime) { hs.NewHandle(soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread))); CHECK(cl->EnsureInitialized(soa.Self(), thread_class, true, true)); - mirror::ArtField* contextClassLoader = + ArtField* contextClassLoader = thread_class->FindDeclaredInstanceField("contextClassLoader", "Ljava/lang/ClassLoader;"); CHECK(contextClassLoader != NULL); @@ -862,7 +865,14 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) // Use MemMap arena pool for jit, malloc otherwise. Malloc arenas are faster to allocate but // can't be trimmed as easily. const bool use_malloc = !use_jit; - arena_pool_.reset(new ArenaPool(use_malloc)); + arena_pool_.reset(new ArenaPool(use_malloc, false)); + if (IsCompiler() && Is64BitInstructionSet(kRuntimeISA)) { + // 4gb, no malloc. Explanation in header. + low_4gb_arena_pool_.reset(new ArenaPool(false, true)); + linear_alloc_.reset(new LinearAlloc(low_4gb_arena_pool_.get())); + } else { + linear_alloc_.reset(new LinearAlloc(arena_pool_.get())); + } BlockSignals(); InitPlatformSignalHandlers(); @@ -1294,7 +1304,6 @@ mirror::Throwable* Runtime::GetPreAllocatedNoClassDefFoundError() { 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::ArtField::VisitRoots(visitor); mirror::ArtMethod::VisitRoots(visitor); mirror::Class::VisitRoots(visitor); mirror::Reference::VisitRoots(visitor); diff --git a/runtime/runtime.h b/runtime/runtime.h index baa4d18..d95640d 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -42,6 +42,7 @@ namespace art { class ArenaPool; class CompilerCallbacks; +class LinearAlloc; namespace gc { class Heap; @@ -549,6 +550,9 @@ class Runtime { const ArenaPool* GetArenaPool() const { return arena_pool_.get(); } + LinearAlloc* GetLinearAlloc() { + return linear_alloc_.get(); + } jit::JitOptions* GetJITOptions() { return jit_options_.get(); @@ -618,6 +622,13 @@ class Runtime { gc::Heap* heap_; std::unique_ptr<ArenaPool> arena_pool_; + // Special low 4gb pool for compiler linear alloc. We need ArtFields to be in low 4gb if we are + // compiling using a 32 bit image on a 64 bit compiler in case we resolve things in the image + // since the field arrays are int arrays in this case. + std::unique_ptr<ArenaPool> low_4gb_arena_pool_; + + // Shared linear alloc for now. + std::unique_ptr<LinearAlloc> linear_alloc_; // The number of spins that are done before thread suspension is used to forcibly inflate. size_t max_spins_before_thin_lock_inflation_; diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h index adf3480..11b7df6 100644 --- a/runtime/scoped_thread_state_change.h +++ b/runtime/scoped_thread_state_change.h @@ -20,7 +20,7 @@ #include "base/casts.h" #include "java_vm_ext.h" #include "jni_env_ext-inl.h" -#include "mirror/art_field.h" +#include "art_field.h" #include "read_barrier.h" #include "thread-inl.h" #include "verify_object.h" @@ -148,20 +148,16 @@ class ScopedObjectAccessAlreadyRunnable { return down_cast<T>(Self()->DecodeJObject(obj)); } - mirror::ArtField* DecodeField(jfieldID fid) const + ArtField* DecodeField(jfieldID fid) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Locks::mutator_lock_->AssertSharedHeld(Self()); DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states. - CHECK(!kMovingFields); - mirror::ArtField* field = reinterpret_cast<mirror::ArtField*>(fid); - return ReadBarrier::BarrierForRoot<mirror::ArtField, kWithReadBarrier>(&field); + return reinterpret_cast<ArtField*>(fid); } - jfieldID EncodeField(mirror::ArtField* field) const - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + jfieldID EncodeField(ArtField* field) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Locks::mutator_lock_->AssertSharedHeld(Self()); DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states. - CHECK(!kMovingFields); return reinterpret_cast<jfieldID>(field); } diff --git a/runtime/thread.cc b/runtime/thread.cc index af11f73..58b272b 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -32,11 +32,11 @@ #include <sstream> #include "arch/context.h" +#include "art_field-inl.h" #include "base/mutex.h" #include "base/timing_logger.h" #include "base/to_str.h" #include "class_linker-inl.h" -#include "class_linker.h" #include "debugger.h" #include "dex_file-inl.h" #include "entrypoints/entrypoint_utils.h" @@ -47,10 +47,8 @@ #include "gc/heap.h" #include "gc/space/space.h" #include "handle_scope-inl.h" -#include "handle_scope.h" #include "indirect_reference_table-inl.h" #include "jni_internal.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class_loader.h" #include "mirror/class-inl.h" @@ -173,7 +171,7 @@ void* Thread::CreateCallback(void* arg) { self->tlsPtr_.jpeer = nullptr; self->SetThreadName(self->GetThreadName(soa)->ToModifiedUtf8().c_str()); - mirror::ArtField* priorityField = soa.DecodeField(WellKnownClasses::java_lang_Thread_priority); + ArtField* priorityField = soa.DecodeField(WellKnownClasses::java_lang_Thread_priority); self->SetNativePriority(priorityField->GetInt(self->tlsPtr_.opeer)); Dbg::PostThreadStart(self); @@ -190,7 +188,7 @@ void* Thread::CreateCallback(void* arg) { Thread* Thread::FromManagedThread(const ScopedObjectAccessAlreadyRunnable& soa, mirror::Object* thread_peer) { - mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer); + ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_nativePeer); Thread* result = reinterpret_cast<Thread*>(static_cast<uintptr_t>(f->GetLong(thread_peer))); // Sanity check that if we have a result it is either suspended or we hold the thread_list_lock_ // to stop it from going away. @@ -589,7 +587,7 @@ void Thread::Dump(std::ostream& os) const { } mirror::String* Thread::GetThreadName(const ScopedObjectAccessAlreadyRunnable& soa) const { - mirror::ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); + ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name); return (tlsPtr_.opeer != nullptr) ? reinterpret_cast<mirror::String*>(f->GetObject(tlsPtr_.opeer)) : nullptr; } @@ -794,7 +792,7 @@ void Thread::DumpState(std::ostream& os, const Thread* thread, pid_t tid) { soa.DecodeField(WellKnownClasses::java_lang_Thread_group)->GetObject(thread->tlsPtr_.opeer); if (thread_group != nullptr) { - mirror::ArtField* group_name_field = + ArtField* group_name_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name); mirror::String* group_name_string = reinterpret_cast<mirror::String*>(group_name_field->GetObject(thread_group)); diff --git a/runtime/trace.cc b/runtime/trace.cc index 5375dc0..7326865 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -582,7 +582,7 @@ void Trace::DexPcMoved(Thread* thread, mirror::Object* this_object, } void Trace::FieldRead(Thread* thread, mirror::Object* this_object, - mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field) + mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { UNUSED(thread, this_object, method, dex_pc, field); // We're not recorded to listen to this kind of event, so complain. @@ -590,7 +590,7 @@ void Trace::FieldRead(Thread* thread, mirror::Object* this_object, } void Trace::FieldWritten(Thread* thread, mirror::Object* this_object, - mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field, + mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field, const JValue& field_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { UNUSED(thread, this_object, method, dex_pc, field, field_value); diff --git a/runtime/trace.h b/runtime/trace.h index 80f926f..d8bd428 100644 --- a/runtime/trace.h +++ b/runtime/trace.h @@ -33,10 +33,10 @@ namespace art { namespace mirror { - class ArtField; class ArtMethod; } // namespace mirror +class ArtField; class Thread; enum TracingMode { @@ -99,10 +99,10 @@ class Trace FINAL : public instrumentation::InstrumentationListener { mirror::ArtMethod* method, uint32_t new_dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE; void FieldRead(Thread* thread, mirror::Object* this_object, - mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field) + mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE; void FieldWritten(Thread* thread, mirror::Object* this_object, - mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field, + mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field, const JValue& field_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE; void ExceptionCaught(Thread* thread, mirror::Throwable* exception_object) diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc index 24ecf6b..9792eca 100644 --- a/runtime/transaction_test.cc +++ b/runtime/transaction_test.cc @@ -16,9 +16,9 @@ #include "transaction.h" +#include "art_field-inl.h" #include "common_runtime_test.h" #include "mirror/array-inl.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "scoped_thread_state_change.h" @@ -181,47 +181,47 @@ TEST_F(TransactionTest, StaticFieldsTest) { ASSERT_FALSE(soa.Self()->IsExceptionPending()); // Lookup fields. - mirror::ArtField* booleanField = h_klass->FindDeclaredStaticField("booleanField", "Z"); + ArtField* booleanField = h_klass->FindDeclaredStaticField("booleanField", "Z"); ASSERT_TRUE(booleanField != nullptr); ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean); ASSERT_EQ(booleanField->GetBoolean(h_klass.Get()), false); - mirror::ArtField* byteField = h_klass->FindDeclaredStaticField("byteField", "B"); + ArtField* byteField = h_klass->FindDeclaredStaticField("byteField", "B"); ASSERT_TRUE(byteField != nullptr); ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte); ASSERT_EQ(byteField->GetByte(h_klass.Get()), 0); - mirror::ArtField* charField = h_klass->FindDeclaredStaticField("charField", "C"); + ArtField* charField = h_klass->FindDeclaredStaticField("charField", "C"); ASSERT_TRUE(charField != nullptr); ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar); ASSERT_EQ(charField->GetChar(h_klass.Get()), 0u); - mirror::ArtField* shortField = h_klass->FindDeclaredStaticField("shortField", "S"); + ArtField* shortField = h_klass->FindDeclaredStaticField("shortField", "S"); ASSERT_TRUE(shortField != nullptr); ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort); ASSERT_EQ(shortField->GetShort(h_klass.Get()), 0); - mirror::ArtField* intField = h_klass->FindDeclaredStaticField("intField", "I"); + ArtField* intField = h_klass->FindDeclaredStaticField("intField", "I"); ASSERT_TRUE(intField != nullptr); ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt); ASSERT_EQ(intField->GetInt(h_klass.Get()), 0); - mirror::ArtField* longField = h_klass->FindDeclaredStaticField("longField", "J"); + ArtField* longField = h_klass->FindDeclaredStaticField("longField", "J"); ASSERT_TRUE(longField != nullptr); ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong); ASSERT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0)); - mirror::ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F"); + ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F"); ASSERT_TRUE(floatField != nullptr); ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat); ASSERT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f)); - mirror::ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D"); + ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D"); ASSERT_TRUE(doubleField != nullptr); ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble); ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0)); - mirror::ArtField* objectField = h_klass->FindDeclaredStaticField("objectField", + ArtField* objectField = h_klass->FindDeclaredStaticField("objectField", "Ljava/lang/Object;"); ASSERT_TRUE(objectField != nullptr); ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot); @@ -283,47 +283,47 @@ TEST_F(TransactionTest, InstanceFieldsTest) { ASSERT_TRUE(h_instance.Get() != nullptr); // Lookup fields. - mirror::ArtField* booleanField = h_klass->FindDeclaredInstanceField("booleanField", "Z"); + ArtField* booleanField = h_klass->FindDeclaredInstanceField("booleanField", "Z"); ASSERT_TRUE(booleanField != nullptr); ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean); ASSERT_EQ(booleanField->GetBoolean(h_instance.Get()), false); - mirror::ArtField* byteField = h_klass->FindDeclaredInstanceField("byteField", "B"); + ArtField* byteField = h_klass->FindDeclaredInstanceField("byteField", "B"); ASSERT_TRUE(byteField != nullptr); ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte); ASSERT_EQ(byteField->GetByte(h_instance.Get()), 0); - mirror::ArtField* charField = h_klass->FindDeclaredInstanceField("charField", "C"); + ArtField* charField = h_klass->FindDeclaredInstanceField("charField", "C"); ASSERT_TRUE(charField != nullptr); ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar); ASSERT_EQ(charField->GetChar(h_instance.Get()), 0u); - mirror::ArtField* shortField = h_klass->FindDeclaredInstanceField("shortField", "S"); + ArtField* shortField = h_klass->FindDeclaredInstanceField("shortField", "S"); ASSERT_TRUE(shortField != nullptr); ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort); ASSERT_EQ(shortField->GetShort(h_instance.Get()), 0); - mirror::ArtField* intField = h_klass->FindDeclaredInstanceField("intField", "I"); + ArtField* intField = h_klass->FindDeclaredInstanceField("intField", "I"); ASSERT_TRUE(intField != nullptr); ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt); ASSERT_EQ(intField->GetInt(h_instance.Get()), 0); - mirror::ArtField* longField = h_klass->FindDeclaredInstanceField("longField", "J"); + ArtField* longField = h_klass->FindDeclaredInstanceField("longField", "J"); ASSERT_TRUE(longField != nullptr); ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong); ASSERT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0)); - mirror::ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F"); + ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F"); ASSERT_TRUE(floatField != nullptr); ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat); ASSERT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f)); - mirror::ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D"); + ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D"); ASSERT_TRUE(doubleField != nullptr); ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble); ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0)); - mirror::ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField", + ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField", "Ljava/lang/Object;"); ASSERT_TRUE(objectField != nullptr); ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot); @@ -381,63 +381,63 @@ TEST_F(TransactionTest, StaticArrayFieldsTest) { ASSERT_FALSE(soa.Self()->IsExceptionPending()); // Lookup fields. - mirror::ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z"); + ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z"); ASSERT_TRUE(booleanArrayField != nullptr); mirror::BooleanArray* booleanArray = booleanArrayField->GetObject(h_klass.Get())->AsBooleanArray(); ASSERT_TRUE(booleanArray != nullptr); ASSERT_EQ(booleanArray->GetLength(), 1); ASSERT_EQ(booleanArray->GetWithoutChecks(0), false); - mirror::ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B"); + ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B"); ASSERT_TRUE(byteArrayField != nullptr); mirror::ByteArray* byteArray = byteArrayField->GetObject(h_klass.Get())->AsByteArray(); ASSERT_TRUE(byteArray != nullptr); ASSERT_EQ(byteArray->GetLength(), 1); ASSERT_EQ(byteArray->GetWithoutChecks(0), 0); - mirror::ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C"); + ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C"); ASSERT_TRUE(charArrayField != nullptr); mirror::CharArray* charArray = charArrayField->GetObject(h_klass.Get())->AsCharArray(); ASSERT_TRUE(charArray != nullptr); ASSERT_EQ(charArray->GetLength(), 1); ASSERT_EQ(charArray->GetWithoutChecks(0), 0u); - mirror::ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S"); + ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S"); ASSERT_TRUE(shortArrayField != nullptr); mirror::ShortArray* shortArray = shortArrayField->GetObject(h_klass.Get())->AsShortArray(); ASSERT_TRUE(shortArray != nullptr); ASSERT_EQ(shortArray->GetLength(), 1); ASSERT_EQ(shortArray->GetWithoutChecks(0), 0); - mirror::ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I"); + ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I"); ASSERT_TRUE(intArrayField != nullptr); mirror::IntArray* intArray = intArrayField->GetObject(h_klass.Get())->AsIntArray(); ASSERT_TRUE(intArray != nullptr); ASSERT_EQ(intArray->GetLength(), 1); ASSERT_EQ(intArray->GetWithoutChecks(0), 0); - mirror::ArtField* longArrayField = h_klass->FindDeclaredStaticField("longArrayField", "[J"); + ArtField* longArrayField = h_klass->FindDeclaredStaticField("longArrayField", "[J"); ASSERT_TRUE(longArrayField != nullptr); mirror::LongArray* longArray = longArrayField->GetObject(h_klass.Get())->AsLongArray(); ASSERT_TRUE(longArray != nullptr); ASSERT_EQ(longArray->GetLength(), 1); ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0)); - mirror::ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F"); + ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F"); ASSERT_TRUE(floatArrayField != nullptr); mirror::FloatArray* floatArray = floatArrayField->GetObject(h_klass.Get())->AsFloatArray(); ASSERT_TRUE(floatArray != nullptr); ASSERT_EQ(floatArray->GetLength(), 1); ASSERT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f)); - mirror::ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D"); + ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D"); ASSERT_TRUE(doubleArrayField != nullptr); mirror::DoubleArray* doubleArray = doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray(); ASSERT_TRUE(doubleArray != nullptr); ASSERT_EQ(doubleArray->GetLength(), 1); ASSERT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f)); - mirror::ArtField* objectArrayField = h_klass->FindDeclaredStaticField("objectArrayField", + ArtField* objectArrayField = h_klass->FindDeclaredStaticField("objectArrayField", "[Ljava/lang/Object;"); ASSERT_TRUE(objectArrayField != nullptr); mirror::ObjectArray<mirror::Object>* objectArray = diff --git a/runtime/utils.cc b/runtime/utils.cc index 8a23ff7..f13da8b 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -25,10 +25,10 @@ #include <unistd.h> #include <memory> +#include "art_field-inl.h" #include "base/stl_util.h" #include "base/unix_file/fd_file.h" #include "dex_file-inl.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/class_loader.h" @@ -364,7 +364,7 @@ std::string PrettyDescriptor(const char* descriptor) { return result; } -std::string PrettyField(mirror::ArtField* f, bool with_type) { +std::string PrettyField(ArtField* f, bool with_type) { if (f == NULL) { return "null"; } diff --git a/runtime/utils.h b/runtime/utils.h index e6a6b1d..6dee5fe 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -33,10 +33,10 @@ namespace art { +class ArtField; class DexFile; namespace mirror { -class ArtField; class ArtMethod; class Class; class Object; @@ -343,7 +343,7 @@ std::string PrettyDescriptor(Primitive::Type type); // Returns a human-readable signature for 'f'. Something like "a.b.C.f" or // "int a.b.C.f" (depending on the value of 'with_type'). -std::string PrettyField(mirror::ArtField* f, bool with_type = true) +std::string PrettyField(ArtField* f, bool with_type = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type = true); diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc index 833427e..623a3ec 100644 --- a/runtime/utils_test.cc +++ b/runtime/utils_test.cc @@ -146,7 +146,7 @@ TEST_F(UtilsTest, PrettyField) { mirror::Class* java_lang_String = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;"); - mirror::ArtField* f; + ArtField* f; f = java_lang_String->FindDeclaredInstanceField("count", "I"); EXPECT_EQ("int java.lang.String.count", PrettyField(f)); EXPECT_EQ("java.lang.String.count", PrettyField(f, false)); diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 9fc2658..065df05 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -18,6 +18,7 @@ #include <iostream> +#include "art_field-inl.h" #include "base/logging.h" #include "base/mutex-inl.h" #include "class_linker.h" @@ -30,7 +31,6 @@ #include "indenter.h" #include "intern_table.h" #include "leb128.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/class.h" #include "mirror/class-inl.h" @@ -451,7 +451,7 @@ void MethodVerifier::FindLocksAtDexPc() { Verify(); } -mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m, +ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc) { Thread* self = Thread::Current(); StackHandleScope<3> hs(self); @@ -464,7 +464,7 @@ mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m, return verifier.FindAccessedFieldAtDexPc(dex_pc); } -mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(uint32_t dex_pc) { +ArtField* MethodVerifier::FindAccessedFieldAtDexPc(uint32_t dex_pc) { CHECK(code_item_ != nullptr); // This only makes sense for methods with code. // Strictly speaking, we ought to be able to get away with doing a subset of the full method @@ -3788,7 +3788,7 @@ void MethodVerifier::VerifyAPut(const Instruction* inst, } } -mirror::ArtField* MethodVerifier::GetStaticField(int field_idx) { +ArtField* MethodVerifier::GetStaticField(int field_idx) { const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx); // Check access to class const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_); @@ -3802,8 +3802,8 @@ mirror::ArtField* MethodVerifier::GetStaticField(int field_idx) { return nullptr; // Can't resolve Class so no more to do here, will do checking at runtime. } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - mirror::ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_, - class_loader_); + ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_, + class_loader_); if (field == nullptr) { VLOG(verifier) << "Unable to resolve static field " << field_idx << " (" << dex_file_->GetFieldName(field_id) << ") in " @@ -3823,7 +3823,7 @@ mirror::ArtField* MethodVerifier::GetStaticField(int field_idx) { return field; } -mirror::ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) { +ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) { const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx); // Check access to class const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_); @@ -3837,8 +3837,8 @@ mirror::ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int return nullptr; // Can't resolve Class so no more to do here } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - mirror::ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_, - class_loader_); + ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, dex_cache_, + class_loader_); if (field == nullptr) { VLOG(verifier) << "Unable to resolve instance field " << field_idx << " (" << dex_file_->GetFieldName(field_id) << ") in " @@ -3894,7 +3894,7 @@ template <MethodVerifier::FieldAccessType kAccType> void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& insn_type, bool is_primitive, bool is_static) { uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c(); - mirror::ArtField* field; + ArtField* field; if (is_static) { field = GetStaticField(field_idx); } else { @@ -3914,12 +3914,8 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& } } - mirror::Class* field_type_class; - { - StackHandleScope<1> hs(self_); - HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field)); - field_type_class = can_load_classes_ ? h_field->GetType<true>() : h_field->GetType<false>(); - } + mirror::Class* field_type_class = + can_load_classes_ ? field->GetType<true>() : field->GetType<false>(); if (field_type_class != nullptr) { field_type = ®_types_.FromClass(field->GetTypeDescriptor(), field_type_class, field_type_class->CannotBeAssignedFromOtherTypes()); @@ -3988,7 +3984,7 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& } } -mirror::ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst, +ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst, RegisterLine* reg_line) { DCHECK(IsInstructionIGetQuickOrIPutQuick(inst->Opcode())) << inst->Opcode(); const RegType& object_type = reg_line->GetRegisterType(this, inst->VRegB_22c()); @@ -3997,8 +3993,7 @@ mirror::ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst, return nullptr; } uint32_t field_offset = static_cast<uint32_t>(inst->VRegC_22c()); - mirror::ArtField* const f = mirror::ArtField::FindInstanceFieldWithOffset(object_type.GetClass(), - field_offset); + ArtField* const f = ArtField::FindInstanceFieldWithOffset(object_type.GetClass(), field_offset); DCHECK_EQ(f->GetOffset().Uint32Value(), field_offset); if (f == nullptr) { VLOG(verifier) << "Failed to find instance field at offset '" << field_offset @@ -4012,7 +4007,7 @@ void MethodVerifier::VerifyQuickFieldAccess(const Instruction* inst, const RegTy bool is_primitive) { DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_); - mirror::ArtField* field = GetQuickFieldAccess(inst, work_line_.get()); + ArtField* field = GetQuickFieldAccess(inst, work_line_.get()); if (field == nullptr) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer field from " << inst->Name(); return; @@ -4030,12 +4025,8 @@ void MethodVerifier::VerifyQuickFieldAccess(const Instruction* inst, const RegTy // Get the field type. const RegType* field_type; { - mirror::Class* field_type_class; - { - StackHandleScope<1> hs(Thread::Current()); - HandleWrapper<mirror::ArtField> h_field(hs.NewHandleWrapper(&field)); - field_type_class = can_load_classes_ ? h_field->GetType<true>() : h_field->GetType<false>(); - } + mirror::Class* field_type_class = can_load_classes_ ? field->GetType<true>() : + field->GetType<false>(); if (field_type_class != nullptr) { field_type = ®_types_.FromClass(field->GetTypeDescriptor(), field_type_class, diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 8c0321e..cd414c2 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -191,7 +191,7 @@ class MethodVerifier { // Returns the accessed field corresponding to the quick instruction's field // offset at 'dex_pc' in method 'm'. - static mirror::ArtField* FindAccessedFieldAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc) + static ArtField* FindAccessedFieldAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns the invoked method corresponding to the quick instruction's vtable @@ -250,7 +250,7 @@ class MethodVerifier { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Returns the access field of a quick field access (iget/iput-quick) or nullptr // if it cannot be found. - mirror::ArtField* GetQuickFieldAccess(const Instruction* inst, RegisterLine* reg_line) + ArtField* GetQuickFieldAccess(const Instruction* inst, RegisterLine* reg_line) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Is the method being verified a constructor? @@ -301,7 +301,7 @@ class MethodVerifier { void FindLocksAtDexPc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ArtField* FindAccessedFieldAtDexPc(uint32_t dex_pc) + ArtField* FindAccessedFieldAtDexPc(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::ArtMethod* FindInvokedMethodAtDexPc(uint32_t dex_pc) @@ -525,11 +525,11 @@ class MethodVerifier { bool is_primitive) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Lookup instance field and fail for resolution violations - mirror::ArtField* GetInstanceField(const RegType& obj_type, int field_idx) + ArtField* GetInstanceField(const RegType& obj_type, int field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Lookup static field and fail for resolution violations - mirror::ArtField* GetStaticField(int field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + ArtField* GetStaticField(int field_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Perform verification of an iget/sget/iput/sput instruction. enum class FieldAccessType { // private |