Move ArtField to native
Add linear alloc. Moved ArtField to be native object. Changed image
writer to put ArtFields after the mirror section.
Savings:
2MB on low ram devices
4MB on normal devices
Total PSS measurements before (normal N5, 95s after shell start):
Image size: 7729152 bytes
23112 kB: .NonMoving
23212 kB: .NonMoving
22868 kB: .NonMoving
23072 kB: .NonMoving
22836 kB: .NonMoving
19618 kB: .Zygote
19850 kB: .Zygote
19623 kB: .Zygote
19924 kB: .Zygote
19612 kB: .Zygote
Avg: 42745.4 kB
After:
Image size: 7462912 bytes
17440 kB: .NonMoving
16776 kB: .NonMoving
16804 kB: .NonMoving
17812 kB: .NonMoving
16820 kB: .NonMoving
18788 kB: .Zygote
18856 kB: .Zygote
19064 kB: .Zygote
18841 kB: .Zygote
18629 kB: .Zygote
3499 kB: .LinearAlloc
3408 kB: .LinearAlloc
3424 kB: .LinearAlloc
3600 kB: .LinearAlloc
3436 kB: .LinearAlloc
Avg: 39439.4 kB
No reflection performance changes.
Bug: 19264997
Bug: 17643507
Change-Id: I10c73a37913332080aeb978c7c94713bdfe4fe1c
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 @@
// 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 @@
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 @@
} 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 @@
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 @@
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 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 @@
*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::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 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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
} 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 @@
}
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 @@
// 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 @@
}
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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::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 @@
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 @@
}
};
+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 @@
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 @@
}
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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);
}
-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::FieldsSize(size_t num_elements) const {
+ return ArraySize(pointer_size_, num_elements);
}
-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::ElementOffset(size_t element_size, uint32_t idx) {
+ return mirror::Array::DataOffset(element_size).Uint32Value() + element_size * idx;
+}
+
+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 @@
// 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 @@
}
// 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 @@
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