Merge "Move backtrace logic to backtrace_helper.h"
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index aefdb54..d156644 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -714,7 +714,8 @@
class_linker->VisitClassesWithoutClassesLock(&visitor);
}
-static bool IsBootClassLoaderClass(mirror::Class* klass) REQUIRES_SHARED(Locks::mutator_lock_) {
+static bool IsBootClassLoaderClass(ObjPtr<mirror::Class> klass)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
return klass->GetClassLoader() == nullptr;
}
@@ -722,33 +723,33 @@
return IsBootClassLoaderClass(klass) && !IsInBootImage(klass);
}
-bool ImageWriter::PruneAppImageClass(mirror::Class* klass) {
+bool ImageWriter::PruneAppImageClass(ObjPtr<mirror::Class> klass) {
bool early_exit = false;
std::unordered_set<mirror::Class*> visited;
return PruneAppImageClassInternal(klass, &early_exit, &visited);
}
bool ImageWriter::PruneAppImageClassInternal(
- mirror::Class* klass,
+ ObjPtr<mirror::Class> klass,
bool* early_exit,
std::unordered_set<mirror::Class*>* visited) {
DCHECK(early_exit != nullptr);
DCHECK(visited != nullptr);
DCHECK(compile_app_image_);
- if (klass == nullptr || IsInBootImage(klass)) {
+ if (klass == nullptr || IsInBootImage(klass.Ptr())) {
return false;
}
- auto found = prune_class_memo_.find(klass);
+ auto found = prune_class_memo_.find(klass.Ptr());
if (found != prune_class_memo_.end()) {
// Already computed, return the found value.
return found->second;
}
// Circular dependencies, return false but do not store the result in the memoization table.
- if (visited->find(klass) != visited->end()) {
+ if (visited->find(klass.Ptr()) != visited->end()) {
*early_exit = true;
return false;
}
- visited->emplace(klass);
+ visited->emplace(klass.Ptr());
bool result = IsBootClassLoaderClass(klass);
std::string temp;
// Prune if not an image class, this handles any broken sets of image classes such as having a
@@ -812,20 +813,20 @@
dex_file_oat_index_map_.find(dex_cache->GetDexFile()) == dex_file_oat_index_map_.end();
}
// Erase the element we stored earlier since we are exiting the function.
- auto it = visited->find(klass);
+ auto it = visited->find(klass.Ptr());
DCHECK(it != visited->end());
visited->erase(it);
// Only store result if it is true or none of the calls early exited due to circular
// dependencies. If visited is empty then we are the root caller, in this case the cycle was in
// a child call and we can remember the result.
if (result == true || !my_early_exit || visited->empty()) {
- prune_class_memo_[klass] = result;
+ prune_class_memo_[klass.Ptr()] = result;
}
*early_exit |= my_early_exit;
return result;
}
-bool ImageWriter::KeepClass(Class* klass) {
+bool ImageWriter::KeepClass(ObjPtr<mirror::Class> klass) {
if (klass == nullptr) {
return false;
}
@@ -896,15 +897,27 @@
Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader);
class_table->Visit(classes_visitor);
removed_class_count_ += classes_visitor.Prune();
+
+ // Record app image class loader. The fake boot class loader should not get registered
+ // and we should end up with only one class loader for an app and none for boot image.
+ if (class_loader != nullptr && class_table != nullptr) {
+ DCHECK(class_loader_ == nullptr);
+ class_loader_ = class_loader;
+ }
}
size_t GetRemovedClassCount() const {
return removed_class_count_;
}
+ ObjPtr<mirror::ClassLoader> GetClassLoader() const REQUIRES_SHARED(Locks::mutator_lock_) {
+ return class_loader_;
+ }
+
private:
ImageWriter* const image_writer_;
size_t removed_class_count_;
+ ObjPtr<mirror::ClassLoader> class_loader_;
};
void ImageWriter::VisitClassLoaders(ClassLoaderVisitor* visitor) {
@@ -913,69 +926,149 @@
Runtime::Current()->GetClassLinker()->VisitClassLoaders(visitor);
}
+void ImageWriter::PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache,
+ ObjPtr<mirror::ClassLoader> class_loader) {
+ // To ensure deterministic contents of the hash-based arrays, each slot shall contain
+ // the candidate with the lowest index. As we're processing entries in increasing index
+ // order, this means trying to look up the entry for the current index if the slot is
+ // empty or if it contains a higher index.
+
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ ArtMethod* resolution_method = runtime->GetResolutionMethod();
+ const DexFile& dex_file = *dex_cache->GetDexFile();
+ // Prune methods.
+ ArtMethod** resolved_methods = dex_cache->GetResolvedMethods();
+ for (size_t i = 0, num = dex_cache->NumResolvedMethods(); i != num; ++i) {
+ ArtMethod* method =
+ mirror::DexCache::GetElementPtrSize(resolved_methods, i, target_ptr_size_);
+ DCHECK(method != nullptr) << "Expected resolution method instead of null method";
+ mirror::Class* declaring_class = method->GetDeclaringClass();
+ // Copied methods may be held live by a class which was not an image class but have a
+ // declaring class which is an image class. Set it to the resolution method to be safe and
+ // prevent dangling pointers.
+ if (method->IsCopied() || !KeepClass(declaring_class)) {
+ mirror::DexCache::SetElementPtrSize(resolved_methods,
+ i,
+ resolution_method,
+ target_ptr_size_);
+ } else if (kIsDebugBuild) {
+ // Check that the class is still in the classes table.
+ ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ CHECK(class_linker->ClassInClassTable(declaring_class)) << "Class "
+ << Class::PrettyClass(declaring_class) << " not in class linker table";
+ }
+ }
+ // Prune fields and make the contents of the field array deterministic.
+ mirror::FieldDexCacheType* resolved_fields = dex_cache->GetResolvedFields();
+ dex::TypeIndex last_class_idx; // Initialized to invalid index.
+ ObjPtr<mirror::Class> last_class = nullptr;
+ for (size_t i = 0, end = dex_file.NumFieldIds(); i < end; ++i) {
+ uint32_t slot_idx = dex_cache->FieldSlotIndex(i);
+ auto pair = mirror::DexCache::GetNativePairPtrSize(resolved_fields, slot_idx, target_ptr_size_);
+ uint32_t stored_index = pair.index;
+ ArtField* field = pair.object;
+ if (field != nullptr && i > stored_index) {
+ continue; // Already checked.
+ }
+ // Check if the referenced class is in the image. Note that we want to check the referenced
+ // class rather than the declaring class to preserve the semantics, i.e. using a FieldId
+ // results in resolving the referenced class and that can for example throw OOME.
+ const DexFile::FieldId& field_id = dex_file.GetFieldId(i);
+ if (field_id.class_idx_ != last_class_idx) {
+ last_class_idx = field_id.class_idx_;
+ last_class = class_linker->LookupResolvedType(
+ dex_file, last_class_idx, dex_cache, class_loader);
+ if (last_class != nullptr && !KeepClass(last_class)) {
+ last_class = nullptr;
+ }
+ }
+ if (field == nullptr || i < stored_index) {
+ if (last_class != nullptr) {
+ const char* name = dex_file.StringDataByIdx(field_id.name_idx_);
+ const char* type = dex_file.StringByTypeIdx(field_id.type_idx_);
+ field = mirror::Class::FindField(Thread::Current(), last_class, name, type);
+ if (field != nullptr) {
+ // If the referenced class is in the image, the defining class must also be there.
+ DCHECK(KeepClass(field->GetDeclaringClass()));
+ dex_cache->SetResolvedField(i, field, target_ptr_size_);
+ }
+ }
+ } else {
+ DCHECK_EQ(i, stored_index);
+ if (last_class == nullptr) {
+ dex_cache->ClearResolvedField(stored_index, target_ptr_size_);
+ }
+ }
+ }
+ // Prune types and make the contents of the type array deterministic.
+ // This is done after fields and methods as their lookup can touch the types array.
+ for (size_t i = 0, end = dex_cache->GetDexFile()->NumTypeIds(); i < end; ++i) {
+ dex::TypeIndex type_idx(i);
+ uint32_t slot_idx = dex_cache->TypeSlotIndex(type_idx);
+ mirror::TypeDexCachePair pair =
+ dex_cache->GetResolvedTypes()[slot_idx].load(std::memory_order_relaxed);
+ uint32_t stored_index = pair.index;
+ ObjPtr<mirror::Class> klass = pair.object.Read();
+ if (klass == nullptr || i < stored_index) {
+ klass = class_linker->LookupResolvedType(dex_file, type_idx, dex_cache, class_loader);
+ if (klass != nullptr) {
+ DCHECK_EQ(dex_cache->GetResolvedType(type_idx), klass);
+ stored_index = i; // For correct clearing below if not keeping the `klass`.
+ }
+ } else if (i == stored_index && !KeepClass(klass)) {
+ dex_cache->ClearResolvedType(dex::TypeIndex(stored_index));
+ }
+ }
+ // Strings do not need pruning, but the contents of the string array must be deterministic.
+ for (size_t i = 0, end = dex_cache->GetDexFile()->NumStringIds(); i < end; ++i) {
+ dex::StringIndex string_idx(i);
+ uint32_t slot_idx = dex_cache->StringSlotIndex(string_idx);
+ mirror::StringDexCachePair pair =
+ dex_cache->GetStrings()[slot_idx].load(std::memory_order_relaxed);
+ uint32_t stored_index = pair.index;
+ ObjPtr<mirror::String> string = pair.object.Read();
+ if (string == nullptr || i < stored_index) {
+ string = class_linker->LookupString(dex_file, string_idx, dex_cache);
+ DCHECK(string == nullptr || dex_cache->GetResolvedString(string_idx) == string);
+ }
+ }
+}
+
void ImageWriter::PruneNonImageClasses() {
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
Thread* self = Thread::Current();
+ ScopedAssertNoThreadSuspension sa(__FUNCTION__);
// Clear class table strong roots so that dex caches can get pruned. We require pruning the class
// path dex caches.
class_linker->ClearClassTableStrongRoots();
// Remove the undesired classes from the class roots.
+ ObjPtr<mirror::ClassLoader> class_loader;
{
PruneClassLoaderClassesVisitor class_loader_visitor(this);
VisitClassLoaders(&class_loader_visitor);
VLOG(compiler) << "Pruned " << class_loader_visitor.GetRemovedClassCount() << " classes";
+ class_loader = class_loader_visitor.GetClassLoader();
+ DCHECK_EQ(class_loader != nullptr, compile_app_image_);
}
// Clear references to removed classes from the DexCaches.
- ArtMethod* resolution_method = runtime->GetResolutionMethod();
-
- ScopedAssertNoThreadSuspension sa(__FUNCTION__);
- ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); // For ClassInClassTable
- ReaderMutexLock mu2(self, *Locks::dex_lock_);
- for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
- if (self->IsJWeakCleared(data.weak_root)) {
- continue;
- }
- ObjPtr<mirror::DexCache> dex_cache = self->DecodeJObject(data.weak_root)->AsDexCache();
- for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
- mirror::TypeDexCachePair pair =
- dex_cache->GetResolvedTypes()[i].load(std::memory_order_relaxed);
- mirror::Class* klass = pair.object.Read();
- if (klass != nullptr && !KeepClass(klass)) {
- dex_cache->ClearResolvedType(dex::TypeIndex(pair.index));
+ std::vector<ObjPtr<mirror::DexCache>> dex_caches;
+ {
+ ReaderMutexLock mu2(self, *Locks::dex_lock_);
+ dex_caches.reserve(class_linker->GetDexCachesData().size());
+ for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
+ if (self->IsJWeakCleared(data.weak_root)) {
+ continue;
}
+ dex_caches.push_back(self->DecodeJObject(data.weak_root)->AsDexCache());
}
- ArtMethod** resolved_methods = dex_cache->GetResolvedMethods();
- for (size_t i = 0, num = dex_cache->NumResolvedMethods(); i != num; ++i) {
- ArtMethod* method =
- mirror::DexCache::GetElementPtrSize(resolved_methods, i, target_ptr_size_);
- DCHECK(method != nullptr) << "Expected resolution method instead of null method";
- mirror::Class* declaring_class = method->GetDeclaringClass();
- // Copied methods may be held live by a class which was not an image class but have a
- // declaring class which is an image class. Set it to the resolution method to be safe and
- // prevent dangling pointers.
- if (method->IsCopied() || !KeepClass(declaring_class)) {
- mirror::DexCache::SetElementPtrSize(resolved_methods,
- i,
- resolution_method,
- target_ptr_size_);
- } else {
- // Check that the class is still in the classes table.
- DCHECK(class_linker->ClassInClassTable(declaring_class)) << "Class "
- << Class::PrettyClass(declaring_class) << " not in class linker table";
- }
- }
- mirror::FieldDexCacheType* resolved_fields = dex_cache->GetResolvedFields();
- for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
- auto pair = mirror::DexCache::GetNativePairPtrSize(resolved_fields, i, target_ptr_size_);
- ArtField* field = pair.object;
- if (field != nullptr && !KeepClass(field->GetDeclaringClass().Ptr())) {
- dex_cache->ClearResolvedField(pair.index, target_ptr_size_);
- }
- }
+ }
+ for (ObjPtr<mirror::DexCache> dex_cache : dex_caches) {
+ PruneAndPreloadDexCache(dex_cache, class_loader);
}
// Drop the array class cache in the ClassLinker, as these are roots holding those classes live.
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index bdc7146..16aff61 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -376,7 +376,7 @@
}
// Returns true if the class was in the original requested image classes list.
- bool KeepClass(mirror::Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
+ bool KeepClass(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
// Debug aid that list of requested image classes.
void DumpImageClasses();
@@ -391,6 +391,12 @@
// Remove unwanted classes from various roots.
void PruneNonImageClasses() REQUIRES_SHARED(Locks::mutator_lock_);
+ // Remove unwanted classes from the DexCache roots and preload deterministic DexCache contents.
+ void PruneAndPreloadDexCache(ObjPtr<mirror::DexCache> dex_cache,
+ ObjPtr<mirror::ClassLoader> class_loader)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(!Locks::classlinker_classes_lock_);
+
// Verify unwanted classes removed.
void CheckNonImageClassesRemoved() REQUIRES_SHARED(Locks::mutator_lock_);
static void CheckNonImageClassesRemovedCallback(mirror::Object* obj, void* arg)
@@ -473,11 +479,11 @@
// we also cannot have any classes which refer to these boot class loader non image classes.
// PruneAppImageClass also prunes if klass depends on a non-image class according to the compiler
// driver.
- bool PruneAppImageClass(mirror::Class* klass)
+ bool PruneAppImageClass(ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
// early_exit is true if we had a cyclic dependency anywhere down the chain.
- bool PruneAppImageClassInternal(mirror::Class* klass,
+ bool PruneAppImageClassInternal(ObjPtr<mirror::Class> klass,
bool* early_exit,
std::unordered_set<mirror::Class*>* visited)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 8e25aa3..105db1d 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -1440,12 +1440,10 @@
mirror::String* GetTargetString(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
ScopedObjectAccessUnchecked soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
ClassLinker* linker = Runtime::Current()->GetClassLinker();
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(GetDexCache(patch.TargetStringDexFile())));
mirror::String* string = linker->LookupString(*patch.TargetStringDexFile(),
patch.TargetStringIndex(),
- dex_cache);
+ GetDexCache(patch.TargetStringDexFile()));
DCHECK(string != nullptr);
DCHECK(writer_->HasBootImage() ||
Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(string));
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 958c1a6..4db4796 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -967,7 +967,7 @@
size_t CodeGeneratorX86::SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
if (GetGraph()->HasSIMD()) {
- __ movupd(Address(ESP, stack_index), XmmRegister(reg_id));
+ __ movups(Address(ESP, stack_index), XmmRegister(reg_id));
} else {
__ movsd(Address(ESP, stack_index), XmmRegister(reg_id));
}
@@ -976,7 +976,7 @@
size_t CodeGeneratorX86::RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
if (GetGraph()->HasSIMD()) {
- __ movupd(XmmRegister(reg_id), Address(ESP, stack_index));
+ __ movups(XmmRegister(reg_id), Address(ESP, stack_index));
} else {
__ movsd(XmmRegister(reg_id), Address(ESP, stack_index));
}
@@ -5713,9 +5713,8 @@
// In suspend check slow path, usually there are no caller-save registers at all.
// If SIMD instructions are present, however, we force spilling all live SIMD
// registers in full width (since the runtime only saves/restores lower part).
- locations->SetCustomSlowPathCallerSaves(GetGraph()->HasSIMD()
- ? RegisterSet::AllFpu()
- : RegisterSet::Empty());
+ locations->SetCustomSlowPathCallerSaves(
+ GetGraph()->HasSIMD() ? RegisterSet::AllFpu() : RegisterSet::Empty());
}
void InstructionCodeGeneratorX86::VisitSuspendCheck(HSuspendCheck* instruction) {
@@ -5818,9 +5817,11 @@
__ movd(destination.AsRegisterPairHigh<Register>(), src_reg);
} else if (destination.IsStackSlot()) {
__ movss(Address(ESP, destination.GetStackIndex()), source.AsFpuRegister<XmmRegister>());
- } else {
- DCHECK(destination.IsDoubleStackSlot());
+ } else if (destination.IsDoubleStackSlot()) {
__ movsd(Address(ESP, destination.GetStackIndex()), source.AsFpuRegister<XmmRegister>());
+ } else {
+ DCHECK(destination.IsSIMDStackSlot());
+ __ movups(Address(ESP, destination.GetStackIndex()), source.AsFpuRegister<XmmRegister>());
}
} else if (source.IsStackSlot()) {
if (destination.IsRegister()) {
@@ -5842,6 +5843,9 @@
DCHECK(destination.IsDoubleStackSlot()) << destination;
MoveMemoryToMemory64(destination.GetStackIndex(), source.GetStackIndex());
}
+ } else if (source.IsSIMDStackSlot()) {
+ DCHECK(destination.IsFpuRegister());
+ __ movups(destination.AsFpuRegister<XmmRegister>(), Address(ESP, source.GetStackIndex()));
} else if (source.IsConstant()) {
HConstant* constant = source.GetConstant();
if (constant->IsIntConstant() || constant->IsNullConstant()) {
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index c106d9b..2ffc398 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1162,7 +1162,7 @@
size_t CodeGeneratorX86_64::SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
if (GetGraph()->HasSIMD()) {
- __ movupd(Address(CpuRegister(RSP), stack_index), XmmRegister(reg_id));
+ __ movups(Address(CpuRegister(RSP), stack_index), XmmRegister(reg_id));
} else {
__ movsd(Address(CpuRegister(RSP), stack_index), XmmRegister(reg_id));
}
@@ -1171,7 +1171,7 @@
size_t CodeGeneratorX86_64::RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) {
if (GetGraph()->HasSIMD()) {
- __ movupd(XmmRegister(reg_id), Address(CpuRegister(RSP), stack_index));
+ __ movups(XmmRegister(reg_id), Address(CpuRegister(RSP), stack_index));
} else {
__ movsd(XmmRegister(reg_id), Address(CpuRegister(RSP), stack_index));
}
@@ -5166,9 +5166,8 @@
// In suspend check slow path, usually there are no caller-save registers at all.
// If SIMD instructions are present, however, we force spilling all live SIMD
// registers in full width (since the runtime only saves/restores lower part).
- locations->SetCustomSlowPathCallerSaves(GetGraph()->HasSIMD()
- ? RegisterSet::AllFpu()
- : RegisterSet::Empty());
+ locations->SetCustomSlowPathCallerSaves(
+ GetGraph()->HasSIMD() ? RegisterSet::AllFpu() : RegisterSet::Empty());
}
void InstructionCodeGeneratorX86_64::VisitSuspendCheck(HSuspendCheck* instruction) {
@@ -5257,6 +5256,10 @@
__ movq(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
__ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
}
+ } else if (source.IsSIMDStackSlot()) {
+ DCHECK(destination.IsFpuRegister());
+ __ movups(destination.AsFpuRegister<XmmRegister>(),
+ Address(CpuRegister(RSP), source.GetStackIndex()));
} else if (source.IsConstant()) {
HConstant* constant = source.GetConstant();
if (constant->IsIntConstant() || constant->IsNullConstant()) {
@@ -5307,10 +5310,13 @@
} else if (destination.IsStackSlot()) {
__ movss(Address(CpuRegister(RSP), destination.GetStackIndex()),
source.AsFpuRegister<XmmRegister>());
- } else {
- DCHECK(destination.IsDoubleStackSlot()) << destination;
+ } else if (destination.IsDoubleStackSlot()) {
__ movsd(Address(CpuRegister(RSP), destination.GetStackIndex()),
source.AsFpuRegister<XmmRegister>());
+ } else {
+ DCHECK(destination.IsSIMDStackSlot());
+ __ movups(Address(CpuRegister(RSP), destination.GetStackIndex()),
+ source.AsFpuRegister<XmmRegister>());
}
}
}
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 2bf5c53..0dfae11 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -322,9 +322,11 @@
codegen_.DumpCoreRegister(stream, location.high());
} else if (location.IsUnallocated()) {
stream << "unallocated";
- } else {
- DCHECK(location.IsDoubleStackSlot());
+ } else if (location.IsDoubleStackSlot()) {
stream << "2x" << location.GetStackIndex() << "(sp)";
+ } else {
+ DCHECK(location.IsSIMDStackSlot());
+ stream << "4x" << location.GetStackIndex() << "(sp)";
}
}
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 9550a53..62f5114 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -292,18 +292,7 @@
return nullptr;
}
PointerSize pointer_size = caller_compilation_unit_.GetClassLinker()->GetImagePointerSize();
- ArtMethod* single_impl = resolved_method->GetSingleImplementation(pointer_size);
- if (single_impl == nullptr) {
- return nullptr;
- }
- if (single_impl->IsProxyMethod()) {
- // Proxy method is a generic invoker that's not worth
- // devirtualizing/inlining. It also causes issues when the proxy
- // method is in another dex file if we try to rewrite invoke-interface to
- // invoke-virtual because a proxy method doesn't have a real dex file.
- return nullptr;
- }
- return single_impl;
+ return resolved_method->GetSingleImplementation(pointer_size);
}
bool HInliner::TryInline(HInvoke* invoke_instruction) {
@@ -1032,23 +1021,11 @@
HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
if (!TryBuildAndInline(invoke_instruction, method, receiver_type, &return_replacement)) {
if (invoke_instruction->IsInvokeInterface()) {
- DCHECK(!method->IsProxyMethod());
// Turn an invoke-interface into an invoke-virtual. An invoke-virtual is always
// better than an invoke-interface because:
// 1) In the best case, the interface call has one more indirection (to fetch the IMT).
// 2) We will not go to the conflict trampoline with an invoke-virtual.
// TODO: Consider sharpening once it is not dependent on the compiler driver.
-
- if (method->IsDefault() && !method->IsCopied()) {
- // Changing to invoke-virtual cannot be done on an original default method
- // since it's not in any vtable. Devirtualization by exact type/inline-cache
- // always uses a method in the iftable which is never an original default
- // method.
- // On the other hand, inlining an original default method by CHA is fine.
- DCHECK(cha_devirtualize);
- return false;
- }
-
const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
uint32_t dex_method_index = FindMethodIndexIn(
method, caller_dex_file, invoke_instruction->GetDexMethodIndex());
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index ba006ed..bf85b19 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -2559,7 +2559,7 @@
// void java.lang.String.getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
void IntrinsicLocationsBuilderMIPS::VisitStringGetCharsNoCheck(HInvoke* invoke) {
LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kCallOnMainOnly,
+ LocationSummary::kNoCall,
kIntrinsified);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
@@ -2567,17 +2567,9 @@
locations->SetInAt(3, Location::RequiresRegister());
locations->SetInAt(4, Location::RequiresRegister());
- // We will call memcpy() to do the actual work. Allocate the temporary
- // registers to use the correct input registers, and output register.
- // memcpy() uses the normal MIPS calling convention.
- InvokeRuntimeCallingConvention calling_convention;
-
- locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
- locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
- locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
-
- Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimInt);
- locations->AddTemp(Location::RegisterLocation(outLocation.AsRegister<Register>()));
+ locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister());
}
void IntrinsicCodeGeneratorMIPS::VisitStringGetCharsNoCheck(HInvoke* invoke) {
@@ -2596,16 +2588,11 @@
Register dstBegin = locations->InAt(4).AsRegister<Register>();
Register dstPtr = locations->GetTemp(0).AsRegister<Register>();
- DCHECK_EQ(dstPtr, A0);
Register srcPtr = locations->GetTemp(1).AsRegister<Register>();
- DCHECK_EQ(srcPtr, A1);
Register numChrs = locations->GetTemp(2).AsRegister<Register>();
- DCHECK_EQ(numChrs, A2);
-
- Register dstReturn = locations->GetTemp(3).AsRegister<Register>();
- DCHECK_EQ(dstReturn, V0);
MipsLabel done;
+ MipsLabel loop;
// Location of data in char array buffer.
const uint32_t data_offset = mirror::Array::DataOffset(char_size).Uint32Value();
@@ -2634,7 +2621,7 @@
__ LoadFromOffset(kLoadWord, TMP, srcObj, count_offset);
__ Sll(TMP, TMP, 31);
- // If string is uncompressed, use memcpy() path.
+ // If string is uncompressed, use uncompressed path.
__ Bnez(TMP, &uncompressed_copy);
// Copy loop for compressed src, copying 1 character (8-bit) to (16-bit) at a time.
@@ -2660,10 +2647,13 @@
__ Addu(srcPtr, srcPtr, AT);
}
- // Calculate number of bytes to copy from number of characters.
- __ Sll(numChrs, numChrs, char_shift);
-
- codegen_->InvokeRuntime(kQuickMemcpy, invoke, invoke->GetDexPc(), nullptr);
+ __ Bind(&loop);
+ __ Lh(AT, srcPtr, 0);
+ __ Addiu(numChrs, numChrs, -1);
+ __ Addiu(srcPtr, srcPtr, char_size);
+ __ Sh(AT, dstPtr, 0);
+ __ Addiu(dstPtr, dstPtr, char_size);
+ __ Bnez(numChrs, &loop);
__ Bind(&done);
}
diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc
index 21c5074..1ee89cf 100644
--- a/compiler/optimizing/intrinsics_mips64.cc
+++ b/compiler/optimizing/intrinsics_mips64.cc
@@ -1895,7 +1895,7 @@
// void java.lang.String.getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
void IntrinsicLocationsBuilderMIPS64::VisitStringGetCharsNoCheck(HInvoke* invoke) {
LocationSummary* locations = new (arena_) LocationSummary(invoke,
- LocationSummary::kCallOnMainOnly,
+ LocationSummary::kNoCall,
kIntrinsified);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
@@ -1903,17 +1903,9 @@
locations->SetInAt(3, Location::RequiresRegister());
locations->SetInAt(4, Location::RequiresRegister());
- // We will call memcpy() to do the actual work. Allocate the temporary
- // registers to use the correct input registers, and output register.
- // memcpy() uses the normal MIPS calling conventions.
- InvokeRuntimeCallingConvention calling_convention;
-
- locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
- locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
- locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
-
- Location outLocation = calling_convention.GetReturnLocation(Primitive::kPrimLong);
- locations->AddTemp(Location::RegisterLocation(outLocation.AsRegister<GpuRegister>()));
+ locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister());
}
void IntrinsicCodeGeneratorMIPS64::VisitStringGetCharsNoCheck(HInvoke* invoke) {
@@ -1932,16 +1924,11 @@
GpuRegister dstBegin = locations->InAt(4).AsRegister<GpuRegister>();
GpuRegister dstPtr = locations->GetTemp(0).AsRegister<GpuRegister>();
- DCHECK_EQ(dstPtr, A0);
GpuRegister srcPtr = locations->GetTemp(1).AsRegister<GpuRegister>();
- DCHECK_EQ(srcPtr, A1);
GpuRegister numChrs = locations->GetTemp(2).AsRegister<GpuRegister>();
- DCHECK_EQ(numChrs, A2);
-
- GpuRegister dstReturn = locations->GetTemp(3).AsRegister<GpuRegister>();
- DCHECK_EQ(dstReturn, V0);
Mips64Label done;
+ Mips64Label loop;
// Location of data in char array buffer.
const uint32_t data_offset = mirror::Array::DataOffset(char_size).Uint32Value();
@@ -1965,7 +1952,7 @@
__ LoadFromOffset(kLoadWord, TMP, srcObj, count_offset);
__ Dext(TMP, TMP, 0, 1);
- // If string is uncompressed, use memcpy() path.
+ // If string is uncompressed, use uncompressed path.
__ Bnezc(TMP, &uncompressed_copy);
// Copy loop for compressed src, copying 1 character (8-bit) to (16-bit) at a time.
@@ -1986,10 +1973,13 @@
__ Daddiu(srcPtr, srcObj, value_offset);
__ Dlsa(srcPtr, srcBegin, srcPtr, char_shift);
- // Calculate number of bytes to copy from number of characters.
- __ Dsll(numChrs, numChrs, char_shift);
-
- codegen_->InvokeRuntime(kQuickMemcpy, invoke, invoke->GetDexPc(), nullptr);
+ __ Bind(&loop);
+ __ Lh(AT, srcPtr, 0);
+ __ Daddiu(numChrs, numChrs, -1);
+ __ Daddiu(srcPtr, srcPtr, char_size);
+ __ Sh(AT, dstPtr, 0);
+ __ Daddiu(dstPtr, dstPtr, char_size);
+ __ Bnezc(numChrs, &loop);
__ Bind(&done);
}
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index d391f69..6f0dbce 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -69,11 +69,13 @@
// We do not use the value 9 because it conflicts with kLocationConstantMask.
kDoNotUse9 = 9,
+ kSIMDStackSlot = 10, // 128bit stack slot. TODO: generalize with encoded #bytes?
+
// Unallocated location represents a location that is not fixed and can be
// allocated by a register allocator. Each unallocated location has
// a policy that specifies what kind of location is suitable. Payload
// contains register allocation policy.
- kUnallocated = 10,
+ kUnallocated = 11,
};
Location() : ValueObject(), value_(kInvalid) {
@@ -82,6 +84,7 @@
static_assert((kUnallocated & kLocationConstantMask) != kConstant, "TagError");
static_assert((kStackSlot & kLocationConstantMask) != kConstant, "TagError");
static_assert((kDoubleStackSlot & kLocationConstantMask) != kConstant, "TagError");
+ static_assert((kSIMDStackSlot & kLocationConstantMask) != kConstant, "TagError");
static_assert((kRegister & kLocationConstantMask) != kConstant, "TagError");
static_assert((kFpuRegister & kLocationConstantMask) != kConstant, "TagError");
static_assert((kRegisterPair & kLocationConstantMask) != kConstant, "TagError");
@@ -266,8 +269,20 @@
return GetKind() == kDoubleStackSlot;
}
+ static Location SIMDStackSlot(intptr_t stack_index) {
+ uintptr_t payload = EncodeStackIndex(stack_index);
+ Location loc(kSIMDStackSlot, payload);
+ // Ensure that sign is preserved.
+ DCHECK_EQ(loc.GetStackIndex(), stack_index);
+ return loc;
+ }
+
+ bool IsSIMDStackSlot() const {
+ return GetKind() == kSIMDStackSlot;
+ }
+
intptr_t GetStackIndex() const {
- DCHECK(IsStackSlot() || IsDoubleStackSlot());
+ DCHECK(IsStackSlot() || IsDoubleStackSlot() || IsSIMDStackSlot());
// Decode stack index manually to preserve sign.
return GetPayload() - kStackIndexBias;
}
@@ -315,6 +330,7 @@
case kRegister: return "R";
case kStackSlot: return "S";
case kDoubleStackSlot: return "DS";
+ case kSIMDStackSlot: return "SIMD";
case kUnallocated: return "U";
case kConstant: return "C";
case kFpuRegister: return "F";
diff --git a/compiler/optimizing/register_allocation_resolver.cc b/compiler/optimizing/register_allocation_resolver.cc
index 0d33b49..c6a0b6a 100644
--- a/compiler/optimizing/register_allocation_resolver.cc
+++ b/compiler/optimizing/register_allocation_resolver.cc
@@ -303,6 +303,7 @@
switch (interval->NumberOfSpillSlotsNeeded()) {
case 1: loc = Location::StackSlot(interval->GetParent()->GetSpillSlot()); break;
case 2: loc = Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot()); break;
+ case 4: loc = Location::SIMDStackSlot(interval->GetParent()->GetSpillSlot()); break;
default: LOG(FATAL) << "Unexpected number of spill slots"; UNREACHABLE();
}
InsertMoveAfter(interval->GetDefinedBy(), interval->ToLocation(), loc);
@@ -464,6 +465,7 @@
switch (parent->NumberOfSpillSlotsNeeded()) {
case 1: location_source = Location::StackSlot(parent->GetSpillSlot()); break;
case 2: location_source = Location::DoubleStackSlot(parent->GetSpillSlot()); break;
+ case 4: location_source = Location::SIMDStackSlot(parent->GetSpillSlot()); break;
default: LOG(FATAL) << "Unexpected number of spill slots"; UNREACHABLE();
}
}
@@ -496,7 +498,8 @@
|| destination.IsFpuRegister()
|| destination.IsFpuRegisterPair()
|| destination.IsStackSlot()
- || destination.IsDoubleStackSlot();
+ || destination.IsDoubleStackSlot()
+ || destination.IsSIMDStackSlot();
}
void RegisterAllocationResolver::AddMove(HParallelMove* move,
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 7bd38c7..eedaf6e 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -259,7 +259,7 @@
} else if (runtime->UseJitCompilation()) {
// TODO: Make sure we don't set the "compile PIC" flag for JIT as that's bogus.
// DCHECK(!codegen_->GetCompilerOptions().GetCompilePic());
- string = class_linker->LookupString(dex_file, string_index, dex_cache);
+ string = class_linker->LookupString(dex_file, string_index, dex_cache.Get());
if (string != nullptr) {
if (runtime->GetHeap()->ObjectIsInBootImageSpace(string)) {
desired_load_kind = HLoadString::LoadKind::kBootImageAddress;
@@ -271,7 +271,7 @@
}
} else {
// AOT app compilation. Try to lookup the string without allocating if not found.
- string = class_linker->LookupString(dex_file, string_index, dex_cache);
+ string = class_linker->LookupString(dex_file, string_index, dex_cache.Get());
if (string != nullptr &&
runtime->GetHeap()->ObjectIsInBootImageSpace(string) &&
!codegen_->GetCompilerOptions().GetCompilePic()) {
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index c0a045c..36ee5a9 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -470,6 +470,8 @@
}
size_t LiveInterval::NumberOfSpillSlotsNeeded() const {
+ // TODO: detect vector operation.
+ // Return number of needed spill slots based on type.
return (type_ == Primitive::kPrimLong || type_ == Primitive::kPrimDouble) ? 2 : 1;
}
@@ -497,6 +499,7 @@
switch (NumberOfSpillSlotsNeeded()) {
case 1: return Location::StackSlot(GetParent()->GetSpillSlot());
case 2: return Location::DoubleStackSlot(GetParent()->GetSpillSlot());
+ case 4: return Location::SIMDStackSlot(GetParent()->GetSpillSlot());
default: LOG(FATAL) << "Unexpected number of spill slots"; UNREACHABLE();
}
} else {
diff --git a/compiler/utils/jni_macro_assembler.cc b/compiler/utils/jni_macro_assembler.cc
index 2f154fb..3ac6c3c 100644
--- a/compiler/utils/jni_macro_assembler.cc
+++ b/compiler/utils/jni_macro_assembler.cc
@@ -84,7 +84,11 @@
MacroAsm64UniquePtr JNIMacroAssembler<PointerSize::k64>::Create(
ArenaAllocator* arena,
InstructionSet instruction_set,
- const InstructionSetFeatures* instruction_set_features ATTRIBUTE_UNUSED) {
+ const InstructionSetFeatures* instruction_set_features) {
+#ifndef ART_ENABLE_CODEGEN_mips64
+ UNUSED(instruction_set_features);
+#endif
+
switch (instruction_set) {
#ifdef ART_ENABLE_CODEGEN_arm64
case kArm64:
@@ -92,7 +96,11 @@
#endif
#ifdef ART_ENABLE_CODEGEN_mips64
case kMips64:
- return MacroAsm64UniquePtr(new (arena) mips64::Mips64Assembler(arena));
+ return MacroAsm64UniquePtr(new (arena) mips64::Mips64Assembler(
+ arena,
+ instruction_set_features != nullptr
+ ? instruction_set_features->AsMips64InstructionSetFeatures()
+ : nullptr));
#endif
#ifdef ART_ENABLE_CODEGEN_x86_64
case kX86_64:
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
index 4e7f635..8a5ae75 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -1180,373 +1180,456 @@
Nor(rd, rs, ZERO);
}
-// TODO: Check for MSA presence in Mips64InstructionSetFeatures for each MSA instruction.
-
void Mips64Assembler::AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1e);
}
void Mips64Assembler::OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1e);
}
void Mips64Assembler::NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1e);
}
void Mips64Assembler::XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1e);
}
void Mips64Assembler::AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xe);
}
void Mips64Assembler::AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xe);
}
void Mips64Assembler::AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xe);
}
void Mips64Assembler::AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xe);
}
void Mips64Assembler::SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xe);
}
void Mips64Assembler::SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xe);
}
void Mips64Assembler::SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xe);
}
void Mips64Assembler::SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xe);
}
void Mips64Assembler::MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x12);
}
void Mips64Assembler::MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x12);
}
void Mips64Assembler::MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x12);
}
void Mips64Assembler::MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x12);
}
void Mips64Assembler::Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x4, 0x0, wt, ws, wd, 0x12);
}
void Mips64Assembler::Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x4, 0x1, wt, ws, wd, 0x12);
}
void Mips64Assembler::Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x4, 0x2, wt, ws, wd, 0x12);
}
void Mips64Assembler::Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x4, 0x3, wt, ws, wd, 0x12);
}
void Mips64Assembler::Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x5, 0x0, wt, ws, wd, 0x12);
}
void Mips64Assembler::Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x5, 0x1, wt, ws, wd, 0x12);
}
void Mips64Assembler::Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x5, 0x2, wt, ws, wd, 0x12);
}
void Mips64Assembler::Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x5, 0x3, wt, ws, wd, 0x12);
}
void Mips64Assembler::Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x6, 0x0, wt, ws, wd, 0x12);
}
void Mips64Assembler::Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x6, 0x1, wt, ws, wd, 0x12);
}
void Mips64Assembler::Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x6, 0x2, wt, ws, wd, 0x12);
}
void Mips64Assembler::Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x6, 0x3, wt, ws, wd, 0x12);
}
void Mips64Assembler::Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x7, 0x0, wt, ws, wd, 0x12);
}
void Mips64Assembler::Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x7, 0x1, wt, ws, wd, 0x12);
}
void Mips64Assembler::Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x7, 0x2, wt, ws, wd, 0x12);
}
void Mips64Assembler::Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x7, 0x3, wt, ws, wd, 0x12);
}
void Mips64Assembler::FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x0, wt, ws, wd, 0x1b);
}
void Mips64Assembler::FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x1, wt, ws, wd, 0x1b);
}
void Mips64Assembler::FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x2, wt, ws, wd, 0x1b);
}
void Mips64Assembler::FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x3, wt, ws, wd, 0x1b);
}
void Mips64Assembler::FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x0, wt, ws, wd, 0x1b);
}
void Mips64Assembler::FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x1, wt, ws, wd, 0x1b);
}
void Mips64Assembler::FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x2, wt, ws, wd, 0x1b);
}
void Mips64Assembler::FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x3, wt, ws, wd, 0x1b);
}
void Mips64Assembler::Ffint_sW(VectorRegister wd, VectorRegister ws) {
+ CHECK(HasMsa());
EmitMsa2RF(0x19e, 0x0, ws, wd, 0x1e);
}
void Mips64Assembler::Ffint_sD(VectorRegister wd, VectorRegister ws) {
+ CHECK(HasMsa());
EmitMsa2RF(0x19e, 0x1, ws, wd, 0x1e);
}
void Mips64Assembler::Ftint_sW(VectorRegister wd, VectorRegister ws) {
+ CHECK(HasMsa());
EmitMsa2RF(0x19c, 0x0, ws, wd, 0x1e);
}
void Mips64Assembler::Ftint_sD(VectorRegister wd, VectorRegister ws) {
+ CHECK(HasMsa());
EmitMsa2RF(0x19c, 0x1, ws, wd, 0x1e);
}
void Mips64Assembler::SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x0, wt, ws, wd, 0xd);
}
void Mips64Assembler::SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x1, wt, ws, wd, 0xd);
}
void Mips64Assembler::SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x2, wt, ws, wd, 0xd);
}
void Mips64Assembler::SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x0, 0x3, wt, ws, wd, 0xd);
}
void Mips64Assembler::SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x0, wt, ws, wd, 0xd);
}
void Mips64Assembler::SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x1, wt, ws, wd, 0xd);
}
void Mips64Assembler::SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x2, wt, ws, wd, 0xd);
}
void Mips64Assembler::SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x1, 0x3, wt, ws, wd, 0xd);
}
void Mips64Assembler::SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x2, 0x0, wt, ws, wd, 0xd);
}
void Mips64Assembler::SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x2, 0x1, wt, ws, wd, 0xd);
}
void Mips64Assembler::SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x2, 0x2, wt, ws, wd, 0xd);
}
void Mips64Assembler::SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt) {
+ CHECK(HasMsa());
EmitMsa3R(0x2, 0x3, wt, ws, wd, 0xd);
}
void Mips64Assembler::SlliB(VectorRegister wd, VectorRegister ws, int shamt3) {
+ CHECK(HasMsa());
CHECK(IsUint<3>(shamt3)) << shamt3;
EmitMsaBIT(0x0, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
}
void Mips64Assembler::SlliH(VectorRegister wd, VectorRegister ws, int shamt4) {
+ CHECK(HasMsa());
CHECK(IsUint<4>(shamt4)) << shamt4;
EmitMsaBIT(0x0, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
}
void Mips64Assembler::SlliW(VectorRegister wd, VectorRegister ws, int shamt5) {
+ CHECK(HasMsa());
CHECK(IsUint<5>(shamt5)) << shamt5;
EmitMsaBIT(0x0, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
}
void Mips64Assembler::SlliD(VectorRegister wd, VectorRegister ws, int shamt6) {
+ CHECK(HasMsa());
CHECK(IsUint<6>(shamt6)) << shamt6;
EmitMsaBIT(0x0, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
}
void Mips64Assembler::SraiB(VectorRegister wd, VectorRegister ws, int shamt3) {
+ CHECK(HasMsa());
CHECK(IsUint<3>(shamt3)) << shamt3;
EmitMsaBIT(0x1, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
}
void Mips64Assembler::SraiH(VectorRegister wd, VectorRegister ws, int shamt4) {
+ CHECK(HasMsa());
CHECK(IsUint<4>(shamt4)) << shamt4;
EmitMsaBIT(0x1, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
}
void Mips64Assembler::SraiW(VectorRegister wd, VectorRegister ws, int shamt5) {
+ CHECK(HasMsa());
CHECK(IsUint<5>(shamt5)) << shamt5;
EmitMsaBIT(0x1, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
}
void Mips64Assembler::SraiD(VectorRegister wd, VectorRegister ws, int shamt6) {
+ CHECK(HasMsa());
CHECK(IsUint<6>(shamt6)) << shamt6;
EmitMsaBIT(0x1, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
}
void Mips64Assembler::SrliB(VectorRegister wd, VectorRegister ws, int shamt3) {
+ CHECK(HasMsa());
CHECK(IsUint<3>(shamt3)) << shamt3;
EmitMsaBIT(0x2, shamt3 | kMsaDfMByteMask, ws, wd, 0x9);
}
void Mips64Assembler::SrliH(VectorRegister wd, VectorRegister ws, int shamt4) {
+ CHECK(HasMsa());
CHECK(IsUint<4>(shamt4)) << shamt4;
EmitMsaBIT(0x2, shamt4 | kMsaDfMHalfwordMask, ws, wd, 0x9);
}
void Mips64Assembler::SrliW(VectorRegister wd, VectorRegister ws, int shamt5) {
+ CHECK(HasMsa());
CHECK(IsUint<5>(shamt5)) << shamt5;
EmitMsaBIT(0x2, shamt5 | kMsaDfMWordMask, ws, wd, 0x9);
}
void Mips64Assembler::SrliD(VectorRegister wd, VectorRegister ws, int shamt6) {
+ CHECK(HasMsa());
CHECK(IsUint<6>(shamt6)) << shamt6;
EmitMsaBIT(0x2, shamt6 | kMsaDfMDoublewordMask, ws, wd, 0x9);
}
void Mips64Assembler::MoveV(VectorRegister wd, VectorRegister ws) {
+ CHECK(HasMsa());
EmitMsaBIT(0x1, 0x3e, ws, wd, 0x19);
}
void Mips64Assembler::SplatiB(VectorRegister wd, VectorRegister ws, int n4) {
+ CHECK(HasMsa());
CHECK(IsUint<4>(n4)) << n4;
EmitMsaELM(0x1, n4 | kMsaDfNByteMask, ws, wd, 0x19);
}
void Mips64Assembler::SplatiH(VectorRegister wd, VectorRegister ws, int n3) {
+ CHECK(HasMsa());
CHECK(IsUint<3>(n3)) << n3;
EmitMsaELM(0x1, n3 | kMsaDfNHalfwordMask, ws, wd, 0x19);
}
void Mips64Assembler::SplatiW(VectorRegister wd, VectorRegister ws, int n2) {
+ CHECK(HasMsa());
CHECK(IsUint<2>(n2)) << n2;
EmitMsaELM(0x1, n2 | kMsaDfNWordMask, ws, wd, 0x19);
}
void Mips64Assembler::SplatiD(VectorRegister wd, VectorRegister ws, int n1) {
+ CHECK(HasMsa());
CHECK(IsUint<1>(n1)) << n1;
EmitMsaELM(0x1, n1 | kMsaDfNDoublewordMask, ws, wd, 0x19);
}
void Mips64Assembler::FillB(VectorRegister wd, GpuRegister rs) {
+ CHECK(HasMsa());
EmitMsa2R(0xc0, 0x0, static_cast<VectorRegister>(rs), wd, 0x1e);
}
void Mips64Assembler::FillH(VectorRegister wd, GpuRegister rs) {
+ CHECK(HasMsa());
EmitMsa2R(0xc0, 0x1, static_cast<VectorRegister>(rs), wd, 0x1e);
}
void Mips64Assembler::FillW(VectorRegister wd, GpuRegister rs) {
+ CHECK(HasMsa());
EmitMsa2R(0xc0, 0x2, static_cast<VectorRegister>(rs), wd, 0x1e);
}
void Mips64Assembler::FillD(VectorRegister wd, GpuRegister rs) {
+ CHECK(HasMsa());
EmitMsa2R(0xc0, 0x3, static_cast<VectorRegister>(rs), wd, 0x1e);
}
void Mips64Assembler::LdB(VectorRegister wd, GpuRegister rs, int offset) {
+ CHECK(HasMsa());
CHECK(IsInt<10>(offset)) << offset;
EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x8, 0x0);
}
void Mips64Assembler::LdH(VectorRegister wd, GpuRegister rs, int offset) {
+ CHECK(HasMsa());
CHECK(IsInt<11>(offset)) << offset;
CHECK_ALIGNED(offset, kMips64HalfwordSize);
EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x8, 0x1);
}
void Mips64Assembler::LdW(VectorRegister wd, GpuRegister rs, int offset) {
+ CHECK(HasMsa());
CHECK(IsInt<12>(offset)) << offset;
CHECK_ALIGNED(offset, kMips64WordSize);
EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x8, 0x2);
}
void Mips64Assembler::LdD(VectorRegister wd, GpuRegister rs, int offset) {
+ CHECK(HasMsa());
CHECK(IsInt<13>(offset)) << offset;
CHECK_ALIGNED(offset, kMips64DoublewordSize);
EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x8, 0x3);
}
void Mips64Assembler::StB(VectorRegister wd, GpuRegister rs, int offset) {
+ CHECK(HasMsa());
CHECK(IsInt<10>(offset)) << offset;
EmitMsaMI10(offset & kMsaS10Mask, rs, wd, 0x9, 0x0);
}
void Mips64Assembler::StH(VectorRegister wd, GpuRegister rs, int offset) {
+ CHECK(HasMsa());
CHECK(IsInt<11>(offset)) << offset;
CHECK_ALIGNED(offset, kMips64HalfwordSize);
EmitMsaMI10((offset >> TIMES_2) & kMsaS10Mask, rs, wd, 0x9, 0x1);
}
void Mips64Assembler::StW(VectorRegister wd, GpuRegister rs, int offset) {
+ CHECK(HasMsa());
CHECK(IsInt<12>(offset)) << offset;
CHECK_ALIGNED(offset, kMips64WordSize);
EmitMsaMI10((offset >> TIMES_4) & kMsaS10Mask, rs, wd, 0x9, 0x2);
}
void Mips64Assembler::StD(VectorRegister wd, GpuRegister rs, int offset) {
+ CHECK(HasMsa());
CHECK(IsInt<13>(offset)) << offset;
CHECK_ALIGNED(offset, kMips64DoublewordSize);
EmitMsaMI10((offset >> TIMES_8) & kMsaS10Mask, rs, wd, 0x9, 0x3);
diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h
index f42c162..a8035b6 100644
--- a/compiler/utils/mips64/assembler_mips64.h
+++ b/compiler/utils/mips64/assembler_mips64.h
@@ -21,6 +21,7 @@
#include <utility>
#include <vector>
+#include "arch/mips64/instruction_set_features_mips64.h"
#include "base/arena_containers.h"
#include "base/enums.h"
#include "base/macros.h"
@@ -413,7 +414,8 @@
public:
using JNIBase = JNIMacroAssembler<PointerSize::k64>;
- explicit Mips64Assembler(ArenaAllocator* arena)
+ explicit Mips64Assembler(ArenaAllocator* arena,
+ const Mips64InstructionSetFeatures* instruction_set_features = nullptr)
: Assembler(arena),
overwriting_(false),
overwrite_location_(0),
@@ -422,7 +424,8 @@
jump_tables_(arena->Adapter(kArenaAllocAssembler)),
last_position_adjustment_(0),
last_old_position_(0),
- last_branch_id_(0) {
+ last_branch_id_(0),
+ has_msa_(instruction_set_features != nullptr ? instruction_set_features->HasMsa() : false) {
cfi().DelayEmittingAdvancePCs();
}
@@ -1479,6 +1482,10 @@
// Emits exception block.
void EmitExceptionPoll(Mips64ExceptionSlowPath* exception);
+ bool HasMsa() const {
+ return has_msa_;
+ }
+
// List of exception blocks to generate at the end of the code cache.
std::vector<Mips64ExceptionSlowPath> exception_blocks_;
@@ -1502,6 +1509,8 @@
uint32_t last_old_position_;
uint32_t last_branch_id_;
+ const bool has_msa_;
+
DISALLOW_COPY_AND_ASSIGN(Mips64Assembler);
};
diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc
index 12660ce..cadbe27 100644
--- a/compiler/utils/mips64/assembler_mips64_test.cc
+++ b/compiler/utils/mips64/assembler_mips64_test.cc
@@ -46,6 +46,9 @@
uint32_t,
mips64::VectorRegister> Base;
+ AssemblerMIPS64Test()
+ : instruction_set_features_(Mips64InstructionSetFeatures::FromVariant("default", nullptr)) {}
+
protected:
// Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
std::string GetArchitectureString() OVERRIDE {
@@ -78,6 +81,10 @@
return " -D -bbinary -mmips:isa64r6";
}
+ mips64::Mips64Assembler* CreateAssembler(ArenaAllocator* arena) OVERRIDE {
+ return new (arena) mips64::Mips64Assembler(arena, instruction_set_features_.get());
+ }
+
void SetUpHelpers() OVERRIDE {
if (registers_.size() == 0) {
registers_.push_back(new mips64::GpuRegister(mips64::ZERO));
@@ -313,8 +320,9 @@
std::vector<mips64::FpuRegister*> fp_registers_;
std::vector<mips64::VectorRegister*> vec_registers_;
-};
+ std::unique_ptr<const Mips64InstructionSetFeatures> instruction_set_features_;
+};
TEST_F(AssemblerMIPS64Test, Toolchain) {
EXPECT_TRUE(CheckTools());
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 8f09cc6..2248c3b 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -691,7 +691,7 @@
// Pointer to JNI function registered to this method, or a function to resolve the JNI function,
// or the profiling data for non-native methods, or an ImtConflictTable, or the
- // single-implementation of an abstract/interface method.
+ // single-implementation of an abstract method.
void* data_;
// Method dispatch from quick compiled code invokes this pointer which may cause bridging into
diff --git a/runtime/cha.cc b/runtime/cha.cc
index 7948c29..eaba01b 100644
--- a/runtime/cha.cc
+++ b/runtime/cha.cc
@@ -210,7 +210,7 @@
}
}
-void ClassHierarchyAnalysis::CheckVirtualMethodSingleImplementationInfo(
+void ClassHierarchyAnalysis::CheckSingleImplementationInfo(
Handle<mirror::Class> klass,
ArtMethod* virtual_method,
ArtMethod* method_in_super,
@@ -290,9 +290,8 @@
// A non-abstract method overrides an abstract method.
if (method_in_super->GetSingleImplementation(pointer_size) == nullptr) {
// Abstract method_in_super has no implementation yet.
- // We need to grab cha_lock_ since there may be multiple class linking
- // going on that can check/modify the single-implementation flag/method
- // of method_in_super.
+ // We need to grab cha_lock_ for further checking/updating due to possible
+ // races.
MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
if (!method_in_super->HasSingleImplementation()) {
return;
@@ -363,55 +362,6 @@
}
}
-void ClassHierarchyAnalysis::CheckInterfaceMethodSingleImplementationInfo(
- Handle<mirror::Class> klass,
- ArtMethod* interface_method,
- ArtMethod* implementation_method,
- std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
- PointerSize pointer_size) {
- DCHECK(klass->IsInstantiable());
- DCHECK(interface_method->IsAbstract() || interface_method->IsDefault());
-
- if (!interface_method->HasSingleImplementation()) {
- return;
- }
-
- if (implementation_method->IsAbstract()) {
- // An instantiable class doesn't supply an implementation for
- // interface_method. Invoking the interface method on the class will throw
- // AbstractMethodError. This is an uncommon case, so we simply treat
- // interface_method as not having single-implementation.
- invalidated_single_impl_methods.insert(interface_method);
- return;
- }
-
- // We need to grab cha_lock_ since there may be multiple class linking going
- // on that can check/modify the single-implementation flag/method of
- // interface_method.
- MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
- // Do this check again after we grab cha_lock_.
- if (!interface_method->HasSingleImplementation()) {
- return;
- }
-
- ArtMethod* single_impl = interface_method->GetSingleImplementation(pointer_size);
- if (single_impl == nullptr) {
- // implementation_method becomes the first implementation for
- // interface_method.
- interface_method->SetSingleImplementation(implementation_method, pointer_size);
- // Keep interface_method's single-implementation status.
- return;
- }
- DCHECK(!single_impl->IsAbstract());
- if (single_impl->GetDeclaringClass() == implementation_method->GetDeclaringClass()) {
- // Same implementation. Since implementation_method may be a copy of a default
- // method, we need to check the declaring class for equality.
- return;
- }
- // Another implementation for interface_method.
- invalidated_single_impl_methods.insert(interface_method);
-}
-
void ClassHierarchyAnalysis::InitSingleImplementationFlag(Handle<mirror::Class> klass,
ArtMethod* method,
PointerSize pointer_size) {
@@ -432,7 +382,6 @@
// Rare case, but we do accept it (such as 800-smali/smali/b_26143249.smali).
// Do not attempt to devirtualize it.
method->SetHasSingleImplementation(false);
- DCHECK(method->GetSingleImplementation(pointer_size) == nullptr);
} else {
// Abstract method starts with single-implementation flag set and null
// implementation method.
@@ -447,15 +396,9 @@
}
void ClassHierarchyAnalysis::UpdateAfterLoadingOf(Handle<mirror::Class> klass) {
- PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
if (klass->IsInterface()) {
- for (ArtMethod& method : klass->GetDeclaredVirtualMethods(image_pointer_size)) {
- DCHECK(method.IsAbstract() || method.IsDefault());
- InitSingleImplementationFlag(klass, &method, image_pointer_size);
- }
return;
}
-
mirror::Class* super_class = klass->GetSuperClass();
if (super_class == nullptr) {
return;
@@ -465,6 +408,7 @@
// is invalidated by linking `klass`.
std::unordered_set<ArtMethod*> invalidated_single_impl_methods;
+ PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
// Do an entry-by-entry comparison of vtable contents with super's vtable.
for (int32_t i = 0; i < super_class->GetVTableLength(); ++i) {
ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
@@ -474,59 +418,33 @@
if (method->IsAbstract() && klass->IsInstantiable()) {
// An instantiable class that inherits an abstract method is treated as
// supplying an implementation that throws AbstractMethodError.
- CheckVirtualMethodSingleImplementationInfo(klass,
- method,
- method_in_super,
- invalidated_single_impl_methods,
- image_pointer_size);
+ CheckSingleImplementationInfo(klass,
+ method,
+ method_in_super,
+ invalidated_single_impl_methods,
+ image_pointer_size);
}
continue;
}
InitSingleImplementationFlag(klass, method, image_pointer_size);
- CheckVirtualMethodSingleImplementationInfo(klass,
- method,
- method_in_super,
- invalidated_single_impl_methods,
- image_pointer_size);
+ CheckSingleImplementationInfo(klass,
+ method,
+ method_in_super,
+ invalidated_single_impl_methods,
+ image_pointer_size);
}
+
// For new virtual methods that don't override.
for (int32_t i = super_class->GetVTableLength(); i < klass->GetVTableLength(); ++i) {
ArtMethod* method = klass->GetVTableEntry(i, image_pointer_size);
InitSingleImplementationFlag(klass, method, image_pointer_size);
}
- if (klass->IsInstantiable()) {
- auto* iftable = klass->GetIfTable();
- const size_t ifcount = klass->GetIfTableCount();
- for (size_t i = 0; i < ifcount; ++i) {
- mirror::Class* interface = iftable->GetInterface(i);
- for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
- ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size);
- mirror::PointerArray* method_array = iftable->GetMethodArray(i);
- ArtMethod* implementation_method =
- method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size);
- DCHECK(implementation_method != nullptr) << klass->PrettyClass();
- CheckInterfaceMethodSingleImplementationInfo(klass,
- interface_method,
- implementation_method,
- invalidated_single_impl_methods,
- image_pointer_size);
- }
- }
- }
-
- InvalidateSingleImplementationMethods(invalidated_single_impl_methods);
-}
-
-void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods(
- std::unordered_set<ArtMethod*>& invalidated_single_impl_methods) {
+ Runtime* const runtime = Runtime::Current();
if (!invalidated_single_impl_methods.empty()) {
- Runtime* const runtime = Runtime::Current();
Thread *self = Thread::Current();
// Method headers for compiled code to be invalidated.
std::unordered_set<OatQuickMethodHeader*> dependent_method_headers;
- PointerSize image_pointer_size =
- Runtime::Current()->GetClassLinker()->GetImagePointerSize();
{
// We do this under cha_lock_. Committing code also grabs this lock to
diff --git a/runtime/cha.h b/runtime/cha.h
index 99c49d2..a56a752 100644
--- a/runtime/cha.h
+++ b/runtime/cha.h
@@ -117,13 +117,11 @@
PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Check/update single-implementation info when one virtual method
- // overrides another.
// `virtual_method` in `klass` overrides `method_in_super`.
- // This may invalidate some assumptions on single-implementation.
+ // This will invalidate some assumptions on single-implementation.
// Append methods that should have their single-implementation flag invalidated
// to `invalidated_single_impl_methods`.
- void CheckVirtualMethodSingleImplementationInfo(
+ void CheckSingleImplementationInfo(
Handle<mirror::Class> klass,
ArtMethod* virtual_method,
ArtMethod* method_in_super,
@@ -131,23 +129,6 @@
PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Check/update single-implementation info when one method
- // implements an interface method.
- // `implementation_method` in `klass` implements `interface_method`.
- // Append `interface_method` to `invalidated_single_impl_methods`
- // if `interface_method` gets a new implementation.
- void CheckInterfaceMethodSingleImplementationInfo(
- Handle<mirror::Class> klass,
- ArtMethod* interface_method,
- ArtMethod* implementation_method,
- std::unordered_set<ArtMethod*>& invalidated_single_impl_methods,
- PointerSize pointer_size)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- void InvalidateSingleImplementationMethods(
- std::unordered_set<ArtMethod*>& invalidated_single_impl_methods)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
// For all methods in vtable slot at `verify_index` of `verify_class` and its
// superclasses, single-implementation status should be false, except if the
// method is `excluded_method`.
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index fa87c8c..8162a82 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7821,7 +7821,7 @@
mirror::String* ClassLinker::LookupString(const DexFile& dex_file,
dex::StringIndex string_idx,
- Handle<mirror::DexCache> dex_cache) {
+ ObjPtr<mirror::DexCache> dex_cache) {
DCHECK(dex_cache != nullptr);
ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
if (resolved != nullptr) {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 6254acb..ef51d82 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -247,7 +247,7 @@
// result in the DexCache if found. Return null if not found.
mirror::String* LookupString(const DexFile& dex_file,
dex::StringIndex string_idx,
- Handle<mirror::DexCache> dex_cache)
+ ObjPtr<mirror::DexCache> dex_cache)
REQUIRES_SHARED(Locks::mutator_lock_);
// Resolve a Type with the given index from the DexFile, storing the
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index b421810..9f04e59 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -618,7 +618,7 @@
ClassExtOffsets() : CheckOffsets<mirror::ClassExt>(false, "Ldalvik/system/ClassExt;") {
addOffset(OFFSETOF_MEMBER(mirror::ClassExt, obsolete_dex_caches_), "obsoleteDexCaches");
addOffset(OFFSETOF_MEMBER(mirror::ClassExt, obsolete_methods_), "obsoleteMethods");
- addOffset(OFFSETOF_MEMBER(mirror::ClassExt, original_dex_file_), "originalDexFile");
+ addOffset(OFFSETOF_MEMBER(mirror::ClassExt, original_dex_file_bytes_), "originalDexFile");
addOffset(OFFSETOF_MEMBER(mirror::ClassExt, verify_error_), "verifyError");
}
};
diff --git a/runtime/mirror/class_ext.cc b/runtime/mirror/class_ext.cc
index 94e4b88..5dc3aca 100644
--- a/runtime/mirror/class_ext.cc
+++ b/runtime/mirror/class_ext.cc
@@ -117,9 +117,9 @@
}
}
-void ClassExt::SetOriginalDexFile(ObjPtr<Object> bytes) {
+void ClassExt::SetOriginalDexFileBytes(ObjPtr<ByteArray> bytes) {
DCHECK(!Runtime::Current()->IsActiveTransaction());
- SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ClassExt, original_dex_file_), bytes);
+ SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ClassExt, original_dex_file_bytes_), bytes);
}
void ClassExt::SetClass(ObjPtr<Class> dalvik_system_ClassExt) {
diff --git a/runtime/mirror/class_ext.h b/runtime/mirror/class_ext.h
index 708665d..fac955a 100644
--- a/runtime/mirror/class_ext.h
+++ b/runtime/mirror/class_ext.h
@@ -60,11 +60,11 @@
OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_methods_));
}
- Object* GetOriginalDexFile() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetFieldObject<Object>(OFFSET_OF_OBJECT_MEMBER(ClassExt, original_dex_file_));
+ ByteArray* GetOriginalDexFileBytes() REQUIRES_SHARED(Locks::mutator_lock_) {
+ return GetFieldObject<ByteArray>(OFFSET_OF_OBJECT_MEMBER(ClassExt, original_dex_file_bytes_));
}
- void SetOriginalDexFile(ObjPtr<Object> bytes) REQUIRES_SHARED(Locks::mutator_lock_);
+ void SetOriginalDexFileBytes(ObjPtr<ByteArray> bytes) REQUIRES_SHARED(Locks::mutator_lock_);
void SetObsoleteArrays(ObjPtr<PointerArray> methods, ObjPtr<ObjectArray<DexCache>> dex_caches)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -89,7 +89,7 @@
HeapReference<PointerArray> obsolete_methods_;
- HeapReference<Object> original_dex_file_;
+ HeapReference<ByteArray> original_dex_file_bytes_;
// The saved verification error of this class.
HeapReference<Object> verify_error_;
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 48a9ecd..78b2e15 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -426,6 +426,11 @@
NativeDexCachePair<T> pair,
PointerSize ptr_size);
+ uint32_t StringSlotIndex(dex::StringIndex string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
+ uint32_t TypeSlotIndex(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
+ uint32_t FieldSlotIndex(uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_);
+ uint32_t MethodTypeSlotIndex(uint32_t proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
+
private:
void Init(const DexFile* dex_file,
ObjPtr<String> location,
@@ -457,11 +462,6 @@
using ConversionPair32 = ConversionPair<uint32_t>;
using ConversionPair64 = ConversionPair<uint64_t>;
- uint32_t StringSlotIndex(dex::StringIndex string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
- uint32_t TypeSlotIndex(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
- uint32_t FieldSlotIndex(uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_);
- uint32_t MethodTypeSlotIndex(uint32_t proto_idx) REQUIRES_SHARED(Locks::mutator_lock_);
-
// Visit instance fields of the dex cache as well as its associated arrays.
template <bool kVisitNativeRoots,
VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
diff --git a/runtime/openjdkjvmti/ti_class.cc b/runtime/openjdkjvmti/ti_class.cc
index 38fd1d4..2d1b25e 100644
--- a/runtime/openjdkjvmti/ti_class.cc
+++ b/runtime/openjdkjvmti/ti_class.cc
@@ -259,7 +259,7 @@
}
// Actually set the ClassExt's original bytes once we have actually succeeded.
- ext->SetOriginalDexFile(arr.Get());
+ ext->SetOriginalDexFileBytes(arr.Get());
// Set the return values
*final_class_def = &dex_file->GetClassDef(0);
*final_dex_file = dex_file.release();
diff --git a/runtime/openjdkjvmti/ti_redefine.cc b/runtime/openjdkjvmti/ti_redefine.cc
index 7faddfb..9c1d6ef 100644
--- a/runtime/openjdkjvmti/ti_redefine.cc
+++ b/runtime/openjdkjvmti/ti_redefine.cc
@@ -469,7 +469,7 @@
result_ = result;
}
-art::mirror::Object* Redefiner::ClassRedefinition::AllocateOrGetOriginalDexFile() {
+art::mirror::ByteArray* Redefiner::ClassRedefinition::AllocateOrGetOriginalDexFileBytes() {
// If we have been specifically given a new set of bytes use that
if (original_dex_file_.size() != 0) {
return art::mirror::ByteArray::AllocateAndFill(
@@ -481,21 +481,24 @@
// See if we already have one set.
art::ObjPtr<art::mirror::ClassExt> ext(GetMirrorClass()->GetExtData());
if (!ext.IsNull()) {
- art::ObjPtr<art::mirror::Object> old_original_dex_file(ext->GetOriginalDexFile());
- if (!old_original_dex_file.IsNull()) {
+ art::ObjPtr<art::mirror::ByteArray> old_original_bytes(ext->GetOriginalDexFileBytes());
+ if (!old_original_bytes.IsNull()) {
// We do. Use it.
- return old_original_dex_file.Ptr();
+ return old_original_bytes.Ptr();
}
}
- // return the current dex_cache which has the dex file in it.
- art::ObjPtr<art::mirror::DexCache> current_dex_cache(GetMirrorClass()->GetDexCache());
+ // Copy the current dex_file
+ const art::DexFile& current_dex_file = GetMirrorClass()->GetDexFile();
// TODO Handle this or make it so it cannot happen.
- if (current_dex_cache->GetDexFile()->NumClassDefs() != 1) {
+ if (current_dex_file.NumClassDefs() != 1) {
LOG(WARNING) << "Current dex file has more than one class in it. Calling RetransformClasses "
<< "on this class might fail if no transformations are applied to it!";
}
- return current_dex_cache.Ptr();
+ return art::mirror::ByteArray::AllocateAndFill(
+ driver_->self_,
+ reinterpret_cast<const signed char*>(current_dex_file.Begin()),
+ current_dex_file.Size());
}
struct CallbackCtx {
@@ -844,9 +847,9 @@
return art::down_cast<art::mirror::Class*>(GetSlot(klass_index, kSlotMirrorClass));
}
- art::mirror::Object* GetOriginalDexFile(jint klass_index) const
+ art::mirror::ByteArray* GetOriginalDexFileBytes(jint klass_index) const
REQUIRES_SHARED(art::Locks::mutator_lock_) {
- return art::down_cast<art::mirror::Object*>(GetSlot(klass_index, kSlotOrigDexFile));
+ return art::down_cast<art::mirror::ByteArray*>(GetSlot(klass_index, kSlotOrigDexFile));
}
void SetSourceClassLoader(jint klass_index, art::mirror::ClassLoader* loader)
@@ -869,7 +872,7 @@
REQUIRES_SHARED(art::Locks::mutator_lock_) {
SetSlot(klass_index, kSlotMirrorClass, klass);
}
- void SetOriginalDexFile(jint klass_index, art::mirror::Object* bytes)
+ void SetOriginalDexFileBytes(jint klass_index, art::mirror::ByteArray* bytes)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
SetSlot(klass_index, kSlotOrigDexFile, bytes);
}
@@ -982,9 +985,9 @@
art::mirror::Class* GetMirrorClass() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
return holder_.GetMirrorClass(idx_);
}
- art::mirror::Object* GetOriginalDexFile() const
+ art::mirror::ByteArray* GetOriginalDexFileBytes() const
REQUIRES_SHARED(art::Locks::mutator_lock_) {
- return holder_.GetOriginalDexFile(idx_);
+ return holder_.GetOriginalDexFileBytes(idx_);
}
int32_t GetIndex() const {
return idx_;
@@ -1007,9 +1010,9 @@
void SetMirrorClass(art::mirror::Class* klass) REQUIRES_SHARED(art::Locks::mutator_lock_) {
holder_.SetMirrorClass(idx_, klass);
}
- void SetOriginalDexFile(art::mirror::Object* bytes)
+ void SetOriginalDexFileBytes(art::mirror::ByteArray* bytes)
REQUIRES_SHARED(art::Locks::mutator_lock_) {
- holder_.SetOriginalDexFile(idx_, bytes);
+ holder_.SetOriginalDexFileBytes(idx_, bytes);
}
private:
@@ -1135,8 +1138,8 @@
}
// We won't always need to set this field.
- cur_data->SetOriginalDexFile(AllocateOrGetOriginalDexFile());
- if (cur_data->GetOriginalDexFile() == nullptr) {
+ cur_data->SetOriginalDexFileBytes(AllocateOrGetOriginalDexFileBytes());
+ if (cur_data->GetOriginalDexFileBytes() == nullptr) {
driver_->self_->AssertPendingOOMException();
driver_->self_->ClearException();
RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate array for original dex file");
@@ -1282,7 +1285,7 @@
art::mirror::Class* klass = data.GetMirrorClass();
// TODO Rewrite so we don't do a stack walk for each and every class.
redef.FindAndAllocateObsoleteMethods(klass);
- redef.UpdateClass(klass, data.GetNewDexCache(), data.GetOriginalDexFile());
+ redef.UpdateClass(klass, data.GetNewDexCache(), data.GetOriginalDexFileBytes());
}
// TODO We should check for if any of the redefined methods are intrinsic methods here and, if any
// are, force a full-world deoptimization before finishing redefinition. If we don't do this then
@@ -1362,7 +1365,7 @@
void Redefiner::ClassRedefinition::UpdateClass(
art::ObjPtr<art::mirror::Class> mclass,
art::ObjPtr<art::mirror::DexCache> new_dex_cache,
- art::ObjPtr<art::mirror::Object> original_dex_file) {
+ art::ObjPtr<art::mirror::ByteArray> original_dex_file) {
DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
const art::DexFile::ClassDef& class_def = dex_file_->GetClassDef(0);
UpdateMethods(mclass, new_dex_cache, class_def);
@@ -1376,7 +1379,7 @@
mclass->SetDexTypeIndex(dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(class_sig_.c_str())));
art::ObjPtr<art::mirror::ClassExt> ext(mclass->GetExtData());
CHECK(!ext.IsNull());
- ext->SetOriginalDexFile(original_dex_file);
+ ext->SetOriginalDexFileBytes(original_dex_file);
}
// This function does all (java) allocations we need to do for the Class being redefined.
diff --git a/runtime/openjdkjvmti/ti_redefine.h b/runtime/openjdkjvmti/ti_redefine.h
index 6c09d46..4313a94 100644
--- a/runtime/openjdkjvmti/ti_redefine.h
+++ b/runtime/openjdkjvmti/ti_redefine.h
@@ -137,7 +137,7 @@
REQUIRES_SHARED(art::Locks::mutator_lock_);
// This may return nullptr with a OOME pending if allocation fails.
- art::mirror::Object* AllocateOrGetOriginalDexFile()
+ art::mirror::ByteArray* AllocateOrGetOriginalDexFileBytes()
REQUIRES_SHARED(art::Locks::mutator_lock_);
void RecordFailure(jvmtiError e, const std::string& err) {
@@ -196,7 +196,7 @@
void UpdateClass(art::ObjPtr<art::mirror::Class> mclass,
art::ObjPtr<art::mirror::DexCache> new_dex_cache,
- art::ObjPtr<art::mirror::Object> original_dex_file)
+ art::ObjPtr<art::mirror::ByteArray> original_dex_file)
REQUIRES(art::Locks::mutator_lock_);
void ReleaseDexFile() REQUIRES_SHARED(art::Locks::mutator_lock_);
diff --git a/runtime/openjdkjvmti/transform.cc b/runtime/openjdkjvmti/transform.cc
index 06aecba..bd52cbb 100644
--- a/runtime/openjdkjvmti/transform.cc
+++ b/runtime/openjdkjvmti/transform.cc
@@ -150,27 +150,16 @@
art::Handle<art::mirror::Class> klass,
/*out*/jint* dex_data_len,
/*out*/unsigned char** dex_data) {
- art::StackHandleScope<3> hs(art::Thread::Current());
+ art::StackHandleScope<2> hs(art::Thread::Current());
art::Handle<art::mirror::ClassExt> ext(hs.NewHandle(klass->GetExtData()));
if (!ext.IsNull()) {
- art::Handle<art::mirror::Object> orig_dex(hs.NewHandle(ext->GetOriginalDexFile()));
+ art::Handle<art::mirror::ByteArray> orig_dex(hs.NewHandle(ext->GetOriginalDexFileBytes()));
if (!orig_dex.IsNull()) {
- if (orig_dex->IsArrayInstance()) {
- DCHECK(orig_dex->GetClass()->GetComponentType()->IsPrimitiveByte());
- art::Handle<art::mirror::ByteArray> orig_dex_bytes(
- hs.NewHandle(art::down_cast<art::mirror::ByteArray*>(orig_dex->AsArray())));
- *dex_data_len = static_cast<jint>(orig_dex_bytes->GetLength());
- return CopyDataIntoJvmtiBuffer(
- env,
- reinterpret_cast<const unsigned char*>(orig_dex_bytes->GetData()),
- *dex_data_len,
- /*out*/dex_data);
- } else {
- DCHECK(orig_dex->IsDexCache());
- const art::DexFile* dex_file = orig_dex->AsDexCache()->GetDexFile();
- *dex_data_len = static_cast<jint>(dex_file->Size());
- return CopyDataIntoJvmtiBuffer(env, dex_file->Begin(), dex_file->Size(), /*out*/dex_data);
- }
+ *dex_data_len = static_cast<jint>(orig_dex->GetLength());
+ return CopyDataIntoJvmtiBuffer(env,
+ reinterpret_cast<const unsigned char*>(orig_dex->GetData()),
+ *dex_data_len,
+ /*out*/dex_data);
}
}
// TODO De-quicken the dex file before passing it to the agents.
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 97c1228..9206292 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -508,7 +508,7 @@
dex::StringIndex string_idx = dex_file->GetIndexForStringId(*string_id);
ASSERT_TRUE(string_idx.IsValid());
// String should only get resolved by the initializer.
- EXPECT_TRUE(class_linker_->LookupString(*dex_file, string_idx, h_dex_cache) == nullptr);
+ EXPECT_TRUE(class_linker_->LookupString(*dex_file, string_idx, h_dex_cache.Get()) == nullptr);
EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
// Do the transaction, then roll back.
Transaction transaction;
@@ -518,7 +518,7 @@
ASSERT_TRUE(h_klass->IsInitialized());
// Make sure the string got resolved by the transaction.
{
- mirror::String* s = class_linker_->LookupString(*dex_file, string_idx, h_dex_cache);
+ mirror::String* s = class_linker_->LookupString(*dex_file, string_idx, h_dex_cache.Get());
ASSERT_TRUE(s != nullptr);
EXPECT_STREQ(s->ToModifiedUtf8().c_str(), kResolvedString);
EXPECT_EQ(s, h_dex_cache->GetResolvedString(string_idx));
@@ -526,7 +526,7 @@
Runtime::Current()->ExitTransactionMode();
transaction.Rollback();
// Check that the string did not stay resolved.
- EXPECT_TRUE(class_linker_->LookupString(*dex_file, string_idx, h_dex_cache) == nullptr);
+ EXPECT_TRUE(class_linker_->LookupString(*dex_file, string_idx, h_dex_cache.Get()) == nullptr);
EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
ASSERT_FALSE(h_klass->IsInitialized());
ASSERT_FALSE(soa.Self()->IsExceptionPending());
diff --git a/test/159-app-image-fields/expected.txt b/test/159-app-image-fields/expected.txt
new file mode 100644
index 0000000..f63e8e3
--- /dev/null
+++ b/test/159-app-image-fields/expected.txt
@@ -0,0 +1,3 @@
+Eating all memory.
+memoryWasAllocated = true
+match: true
diff --git a/test/159-app-image-fields/info.txt b/test/159-app-image-fields/info.txt
new file mode 100644
index 0000000..9b10078
--- /dev/null
+++ b/test/159-app-image-fields/info.txt
@@ -0,0 +1,3 @@
+Regression test for erroneously storing an ArtField* in the app image DexCache
+when the class from the corresponding FieldId is not in the app image, only the
+declaring class is.
diff --git a/test/159-app-image-fields/profile b/test/159-app-image-fields/profile
new file mode 100644
index 0000000..4184fa2
--- /dev/null
+++ b/test/159-app-image-fields/profile
@@ -0,0 +1,3 @@
+LAAA/Base;
+LMain;
+LFields;
diff --git a/test/616-cha-interface-default/run b/test/159-app-image-fields/run
similarity index 71%
rename from test/616-cha-interface-default/run
rename to test/159-app-image-fields/run
index d8b4f0d..7cc107a 100644
--- a/test/616-cha-interface-default/run
+++ b/test/159-app-image-fields/run
@@ -14,5 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Run without an app image to prevent the classes to be loaded at startup.
-exec ${RUN} "${@}" --no-app-image
+# Use a profile to put specific classes in the app image.
+# Also run the compiler with -j1 to ensure specific class verification order.
+exec ${RUN} $@ --profile -Xcompiler-option --compiler-filter=speed-profile \
+ -Xcompiler-option -j1
diff --git a/test/616-cha-proxy-method-inline/src-multidex/Foo.java b/test/159-app-image-fields/src/AAA/Base.java
similarity index 83%
rename from test/616-cha-proxy-method-inline/src-multidex/Foo.java
rename to test/159-app-image-fields/src/AAA/Base.java
index 9deca3e..41ee83a 100644
--- a/test/616-cha-proxy-method-inline/src-multidex/Foo.java
+++ b/test/159-app-image-fields/src/AAA/Base.java
@@ -14,6 +14,9 @@
* limitations under the License.
*/
-interface Foo {
- public Object bar(Object obj);
+package AAA;
+
+class Base {
+ // The field is public but the class is package-private.
+ public static int value = 42;
}
diff --git a/test/616-cha-proxy-method-inline/src-multidex/Foo.java b/test/159-app-image-fields/src/AAA/Derived.java
similarity index 80%
copy from test/616-cha-proxy-method-inline/src-multidex/Foo.java
copy to test/159-app-image-fields/src/AAA/Derived.java
index 9deca3e..f6045d5 100644
--- a/test/616-cha-proxy-method-inline/src-multidex/Foo.java
+++ b/test/159-app-image-fields/src/AAA/Derived.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
-interface Foo {
- public Object bar(Object obj);
+package AAA;
+
+public class Derived extends Base {
+ // Allows public access to Base.value (Base is package-private) referenced as Derived.value.
}
diff --git a/test/159-app-image-fields/src/Main.java b/test/159-app-image-fields/src/Main.java
new file mode 100644
index 0000000..d06a502
--- /dev/null
+++ b/test/159-app-image-fields/src/Main.java
@@ -0,0 +1,2156 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+import AAA.Derived;
+
+public class Main {
+ public static void main(String[] args) {
+ try {
+ // Make sure we resolve Fields before eating memory.
+ // (Making sure that the test passes in no-image configurations.)
+ Class.forName("Fields", false, Main.class.getClassLoader());
+ System.out.println("Eating all memory.");
+ Object memory = eatAllMemory();
+
+ // This test assumes that Derived is not yet resolved. In some configurations
+ // (notably interp-ac), Derived is already resolved by verifying Main at run
+ // time. Therefore we cannot assume that we get a certain `value` and need to
+ // simply check for consistency, i.e. `value == another_value`.
+ int value = 0;
+ try {
+ // If the ArtField* is erroneously left in the DexCache, this
+ // shall succeed despite the class Derived being unresolved so
+ // far. Otherwise, we shall throw OOME trying to resolve it.
+ value = Derived.value;
+ } catch (OutOfMemoryError e) {
+ value = -1;
+ }
+ Fields.clobberDexCache();
+ int another_value = 0;
+ try {
+ // Try again for comparison. Since the DexCache field array has been
+ // clobbered by Fields.clobberDexCache(), this shall throw OOME.
+ another_value = Derived.value;
+ } catch (OutOfMemoryError e) {
+ another_value = -1;
+ }
+ boolean memoryWasAllocated = (memory != null);
+ memory = null;
+ System.out.println("memoryWasAllocated = " + memoryWasAllocated);
+ System.out.println("match: " + (value == another_value));
+ if (value != another_value || (value != -1 && value != 42)) {
+ // Mismatch or unexpected value, print additional debugging information.
+ System.out.println("value: " + value);
+ System.out.println("another_value: " + another_value);
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ public static Object eatAllMemory() {
+ Object[] result = null;
+ int size = 1000000;
+ while (result == null && size != 0) {
+ try {
+ result = new Object[size];
+ } catch (OutOfMemoryError oome) {
+ size /= 2;
+ }
+ }
+ if (result != null) {
+ int index = 0;
+ while (index != result.length && size != 0) {
+ try {
+ result[index] = new byte[size];
+ ++index;
+ } catch (OutOfMemoryError oome) {
+ size /= 2;
+ }
+ }
+ }
+ return result;
+ }
+}
+
+// The naming is deliberate to take into account two different situations:
+// - eagerly preloading DexCache with the available candidate with the lowest index,
+// - not preloading DexCache and relying on the verification to populate it.
+// This corresponds to new and old behavior, respectively.
+//
+// Eager preloading: "LFields;" is after "LAAA/Base;" and "LAAA/Derived;" so that
+// Derived.value takes priority over Fields.testField*.
+//
+// Relying on verifier: "LFields;" is before "LMain;" so that the class definition
+// of Fields precedes the definition of Main (this is not strictly required but the
+// tools look at lexicographic ordering when there is no inheritance relationship)
+// and the verification of Main is last and fills the DexCache with Derived.value.
+//
+class Fields {
+ public static int clobberDexCache() {
+ return 0
+ + testField0000
+ + testField0001
+ + testField0002
+ + testField0003
+ + testField0004
+ + testField0005
+ + testField0006
+ + testField0007
+ + testField0008
+ + testField0009
+ + testField0010
+ + testField0011
+ + testField0012
+ + testField0013
+ + testField0014
+ + testField0015
+ + testField0016
+ + testField0017
+ + testField0018
+ + testField0019
+ + testField0020
+ + testField0021
+ + testField0022
+ + testField0023
+ + testField0024
+ + testField0025
+ + testField0026
+ + testField0027
+ + testField0028
+ + testField0029
+ + testField0030
+ + testField0031
+ + testField0032
+ + testField0033
+ + testField0034
+ + testField0035
+ + testField0036
+ + testField0037
+ + testField0038
+ + testField0039
+ + testField0040
+ + testField0041
+ + testField0042
+ + testField0043
+ + testField0044
+ + testField0045
+ + testField0046
+ + testField0047
+ + testField0048
+ + testField0049
+ + testField0050
+ + testField0051
+ + testField0052
+ + testField0053
+ + testField0054
+ + testField0055
+ + testField0056
+ + testField0057
+ + testField0058
+ + testField0059
+ + testField0060
+ + testField0061
+ + testField0062
+ + testField0063
+ + testField0064
+ + testField0065
+ + testField0066
+ + testField0067
+ + testField0068
+ + testField0069
+ + testField0070
+ + testField0071
+ + testField0072
+ + testField0073
+ + testField0074
+ + testField0075
+ + testField0076
+ + testField0077
+ + testField0078
+ + testField0079
+ + testField0080
+ + testField0081
+ + testField0082
+ + testField0083
+ + testField0084
+ + testField0085
+ + testField0086
+ + testField0087
+ + testField0088
+ + testField0089
+ + testField0090
+ + testField0091
+ + testField0092
+ + testField0093
+ + testField0094
+ + testField0095
+ + testField0096
+ + testField0097
+ + testField0098
+ + testField0099
+ + testField0100
+ + testField0101
+ + testField0102
+ + testField0103
+ + testField0104
+ + testField0105
+ + testField0106
+ + testField0107
+ + testField0108
+ + testField0109
+ + testField0110
+ + testField0111
+ + testField0112
+ + testField0113
+ + testField0114
+ + testField0115
+ + testField0116
+ + testField0117
+ + testField0118
+ + testField0119
+ + testField0120
+ + testField0121
+ + testField0122
+ + testField0123
+ + testField0124
+ + testField0125
+ + testField0126
+ + testField0127
+ + testField0128
+ + testField0129
+ + testField0130
+ + testField0131
+ + testField0132
+ + testField0133
+ + testField0134
+ + testField0135
+ + testField0136
+ + testField0137
+ + testField0138
+ + testField0139
+ + testField0140
+ + testField0141
+ + testField0142
+ + testField0143
+ + testField0144
+ + testField0145
+ + testField0146
+ + testField0147
+ + testField0148
+ + testField0149
+ + testField0150
+ + testField0151
+ + testField0152
+ + testField0153
+ + testField0154
+ + testField0155
+ + testField0156
+ + testField0157
+ + testField0158
+ + testField0159
+ + testField0160
+ + testField0161
+ + testField0162
+ + testField0163
+ + testField0164
+ + testField0165
+ + testField0166
+ + testField0167
+ + testField0168
+ + testField0169
+ + testField0170
+ + testField0171
+ + testField0172
+ + testField0173
+ + testField0174
+ + testField0175
+ + testField0176
+ + testField0177
+ + testField0178
+ + testField0179
+ + testField0180
+ + testField0181
+ + testField0182
+ + testField0183
+ + testField0184
+ + testField0185
+ + testField0186
+ + testField0187
+ + testField0188
+ + testField0189
+ + testField0190
+ + testField0191
+ + testField0192
+ + testField0193
+ + testField0194
+ + testField0195
+ + testField0196
+ + testField0197
+ + testField0198
+ + testField0199
+ + testField0200
+ + testField0201
+ + testField0202
+ + testField0203
+ + testField0204
+ + testField0205
+ + testField0206
+ + testField0207
+ + testField0208
+ + testField0209
+ + testField0210
+ + testField0211
+ + testField0212
+ + testField0213
+ + testField0214
+ + testField0215
+ + testField0216
+ + testField0217
+ + testField0218
+ + testField0219
+ + testField0220
+ + testField0221
+ + testField0222
+ + testField0223
+ + testField0224
+ + testField0225
+ + testField0226
+ + testField0227
+ + testField0228
+ + testField0229
+ + testField0230
+ + testField0231
+ + testField0232
+ + testField0233
+ + testField0234
+ + testField0235
+ + testField0236
+ + testField0237
+ + testField0238
+ + testField0239
+ + testField0240
+ + testField0241
+ + testField0242
+ + testField0243
+ + testField0244
+ + testField0245
+ + testField0246
+ + testField0247
+ + testField0248
+ + testField0249
+ + testField0250
+ + testField0251
+ + testField0252
+ + testField0253
+ + testField0254
+ + testField0255
+ + testField0256
+ + testField0257
+ + testField0258
+ + testField0259
+ + testField0260
+ + testField0261
+ + testField0262
+ + testField0263
+ + testField0264
+ + testField0265
+ + testField0266
+ + testField0267
+ + testField0268
+ + testField0269
+ + testField0270
+ + testField0271
+ + testField0272
+ + testField0273
+ + testField0274
+ + testField0275
+ + testField0276
+ + testField0277
+ + testField0278
+ + testField0279
+ + testField0280
+ + testField0281
+ + testField0282
+ + testField0283
+ + testField0284
+ + testField0285
+ + testField0286
+ + testField0287
+ + testField0288
+ + testField0289
+ + testField0290
+ + testField0291
+ + testField0292
+ + testField0293
+ + testField0294
+ + testField0295
+ + testField0296
+ + testField0297
+ + testField0298
+ + testField0299
+ + testField0300
+ + testField0301
+ + testField0302
+ + testField0303
+ + testField0304
+ + testField0305
+ + testField0306
+ + testField0307
+ + testField0308
+ + testField0309
+ + testField0310
+ + testField0311
+ + testField0312
+ + testField0313
+ + testField0314
+ + testField0315
+ + testField0316
+ + testField0317
+ + testField0318
+ + testField0319
+ + testField0320
+ + testField0321
+ + testField0322
+ + testField0323
+ + testField0324
+ + testField0325
+ + testField0326
+ + testField0327
+ + testField0328
+ + testField0329
+ + testField0330
+ + testField0331
+ + testField0332
+ + testField0333
+ + testField0334
+ + testField0335
+ + testField0336
+ + testField0337
+ + testField0338
+ + testField0339
+ + testField0340
+ + testField0341
+ + testField0342
+ + testField0343
+ + testField0344
+ + testField0345
+ + testField0346
+ + testField0347
+ + testField0348
+ + testField0349
+ + testField0350
+ + testField0351
+ + testField0352
+ + testField0353
+ + testField0354
+ + testField0355
+ + testField0356
+ + testField0357
+ + testField0358
+ + testField0359
+ + testField0360
+ + testField0361
+ + testField0362
+ + testField0363
+ + testField0364
+ + testField0365
+ + testField0366
+ + testField0367
+ + testField0368
+ + testField0369
+ + testField0370
+ + testField0371
+ + testField0372
+ + testField0373
+ + testField0374
+ + testField0375
+ + testField0376
+ + testField0377
+ + testField0378
+ + testField0379
+ + testField0380
+ + testField0381
+ + testField0382
+ + testField0383
+ + testField0384
+ + testField0385
+ + testField0386
+ + testField0387
+ + testField0388
+ + testField0389
+ + testField0390
+ + testField0391
+ + testField0392
+ + testField0393
+ + testField0394
+ + testField0395
+ + testField0396
+ + testField0397
+ + testField0398
+ + testField0399
+ + testField0400
+ + testField0401
+ + testField0402
+ + testField0403
+ + testField0404
+ + testField0405
+ + testField0406
+ + testField0407
+ + testField0408
+ + testField0409
+ + testField0410
+ + testField0411
+ + testField0412
+ + testField0413
+ + testField0414
+ + testField0415
+ + testField0416
+ + testField0417
+ + testField0418
+ + testField0419
+ + testField0420
+ + testField0421
+ + testField0422
+ + testField0423
+ + testField0424
+ + testField0425
+ + testField0426
+ + testField0427
+ + testField0428
+ + testField0429
+ + testField0430
+ + testField0431
+ + testField0432
+ + testField0433
+ + testField0434
+ + testField0435
+ + testField0436
+ + testField0437
+ + testField0438
+ + testField0439
+ + testField0440
+ + testField0441
+ + testField0442
+ + testField0443
+ + testField0444
+ + testField0445
+ + testField0446
+ + testField0447
+ + testField0448
+ + testField0449
+ + testField0450
+ + testField0451
+ + testField0452
+ + testField0453
+ + testField0454
+ + testField0455
+ + testField0456
+ + testField0457
+ + testField0458
+ + testField0459
+ + testField0460
+ + testField0461
+ + testField0462
+ + testField0463
+ + testField0464
+ + testField0465
+ + testField0466
+ + testField0467
+ + testField0468
+ + testField0469
+ + testField0470
+ + testField0471
+ + testField0472
+ + testField0473
+ + testField0474
+ + testField0475
+ + testField0476
+ + testField0477
+ + testField0478
+ + testField0479
+ + testField0480
+ + testField0481
+ + testField0482
+ + testField0483
+ + testField0484
+ + testField0485
+ + testField0486
+ + testField0487
+ + testField0488
+ + testField0489
+ + testField0490
+ + testField0491
+ + testField0492
+ + testField0493
+ + testField0494
+ + testField0495
+ + testField0496
+ + testField0497
+ + testField0498
+ + testField0499
+ + testField0500
+ + testField0501
+ + testField0502
+ + testField0503
+ + testField0504
+ + testField0505
+ + testField0506
+ + testField0507
+ + testField0508
+ + testField0509
+ + testField0510
+ + testField0511
+ + testField0512
+ + testField0513
+ + testField0514
+ + testField0515
+ + testField0516
+ + testField0517
+ + testField0518
+ + testField0519
+ + testField0520
+ + testField0521
+ + testField0522
+ + testField0523
+ + testField0524
+ + testField0525
+ + testField0526
+ + testField0527
+ + testField0528
+ + testField0529
+ + testField0530
+ + testField0531
+ + testField0532
+ + testField0533
+ + testField0534
+ + testField0535
+ + testField0536
+ + testField0537
+ + testField0538
+ + testField0539
+ + testField0540
+ + testField0541
+ + testField0542
+ + testField0543
+ + testField0544
+ + testField0545
+ + testField0546
+ + testField0547
+ + testField0548
+ + testField0549
+ + testField0550
+ + testField0551
+ + testField0552
+ + testField0553
+ + testField0554
+ + testField0555
+ + testField0556
+ + testField0557
+ + testField0558
+ + testField0559
+ + testField0560
+ + testField0561
+ + testField0562
+ + testField0563
+ + testField0564
+ + testField0565
+ + testField0566
+ + testField0567
+ + testField0568
+ + testField0569
+ + testField0570
+ + testField0571
+ + testField0572
+ + testField0573
+ + testField0574
+ + testField0575
+ + testField0576
+ + testField0577
+ + testField0578
+ + testField0579
+ + testField0580
+ + testField0581
+ + testField0582
+ + testField0583
+ + testField0584
+ + testField0585
+ + testField0586
+ + testField0587
+ + testField0588
+ + testField0589
+ + testField0590
+ + testField0591
+ + testField0592
+ + testField0593
+ + testField0594
+ + testField0595
+ + testField0596
+ + testField0597
+ + testField0598
+ + testField0599
+ + testField0600
+ + testField0601
+ + testField0602
+ + testField0603
+ + testField0604
+ + testField0605
+ + testField0606
+ + testField0607
+ + testField0608
+ + testField0609
+ + testField0610
+ + testField0611
+ + testField0612
+ + testField0613
+ + testField0614
+ + testField0615
+ + testField0616
+ + testField0617
+ + testField0618
+ + testField0619
+ + testField0620
+ + testField0621
+ + testField0622
+ + testField0623
+ + testField0624
+ + testField0625
+ + testField0626
+ + testField0627
+ + testField0628
+ + testField0629
+ + testField0630
+ + testField0631
+ + testField0632
+ + testField0633
+ + testField0634
+ + testField0635
+ + testField0636
+ + testField0637
+ + testField0638
+ + testField0639
+ + testField0640
+ + testField0641
+ + testField0642
+ + testField0643
+ + testField0644
+ + testField0645
+ + testField0646
+ + testField0647
+ + testField0648
+ + testField0649
+ + testField0650
+ + testField0651
+ + testField0652
+ + testField0653
+ + testField0654
+ + testField0655
+ + testField0656
+ + testField0657
+ + testField0658
+ + testField0659
+ + testField0660
+ + testField0661
+ + testField0662
+ + testField0663
+ + testField0664
+ + testField0665
+ + testField0666
+ + testField0667
+ + testField0668
+ + testField0669
+ + testField0670
+ + testField0671
+ + testField0672
+ + testField0673
+ + testField0674
+ + testField0675
+ + testField0676
+ + testField0677
+ + testField0678
+ + testField0679
+ + testField0680
+ + testField0681
+ + testField0682
+ + testField0683
+ + testField0684
+ + testField0685
+ + testField0686
+ + testField0687
+ + testField0688
+ + testField0689
+ + testField0690
+ + testField0691
+ + testField0692
+ + testField0693
+ + testField0694
+ + testField0695
+ + testField0696
+ + testField0697
+ + testField0698
+ + testField0699
+ + testField0700
+ + testField0701
+ + testField0702
+ + testField0703
+ + testField0704
+ + testField0705
+ + testField0706
+ + testField0707
+ + testField0708
+ + testField0709
+ + testField0710
+ + testField0711
+ + testField0712
+ + testField0713
+ + testField0714
+ + testField0715
+ + testField0716
+ + testField0717
+ + testField0718
+ + testField0719
+ + testField0720
+ + testField0721
+ + testField0722
+ + testField0723
+ + testField0724
+ + testField0725
+ + testField0726
+ + testField0727
+ + testField0728
+ + testField0729
+ + testField0730
+ + testField0731
+ + testField0732
+ + testField0733
+ + testField0734
+ + testField0735
+ + testField0736
+ + testField0737
+ + testField0738
+ + testField0739
+ + testField0740
+ + testField0741
+ + testField0742
+ + testField0743
+ + testField0744
+ + testField0745
+ + testField0746
+ + testField0747
+ + testField0748
+ + testField0749
+ + testField0750
+ + testField0751
+ + testField0752
+ + testField0753
+ + testField0754
+ + testField0755
+ + testField0756
+ + testField0757
+ + testField0758
+ + testField0759
+ + testField0760
+ + testField0761
+ + testField0762
+ + testField0763
+ + testField0764
+ + testField0765
+ + testField0766
+ + testField0767
+ + testField0768
+ + testField0769
+ + testField0770
+ + testField0771
+ + testField0772
+ + testField0773
+ + testField0774
+ + testField0775
+ + testField0776
+ + testField0777
+ + testField0778
+ + testField0779
+ + testField0780
+ + testField0781
+ + testField0782
+ + testField0783
+ + testField0784
+ + testField0785
+ + testField0786
+ + testField0787
+ + testField0788
+ + testField0789
+ + testField0790
+ + testField0791
+ + testField0792
+ + testField0793
+ + testField0794
+ + testField0795
+ + testField0796
+ + testField0797
+ + testField0798
+ + testField0799
+ + testField0800
+ + testField0801
+ + testField0802
+ + testField0803
+ + testField0804
+ + testField0805
+ + testField0806
+ + testField0807
+ + testField0808
+ + testField0809
+ + testField0810
+ + testField0811
+ + testField0812
+ + testField0813
+ + testField0814
+ + testField0815
+ + testField0816
+ + testField0817
+ + testField0818
+ + testField0819
+ + testField0820
+ + testField0821
+ + testField0822
+ + testField0823
+ + testField0824
+ + testField0825
+ + testField0826
+ + testField0827
+ + testField0828
+ + testField0829
+ + testField0830
+ + testField0831
+ + testField0832
+ + testField0833
+ + testField0834
+ + testField0835
+ + testField0836
+ + testField0837
+ + testField0838
+ + testField0839
+ + testField0840
+ + testField0841
+ + testField0842
+ + testField0843
+ + testField0844
+ + testField0845
+ + testField0846
+ + testField0847
+ + testField0848
+ + testField0849
+ + testField0850
+ + testField0851
+ + testField0852
+ + testField0853
+ + testField0854
+ + testField0855
+ + testField0856
+ + testField0857
+ + testField0858
+ + testField0859
+ + testField0860
+ + testField0861
+ + testField0862
+ + testField0863
+ + testField0864
+ + testField0865
+ + testField0866
+ + testField0867
+ + testField0868
+ + testField0869
+ + testField0870
+ + testField0871
+ + testField0872
+ + testField0873
+ + testField0874
+ + testField0875
+ + testField0876
+ + testField0877
+ + testField0878
+ + testField0879
+ + testField0880
+ + testField0881
+ + testField0882
+ + testField0883
+ + testField0884
+ + testField0885
+ + testField0886
+ + testField0887
+ + testField0888
+ + testField0889
+ + testField0890
+ + testField0891
+ + testField0892
+ + testField0893
+ + testField0894
+ + testField0895
+ + testField0896
+ + testField0897
+ + testField0898
+ + testField0899
+ + testField0900
+ + testField0901
+ + testField0902
+ + testField0903
+ + testField0904
+ + testField0905
+ + testField0906
+ + testField0907
+ + testField0908
+ + testField0909
+ + testField0910
+ + testField0911
+ + testField0912
+ + testField0913
+ + testField0914
+ + testField0915
+ + testField0916
+ + testField0917
+ + testField0918
+ + testField0919
+ + testField0920
+ + testField0921
+ + testField0922
+ + testField0923
+ + testField0924
+ + testField0925
+ + testField0926
+ + testField0927
+ + testField0928
+ + testField0929
+ + testField0930
+ + testField0931
+ + testField0932
+ + testField0933
+ + testField0934
+ + testField0935
+ + testField0936
+ + testField0937
+ + testField0938
+ + testField0939
+ + testField0940
+ + testField0941
+ + testField0942
+ + testField0943
+ + testField0944
+ + testField0945
+ + testField0946
+ + testField0947
+ + testField0948
+ + testField0949
+ + testField0950
+ + testField0951
+ + testField0952
+ + testField0953
+ + testField0954
+ + testField0955
+ + testField0956
+ + testField0957
+ + testField0958
+ + testField0959
+ + testField0960
+ + testField0961
+ + testField0962
+ + testField0963
+ + testField0964
+ + testField0965
+ + testField0966
+ + testField0967
+ + testField0968
+ + testField0969
+ + testField0970
+ + testField0971
+ + testField0972
+ + testField0973
+ + testField0974
+ + testField0975
+ + testField0976
+ + testField0977
+ + testField0978
+ + testField0979
+ + testField0980
+ + testField0981
+ + testField0982
+ + testField0983
+ + testField0984
+ + testField0985
+ + testField0986
+ + testField0987
+ + testField0988
+ + testField0989
+ + testField0990
+ + testField0991
+ + testField0992
+ + testField0993
+ + testField0994
+ + testField0995
+ + testField0996
+ + testField0997
+ + testField0998
+ + testField0999
+ + testField1000
+ + testField1001
+ + testField1002
+ + testField1003
+ + testField1004
+ + testField1005
+ + testField1006
+ + testField1007
+ + testField1008
+ + testField1009
+ + testField1010
+ + testField1011
+ + testField1012
+ + testField1013
+ + testField1014
+ + testField1015
+ + testField1016
+ + testField1017
+ + testField1018
+ + testField1019
+ + testField1020
+ + testField1021
+ + testField1022
+ + testField1023
+ + 0;
+ }
+
+ private static int testField0000 = 0;
+ private static int testField0001 = 1;
+ private static int testField0002 = 2;
+ private static int testField0003 = 3;
+ private static int testField0004 = 4;
+ private static int testField0005 = 5;
+ private static int testField0006 = 6;
+ private static int testField0007 = 7;
+ private static int testField0008 = 8;
+ private static int testField0009 = 9;
+ private static int testField0010 = 10;
+ private static int testField0011 = 11;
+ private static int testField0012 = 12;
+ private static int testField0013 = 13;
+ private static int testField0014 = 14;
+ private static int testField0015 = 15;
+ private static int testField0016 = 16;
+ private static int testField0017 = 17;
+ private static int testField0018 = 18;
+ private static int testField0019 = 19;
+ private static int testField0020 = 20;
+ private static int testField0021 = 21;
+ private static int testField0022 = 22;
+ private static int testField0023 = 23;
+ private static int testField0024 = 24;
+ private static int testField0025 = 25;
+ private static int testField0026 = 26;
+ private static int testField0027 = 27;
+ private static int testField0028 = 28;
+ private static int testField0029 = 29;
+ private static int testField0030 = 30;
+ private static int testField0031 = 31;
+ private static int testField0032 = 32;
+ private static int testField0033 = 33;
+ private static int testField0034 = 34;
+ private static int testField0035 = 35;
+ private static int testField0036 = 36;
+ private static int testField0037 = 37;
+ private static int testField0038 = 38;
+ private static int testField0039 = 39;
+ private static int testField0040 = 40;
+ private static int testField0041 = 41;
+ private static int testField0042 = 42;
+ private static int testField0043 = 43;
+ private static int testField0044 = 44;
+ private static int testField0045 = 45;
+ private static int testField0046 = 46;
+ private static int testField0047 = 47;
+ private static int testField0048 = 48;
+ private static int testField0049 = 49;
+ private static int testField0050 = 50;
+ private static int testField0051 = 51;
+ private static int testField0052 = 52;
+ private static int testField0053 = 53;
+ private static int testField0054 = 54;
+ private static int testField0055 = 55;
+ private static int testField0056 = 56;
+ private static int testField0057 = 57;
+ private static int testField0058 = 58;
+ private static int testField0059 = 59;
+ private static int testField0060 = 60;
+ private static int testField0061 = 61;
+ private static int testField0062 = 62;
+ private static int testField0063 = 63;
+ private static int testField0064 = 64;
+ private static int testField0065 = 65;
+ private static int testField0066 = 66;
+ private static int testField0067 = 67;
+ private static int testField0068 = 68;
+ private static int testField0069 = 69;
+ private static int testField0070 = 70;
+ private static int testField0071 = 71;
+ private static int testField0072 = 72;
+ private static int testField0073 = 73;
+ private static int testField0074 = 74;
+ private static int testField0075 = 75;
+ private static int testField0076 = 76;
+ private static int testField0077 = 77;
+ private static int testField0078 = 78;
+ private static int testField0079 = 79;
+ private static int testField0080 = 80;
+ private static int testField0081 = 81;
+ private static int testField0082 = 82;
+ private static int testField0083 = 83;
+ private static int testField0084 = 84;
+ private static int testField0085 = 85;
+ private static int testField0086 = 86;
+ private static int testField0087 = 87;
+ private static int testField0088 = 88;
+ private static int testField0089 = 89;
+ private static int testField0090 = 90;
+ private static int testField0091 = 91;
+ private static int testField0092 = 92;
+ private static int testField0093 = 93;
+ private static int testField0094 = 94;
+ private static int testField0095 = 95;
+ private static int testField0096 = 96;
+ private static int testField0097 = 97;
+ private static int testField0098 = 98;
+ private static int testField0099 = 99;
+ private static int testField0100 = 100;
+ private static int testField0101 = 101;
+ private static int testField0102 = 102;
+ private static int testField0103 = 103;
+ private static int testField0104 = 104;
+ private static int testField0105 = 105;
+ private static int testField0106 = 106;
+ private static int testField0107 = 107;
+ private static int testField0108 = 108;
+ private static int testField0109 = 109;
+ private static int testField0110 = 110;
+ private static int testField0111 = 111;
+ private static int testField0112 = 112;
+ private static int testField0113 = 113;
+ private static int testField0114 = 114;
+ private static int testField0115 = 115;
+ private static int testField0116 = 116;
+ private static int testField0117 = 117;
+ private static int testField0118 = 118;
+ private static int testField0119 = 119;
+ private static int testField0120 = 120;
+ private static int testField0121 = 121;
+ private static int testField0122 = 122;
+ private static int testField0123 = 123;
+ private static int testField0124 = 124;
+ private static int testField0125 = 125;
+ private static int testField0126 = 126;
+ private static int testField0127 = 127;
+ private static int testField0128 = 128;
+ private static int testField0129 = 129;
+ private static int testField0130 = 130;
+ private static int testField0131 = 131;
+ private static int testField0132 = 132;
+ private static int testField0133 = 133;
+ private static int testField0134 = 134;
+ private static int testField0135 = 135;
+ private static int testField0136 = 136;
+ private static int testField0137 = 137;
+ private static int testField0138 = 138;
+ private static int testField0139 = 139;
+ private static int testField0140 = 140;
+ private static int testField0141 = 141;
+ private static int testField0142 = 142;
+ private static int testField0143 = 143;
+ private static int testField0144 = 144;
+ private static int testField0145 = 145;
+ private static int testField0146 = 146;
+ private static int testField0147 = 147;
+ private static int testField0148 = 148;
+ private static int testField0149 = 149;
+ private static int testField0150 = 150;
+ private static int testField0151 = 151;
+ private static int testField0152 = 152;
+ private static int testField0153 = 153;
+ private static int testField0154 = 154;
+ private static int testField0155 = 155;
+ private static int testField0156 = 156;
+ private static int testField0157 = 157;
+ private static int testField0158 = 158;
+ private static int testField0159 = 159;
+ private static int testField0160 = 160;
+ private static int testField0161 = 161;
+ private static int testField0162 = 162;
+ private static int testField0163 = 163;
+ private static int testField0164 = 164;
+ private static int testField0165 = 165;
+ private static int testField0166 = 166;
+ private static int testField0167 = 167;
+ private static int testField0168 = 168;
+ private static int testField0169 = 169;
+ private static int testField0170 = 170;
+ private static int testField0171 = 171;
+ private static int testField0172 = 172;
+ private static int testField0173 = 173;
+ private static int testField0174 = 174;
+ private static int testField0175 = 175;
+ private static int testField0176 = 176;
+ private static int testField0177 = 177;
+ private static int testField0178 = 178;
+ private static int testField0179 = 179;
+ private static int testField0180 = 180;
+ private static int testField0181 = 181;
+ private static int testField0182 = 182;
+ private static int testField0183 = 183;
+ private static int testField0184 = 184;
+ private static int testField0185 = 185;
+ private static int testField0186 = 186;
+ private static int testField0187 = 187;
+ private static int testField0188 = 188;
+ private static int testField0189 = 189;
+ private static int testField0190 = 190;
+ private static int testField0191 = 191;
+ private static int testField0192 = 192;
+ private static int testField0193 = 193;
+ private static int testField0194 = 194;
+ private static int testField0195 = 195;
+ private static int testField0196 = 196;
+ private static int testField0197 = 197;
+ private static int testField0198 = 198;
+ private static int testField0199 = 199;
+ private static int testField0200 = 200;
+ private static int testField0201 = 201;
+ private static int testField0202 = 202;
+ private static int testField0203 = 203;
+ private static int testField0204 = 204;
+ private static int testField0205 = 205;
+ private static int testField0206 = 206;
+ private static int testField0207 = 207;
+ private static int testField0208 = 208;
+ private static int testField0209 = 209;
+ private static int testField0210 = 210;
+ private static int testField0211 = 211;
+ private static int testField0212 = 212;
+ private static int testField0213 = 213;
+ private static int testField0214 = 214;
+ private static int testField0215 = 215;
+ private static int testField0216 = 216;
+ private static int testField0217 = 217;
+ private static int testField0218 = 218;
+ private static int testField0219 = 219;
+ private static int testField0220 = 220;
+ private static int testField0221 = 221;
+ private static int testField0222 = 222;
+ private static int testField0223 = 223;
+ private static int testField0224 = 224;
+ private static int testField0225 = 225;
+ private static int testField0226 = 226;
+ private static int testField0227 = 227;
+ private static int testField0228 = 228;
+ private static int testField0229 = 229;
+ private static int testField0230 = 230;
+ private static int testField0231 = 231;
+ private static int testField0232 = 232;
+ private static int testField0233 = 233;
+ private static int testField0234 = 234;
+ private static int testField0235 = 235;
+ private static int testField0236 = 236;
+ private static int testField0237 = 237;
+ private static int testField0238 = 238;
+ private static int testField0239 = 239;
+ private static int testField0240 = 240;
+ private static int testField0241 = 241;
+ private static int testField0242 = 242;
+ private static int testField0243 = 243;
+ private static int testField0244 = 244;
+ private static int testField0245 = 245;
+ private static int testField0246 = 246;
+ private static int testField0247 = 247;
+ private static int testField0248 = 248;
+ private static int testField0249 = 249;
+ private static int testField0250 = 250;
+ private static int testField0251 = 251;
+ private static int testField0252 = 252;
+ private static int testField0253 = 253;
+ private static int testField0254 = 254;
+ private static int testField0255 = 255;
+ private static int testField0256 = 256;
+ private static int testField0257 = 257;
+ private static int testField0258 = 258;
+ private static int testField0259 = 259;
+ private static int testField0260 = 260;
+ private static int testField0261 = 261;
+ private static int testField0262 = 262;
+ private static int testField0263 = 263;
+ private static int testField0264 = 264;
+ private static int testField0265 = 265;
+ private static int testField0266 = 266;
+ private static int testField0267 = 267;
+ private static int testField0268 = 268;
+ private static int testField0269 = 269;
+ private static int testField0270 = 270;
+ private static int testField0271 = 271;
+ private static int testField0272 = 272;
+ private static int testField0273 = 273;
+ private static int testField0274 = 274;
+ private static int testField0275 = 275;
+ private static int testField0276 = 276;
+ private static int testField0277 = 277;
+ private static int testField0278 = 278;
+ private static int testField0279 = 279;
+ private static int testField0280 = 280;
+ private static int testField0281 = 281;
+ private static int testField0282 = 282;
+ private static int testField0283 = 283;
+ private static int testField0284 = 284;
+ private static int testField0285 = 285;
+ private static int testField0286 = 286;
+ private static int testField0287 = 287;
+ private static int testField0288 = 288;
+ private static int testField0289 = 289;
+ private static int testField0290 = 290;
+ private static int testField0291 = 291;
+ private static int testField0292 = 292;
+ private static int testField0293 = 293;
+ private static int testField0294 = 294;
+ private static int testField0295 = 295;
+ private static int testField0296 = 296;
+ private static int testField0297 = 297;
+ private static int testField0298 = 298;
+ private static int testField0299 = 299;
+ private static int testField0300 = 300;
+ private static int testField0301 = 301;
+ private static int testField0302 = 302;
+ private static int testField0303 = 303;
+ private static int testField0304 = 304;
+ private static int testField0305 = 305;
+ private static int testField0306 = 306;
+ private static int testField0307 = 307;
+ private static int testField0308 = 308;
+ private static int testField0309 = 309;
+ private static int testField0310 = 310;
+ private static int testField0311 = 311;
+ private static int testField0312 = 312;
+ private static int testField0313 = 313;
+ private static int testField0314 = 314;
+ private static int testField0315 = 315;
+ private static int testField0316 = 316;
+ private static int testField0317 = 317;
+ private static int testField0318 = 318;
+ private static int testField0319 = 319;
+ private static int testField0320 = 320;
+ private static int testField0321 = 321;
+ private static int testField0322 = 322;
+ private static int testField0323 = 323;
+ private static int testField0324 = 324;
+ private static int testField0325 = 325;
+ private static int testField0326 = 326;
+ private static int testField0327 = 327;
+ private static int testField0328 = 328;
+ private static int testField0329 = 329;
+ private static int testField0330 = 330;
+ private static int testField0331 = 331;
+ private static int testField0332 = 332;
+ private static int testField0333 = 333;
+ private static int testField0334 = 334;
+ private static int testField0335 = 335;
+ private static int testField0336 = 336;
+ private static int testField0337 = 337;
+ private static int testField0338 = 338;
+ private static int testField0339 = 339;
+ private static int testField0340 = 340;
+ private static int testField0341 = 341;
+ private static int testField0342 = 342;
+ private static int testField0343 = 343;
+ private static int testField0344 = 344;
+ private static int testField0345 = 345;
+ private static int testField0346 = 346;
+ private static int testField0347 = 347;
+ private static int testField0348 = 348;
+ private static int testField0349 = 349;
+ private static int testField0350 = 350;
+ private static int testField0351 = 351;
+ private static int testField0352 = 352;
+ private static int testField0353 = 353;
+ private static int testField0354 = 354;
+ private static int testField0355 = 355;
+ private static int testField0356 = 356;
+ private static int testField0357 = 357;
+ private static int testField0358 = 358;
+ private static int testField0359 = 359;
+ private static int testField0360 = 360;
+ private static int testField0361 = 361;
+ private static int testField0362 = 362;
+ private static int testField0363 = 363;
+ private static int testField0364 = 364;
+ private static int testField0365 = 365;
+ private static int testField0366 = 366;
+ private static int testField0367 = 367;
+ private static int testField0368 = 368;
+ private static int testField0369 = 369;
+ private static int testField0370 = 370;
+ private static int testField0371 = 371;
+ private static int testField0372 = 372;
+ private static int testField0373 = 373;
+ private static int testField0374 = 374;
+ private static int testField0375 = 375;
+ private static int testField0376 = 376;
+ private static int testField0377 = 377;
+ private static int testField0378 = 378;
+ private static int testField0379 = 379;
+ private static int testField0380 = 380;
+ private static int testField0381 = 381;
+ private static int testField0382 = 382;
+ private static int testField0383 = 383;
+ private static int testField0384 = 384;
+ private static int testField0385 = 385;
+ private static int testField0386 = 386;
+ private static int testField0387 = 387;
+ private static int testField0388 = 388;
+ private static int testField0389 = 389;
+ private static int testField0390 = 390;
+ private static int testField0391 = 391;
+ private static int testField0392 = 392;
+ private static int testField0393 = 393;
+ private static int testField0394 = 394;
+ private static int testField0395 = 395;
+ private static int testField0396 = 396;
+ private static int testField0397 = 397;
+ private static int testField0398 = 398;
+ private static int testField0399 = 399;
+ private static int testField0400 = 400;
+ private static int testField0401 = 401;
+ private static int testField0402 = 402;
+ private static int testField0403 = 403;
+ private static int testField0404 = 404;
+ private static int testField0405 = 405;
+ private static int testField0406 = 406;
+ private static int testField0407 = 407;
+ private static int testField0408 = 408;
+ private static int testField0409 = 409;
+ private static int testField0410 = 410;
+ private static int testField0411 = 411;
+ private static int testField0412 = 412;
+ private static int testField0413 = 413;
+ private static int testField0414 = 414;
+ private static int testField0415 = 415;
+ private static int testField0416 = 416;
+ private static int testField0417 = 417;
+ private static int testField0418 = 418;
+ private static int testField0419 = 419;
+ private static int testField0420 = 420;
+ private static int testField0421 = 421;
+ private static int testField0422 = 422;
+ private static int testField0423 = 423;
+ private static int testField0424 = 424;
+ private static int testField0425 = 425;
+ private static int testField0426 = 426;
+ private static int testField0427 = 427;
+ private static int testField0428 = 428;
+ private static int testField0429 = 429;
+ private static int testField0430 = 430;
+ private static int testField0431 = 431;
+ private static int testField0432 = 432;
+ private static int testField0433 = 433;
+ private static int testField0434 = 434;
+ private static int testField0435 = 435;
+ private static int testField0436 = 436;
+ private static int testField0437 = 437;
+ private static int testField0438 = 438;
+ private static int testField0439 = 439;
+ private static int testField0440 = 440;
+ private static int testField0441 = 441;
+ private static int testField0442 = 442;
+ private static int testField0443 = 443;
+ private static int testField0444 = 444;
+ private static int testField0445 = 445;
+ private static int testField0446 = 446;
+ private static int testField0447 = 447;
+ private static int testField0448 = 448;
+ private static int testField0449 = 449;
+ private static int testField0450 = 450;
+ private static int testField0451 = 451;
+ private static int testField0452 = 452;
+ private static int testField0453 = 453;
+ private static int testField0454 = 454;
+ private static int testField0455 = 455;
+ private static int testField0456 = 456;
+ private static int testField0457 = 457;
+ private static int testField0458 = 458;
+ private static int testField0459 = 459;
+ private static int testField0460 = 460;
+ private static int testField0461 = 461;
+ private static int testField0462 = 462;
+ private static int testField0463 = 463;
+ private static int testField0464 = 464;
+ private static int testField0465 = 465;
+ private static int testField0466 = 466;
+ private static int testField0467 = 467;
+ private static int testField0468 = 468;
+ private static int testField0469 = 469;
+ private static int testField0470 = 470;
+ private static int testField0471 = 471;
+ private static int testField0472 = 472;
+ private static int testField0473 = 473;
+ private static int testField0474 = 474;
+ private static int testField0475 = 475;
+ private static int testField0476 = 476;
+ private static int testField0477 = 477;
+ private static int testField0478 = 478;
+ private static int testField0479 = 479;
+ private static int testField0480 = 480;
+ private static int testField0481 = 481;
+ private static int testField0482 = 482;
+ private static int testField0483 = 483;
+ private static int testField0484 = 484;
+ private static int testField0485 = 485;
+ private static int testField0486 = 486;
+ private static int testField0487 = 487;
+ private static int testField0488 = 488;
+ private static int testField0489 = 489;
+ private static int testField0490 = 490;
+ private static int testField0491 = 491;
+ private static int testField0492 = 492;
+ private static int testField0493 = 493;
+ private static int testField0494 = 494;
+ private static int testField0495 = 495;
+ private static int testField0496 = 496;
+ private static int testField0497 = 497;
+ private static int testField0498 = 498;
+ private static int testField0499 = 499;
+ private static int testField0500 = 500;
+ private static int testField0501 = 501;
+ private static int testField0502 = 502;
+ private static int testField0503 = 503;
+ private static int testField0504 = 504;
+ private static int testField0505 = 505;
+ private static int testField0506 = 506;
+ private static int testField0507 = 507;
+ private static int testField0508 = 508;
+ private static int testField0509 = 509;
+ private static int testField0510 = 510;
+ private static int testField0511 = 511;
+ private static int testField0512 = 512;
+ private static int testField0513 = 513;
+ private static int testField0514 = 514;
+ private static int testField0515 = 515;
+ private static int testField0516 = 516;
+ private static int testField0517 = 517;
+ private static int testField0518 = 518;
+ private static int testField0519 = 519;
+ private static int testField0520 = 520;
+ private static int testField0521 = 521;
+ private static int testField0522 = 522;
+ private static int testField0523 = 523;
+ private static int testField0524 = 524;
+ private static int testField0525 = 525;
+ private static int testField0526 = 526;
+ private static int testField0527 = 527;
+ private static int testField0528 = 528;
+ private static int testField0529 = 529;
+ private static int testField0530 = 530;
+ private static int testField0531 = 531;
+ private static int testField0532 = 532;
+ private static int testField0533 = 533;
+ private static int testField0534 = 534;
+ private static int testField0535 = 535;
+ private static int testField0536 = 536;
+ private static int testField0537 = 537;
+ private static int testField0538 = 538;
+ private static int testField0539 = 539;
+ private static int testField0540 = 540;
+ private static int testField0541 = 541;
+ private static int testField0542 = 542;
+ private static int testField0543 = 543;
+ private static int testField0544 = 544;
+ private static int testField0545 = 545;
+ private static int testField0546 = 546;
+ private static int testField0547 = 547;
+ private static int testField0548 = 548;
+ private static int testField0549 = 549;
+ private static int testField0550 = 550;
+ private static int testField0551 = 551;
+ private static int testField0552 = 552;
+ private static int testField0553 = 553;
+ private static int testField0554 = 554;
+ private static int testField0555 = 555;
+ private static int testField0556 = 556;
+ private static int testField0557 = 557;
+ private static int testField0558 = 558;
+ private static int testField0559 = 559;
+ private static int testField0560 = 560;
+ private static int testField0561 = 561;
+ private static int testField0562 = 562;
+ private static int testField0563 = 563;
+ private static int testField0564 = 564;
+ private static int testField0565 = 565;
+ private static int testField0566 = 566;
+ private static int testField0567 = 567;
+ private static int testField0568 = 568;
+ private static int testField0569 = 569;
+ private static int testField0570 = 570;
+ private static int testField0571 = 571;
+ private static int testField0572 = 572;
+ private static int testField0573 = 573;
+ private static int testField0574 = 574;
+ private static int testField0575 = 575;
+ private static int testField0576 = 576;
+ private static int testField0577 = 577;
+ private static int testField0578 = 578;
+ private static int testField0579 = 579;
+ private static int testField0580 = 580;
+ private static int testField0581 = 581;
+ private static int testField0582 = 582;
+ private static int testField0583 = 583;
+ private static int testField0584 = 584;
+ private static int testField0585 = 585;
+ private static int testField0586 = 586;
+ private static int testField0587 = 587;
+ private static int testField0588 = 588;
+ private static int testField0589 = 589;
+ private static int testField0590 = 590;
+ private static int testField0591 = 591;
+ private static int testField0592 = 592;
+ private static int testField0593 = 593;
+ private static int testField0594 = 594;
+ private static int testField0595 = 595;
+ private static int testField0596 = 596;
+ private static int testField0597 = 597;
+ private static int testField0598 = 598;
+ private static int testField0599 = 599;
+ private static int testField0600 = 600;
+ private static int testField0601 = 601;
+ private static int testField0602 = 602;
+ private static int testField0603 = 603;
+ private static int testField0604 = 604;
+ private static int testField0605 = 605;
+ private static int testField0606 = 606;
+ private static int testField0607 = 607;
+ private static int testField0608 = 608;
+ private static int testField0609 = 609;
+ private static int testField0610 = 610;
+ private static int testField0611 = 611;
+ private static int testField0612 = 612;
+ private static int testField0613 = 613;
+ private static int testField0614 = 614;
+ private static int testField0615 = 615;
+ private static int testField0616 = 616;
+ private static int testField0617 = 617;
+ private static int testField0618 = 618;
+ private static int testField0619 = 619;
+ private static int testField0620 = 620;
+ private static int testField0621 = 621;
+ private static int testField0622 = 622;
+ private static int testField0623 = 623;
+ private static int testField0624 = 624;
+ private static int testField0625 = 625;
+ private static int testField0626 = 626;
+ private static int testField0627 = 627;
+ private static int testField0628 = 628;
+ private static int testField0629 = 629;
+ private static int testField0630 = 630;
+ private static int testField0631 = 631;
+ private static int testField0632 = 632;
+ private static int testField0633 = 633;
+ private static int testField0634 = 634;
+ private static int testField0635 = 635;
+ private static int testField0636 = 636;
+ private static int testField0637 = 637;
+ private static int testField0638 = 638;
+ private static int testField0639 = 639;
+ private static int testField0640 = 640;
+ private static int testField0641 = 641;
+ private static int testField0642 = 642;
+ private static int testField0643 = 643;
+ private static int testField0644 = 644;
+ private static int testField0645 = 645;
+ private static int testField0646 = 646;
+ private static int testField0647 = 647;
+ private static int testField0648 = 648;
+ private static int testField0649 = 649;
+ private static int testField0650 = 650;
+ private static int testField0651 = 651;
+ private static int testField0652 = 652;
+ private static int testField0653 = 653;
+ private static int testField0654 = 654;
+ private static int testField0655 = 655;
+ private static int testField0656 = 656;
+ private static int testField0657 = 657;
+ private static int testField0658 = 658;
+ private static int testField0659 = 659;
+ private static int testField0660 = 660;
+ private static int testField0661 = 661;
+ private static int testField0662 = 662;
+ private static int testField0663 = 663;
+ private static int testField0664 = 664;
+ private static int testField0665 = 665;
+ private static int testField0666 = 666;
+ private static int testField0667 = 667;
+ private static int testField0668 = 668;
+ private static int testField0669 = 669;
+ private static int testField0670 = 670;
+ private static int testField0671 = 671;
+ private static int testField0672 = 672;
+ private static int testField0673 = 673;
+ private static int testField0674 = 674;
+ private static int testField0675 = 675;
+ private static int testField0676 = 676;
+ private static int testField0677 = 677;
+ private static int testField0678 = 678;
+ private static int testField0679 = 679;
+ private static int testField0680 = 680;
+ private static int testField0681 = 681;
+ private static int testField0682 = 682;
+ private static int testField0683 = 683;
+ private static int testField0684 = 684;
+ private static int testField0685 = 685;
+ private static int testField0686 = 686;
+ private static int testField0687 = 687;
+ private static int testField0688 = 688;
+ private static int testField0689 = 689;
+ private static int testField0690 = 690;
+ private static int testField0691 = 691;
+ private static int testField0692 = 692;
+ private static int testField0693 = 693;
+ private static int testField0694 = 694;
+ private static int testField0695 = 695;
+ private static int testField0696 = 696;
+ private static int testField0697 = 697;
+ private static int testField0698 = 698;
+ private static int testField0699 = 699;
+ private static int testField0700 = 700;
+ private static int testField0701 = 701;
+ private static int testField0702 = 702;
+ private static int testField0703 = 703;
+ private static int testField0704 = 704;
+ private static int testField0705 = 705;
+ private static int testField0706 = 706;
+ private static int testField0707 = 707;
+ private static int testField0708 = 708;
+ private static int testField0709 = 709;
+ private static int testField0710 = 710;
+ private static int testField0711 = 711;
+ private static int testField0712 = 712;
+ private static int testField0713 = 713;
+ private static int testField0714 = 714;
+ private static int testField0715 = 715;
+ private static int testField0716 = 716;
+ private static int testField0717 = 717;
+ private static int testField0718 = 718;
+ private static int testField0719 = 719;
+ private static int testField0720 = 720;
+ private static int testField0721 = 721;
+ private static int testField0722 = 722;
+ private static int testField0723 = 723;
+ private static int testField0724 = 724;
+ private static int testField0725 = 725;
+ private static int testField0726 = 726;
+ private static int testField0727 = 727;
+ private static int testField0728 = 728;
+ private static int testField0729 = 729;
+ private static int testField0730 = 730;
+ private static int testField0731 = 731;
+ private static int testField0732 = 732;
+ private static int testField0733 = 733;
+ private static int testField0734 = 734;
+ private static int testField0735 = 735;
+ private static int testField0736 = 736;
+ private static int testField0737 = 737;
+ private static int testField0738 = 738;
+ private static int testField0739 = 739;
+ private static int testField0740 = 740;
+ private static int testField0741 = 741;
+ private static int testField0742 = 742;
+ private static int testField0743 = 743;
+ private static int testField0744 = 744;
+ private static int testField0745 = 745;
+ private static int testField0746 = 746;
+ private static int testField0747 = 747;
+ private static int testField0748 = 748;
+ private static int testField0749 = 749;
+ private static int testField0750 = 750;
+ private static int testField0751 = 751;
+ private static int testField0752 = 752;
+ private static int testField0753 = 753;
+ private static int testField0754 = 754;
+ private static int testField0755 = 755;
+ private static int testField0756 = 756;
+ private static int testField0757 = 757;
+ private static int testField0758 = 758;
+ private static int testField0759 = 759;
+ private static int testField0760 = 760;
+ private static int testField0761 = 761;
+ private static int testField0762 = 762;
+ private static int testField0763 = 763;
+ private static int testField0764 = 764;
+ private static int testField0765 = 765;
+ private static int testField0766 = 766;
+ private static int testField0767 = 767;
+ private static int testField0768 = 768;
+ private static int testField0769 = 769;
+ private static int testField0770 = 770;
+ private static int testField0771 = 771;
+ private static int testField0772 = 772;
+ private static int testField0773 = 773;
+ private static int testField0774 = 774;
+ private static int testField0775 = 775;
+ private static int testField0776 = 776;
+ private static int testField0777 = 777;
+ private static int testField0778 = 778;
+ private static int testField0779 = 779;
+ private static int testField0780 = 780;
+ private static int testField0781 = 781;
+ private static int testField0782 = 782;
+ private static int testField0783 = 783;
+ private static int testField0784 = 784;
+ private static int testField0785 = 785;
+ private static int testField0786 = 786;
+ private static int testField0787 = 787;
+ private static int testField0788 = 788;
+ private static int testField0789 = 789;
+ private static int testField0790 = 790;
+ private static int testField0791 = 791;
+ private static int testField0792 = 792;
+ private static int testField0793 = 793;
+ private static int testField0794 = 794;
+ private static int testField0795 = 795;
+ private static int testField0796 = 796;
+ private static int testField0797 = 797;
+ private static int testField0798 = 798;
+ private static int testField0799 = 799;
+ private static int testField0800 = 800;
+ private static int testField0801 = 801;
+ private static int testField0802 = 802;
+ private static int testField0803 = 803;
+ private static int testField0804 = 804;
+ private static int testField0805 = 805;
+ private static int testField0806 = 806;
+ private static int testField0807 = 807;
+ private static int testField0808 = 808;
+ private static int testField0809 = 809;
+ private static int testField0810 = 810;
+ private static int testField0811 = 811;
+ private static int testField0812 = 812;
+ private static int testField0813 = 813;
+ private static int testField0814 = 814;
+ private static int testField0815 = 815;
+ private static int testField0816 = 816;
+ private static int testField0817 = 817;
+ private static int testField0818 = 818;
+ private static int testField0819 = 819;
+ private static int testField0820 = 820;
+ private static int testField0821 = 821;
+ private static int testField0822 = 822;
+ private static int testField0823 = 823;
+ private static int testField0824 = 824;
+ private static int testField0825 = 825;
+ private static int testField0826 = 826;
+ private static int testField0827 = 827;
+ private static int testField0828 = 828;
+ private static int testField0829 = 829;
+ private static int testField0830 = 830;
+ private static int testField0831 = 831;
+ private static int testField0832 = 832;
+ private static int testField0833 = 833;
+ private static int testField0834 = 834;
+ private static int testField0835 = 835;
+ private static int testField0836 = 836;
+ private static int testField0837 = 837;
+ private static int testField0838 = 838;
+ private static int testField0839 = 839;
+ private static int testField0840 = 840;
+ private static int testField0841 = 841;
+ private static int testField0842 = 842;
+ private static int testField0843 = 843;
+ private static int testField0844 = 844;
+ private static int testField0845 = 845;
+ private static int testField0846 = 846;
+ private static int testField0847 = 847;
+ private static int testField0848 = 848;
+ private static int testField0849 = 849;
+ private static int testField0850 = 850;
+ private static int testField0851 = 851;
+ private static int testField0852 = 852;
+ private static int testField0853 = 853;
+ private static int testField0854 = 854;
+ private static int testField0855 = 855;
+ private static int testField0856 = 856;
+ private static int testField0857 = 857;
+ private static int testField0858 = 858;
+ private static int testField0859 = 859;
+ private static int testField0860 = 860;
+ private static int testField0861 = 861;
+ private static int testField0862 = 862;
+ private static int testField0863 = 863;
+ private static int testField0864 = 864;
+ private static int testField0865 = 865;
+ private static int testField0866 = 866;
+ private static int testField0867 = 867;
+ private static int testField0868 = 868;
+ private static int testField0869 = 869;
+ private static int testField0870 = 870;
+ private static int testField0871 = 871;
+ private static int testField0872 = 872;
+ private static int testField0873 = 873;
+ private static int testField0874 = 874;
+ private static int testField0875 = 875;
+ private static int testField0876 = 876;
+ private static int testField0877 = 877;
+ private static int testField0878 = 878;
+ private static int testField0879 = 879;
+ private static int testField0880 = 880;
+ private static int testField0881 = 881;
+ private static int testField0882 = 882;
+ private static int testField0883 = 883;
+ private static int testField0884 = 884;
+ private static int testField0885 = 885;
+ private static int testField0886 = 886;
+ private static int testField0887 = 887;
+ private static int testField0888 = 888;
+ private static int testField0889 = 889;
+ private static int testField0890 = 890;
+ private static int testField0891 = 891;
+ private static int testField0892 = 892;
+ private static int testField0893 = 893;
+ private static int testField0894 = 894;
+ private static int testField0895 = 895;
+ private static int testField0896 = 896;
+ private static int testField0897 = 897;
+ private static int testField0898 = 898;
+ private static int testField0899 = 899;
+ private static int testField0900 = 900;
+ private static int testField0901 = 901;
+ private static int testField0902 = 902;
+ private static int testField0903 = 903;
+ private static int testField0904 = 904;
+ private static int testField0905 = 905;
+ private static int testField0906 = 906;
+ private static int testField0907 = 907;
+ private static int testField0908 = 908;
+ private static int testField0909 = 909;
+ private static int testField0910 = 910;
+ private static int testField0911 = 911;
+ private static int testField0912 = 912;
+ private static int testField0913 = 913;
+ private static int testField0914 = 914;
+ private static int testField0915 = 915;
+ private static int testField0916 = 916;
+ private static int testField0917 = 917;
+ private static int testField0918 = 918;
+ private static int testField0919 = 919;
+ private static int testField0920 = 920;
+ private static int testField0921 = 921;
+ private static int testField0922 = 922;
+ private static int testField0923 = 923;
+ private static int testField0924 = 924;
+ private static int testField0925 = 925;
+ private static int testField0926 = 926;
+ private static int testField0927 = 927;
+ private static int testField0928 = 928;
+ private static int testField0929 = 929;
+ private static int testField0930 = 930;
+ private static int testField0931 = 931;
+ private static int testField0932 = 932;
+ private static int testField0933 = 933;
+ private static int testField0934 = 934;
+ private static int testField0935 = 935;
+ private static int testField0936 = 936;
+ private static int testField0937 = 937;
+ private static int testField0938 = 938;
+ private static int testField0939 = 939;
+ private static int testField0940 = 940;
+ private static int testField0941 = 941;
+ private static int testField0942 = 942;
+ private static int testField0943 = 943;
+ private static int testField0944 = 944;
+ private static int testField0945 = 945;
+ private static int testField0946 = 946;
+ private static int testField0947 = 947;
+ private static int testField0948 = 948;
+ private static int testField0949 = 949;
+ private static int testField0950 = 950;
+ private static int testField0951 = 951;
+ private static int testField0952 = 952;
+ private static int testField0953 = 953;
+ private static int testField0954 = 954;
+ private static int testField0955 = 955;
+ private static int testField0956 = 956;
+ private static int testField0957 = 957;
+ private static int testField0958 = 958;
+ private static int testField0959 = 959;
+ private static int testField0960 = 960;
+ private static int testField0961 = 961;
+ private static int testField0962 = 962;
+ private static int testField0963 = 963;
+ private static int testField0964 = 964;
+ private static int testField0965 = 965;
+ private static int testField0966 = 966;
+ private static int testField0967 = 967;
+ private static int testField0968 = 968;
+ private static int testField0969 = 969;
+ private static int testField0970 = 970;
+ private static int testField0971 = 971;
+ private static int testField0972 = 972;
+ private static int testField0973 = 973;
+ private static int testField0974 = 974;
+ private static int testField0975 = 975;
+ private static int testField0976 = 976;
+ private static int testField0977 = 977;
+ private static int testField0978 = 978;
+ private static int testField0979 = 979;
+ private static int testField0980 = 980;
+ private static int testField0981 = 981;
+ private static int testField0982 = 982;
+ private static int testField0983 = 983;
+ private static int testField0984 = 984;
+ private static int testField0985 = 985;
+ private static int testField0986 = 986;
+ private static int testField0987 = 987;
+ private static int testField0988 = 988;
+ private static int testField0989 = 989;
+ private static int testField0990 = 990;
+ private static int testField0991 = 991;
+ private static int testField0992 = 992;
+ private static int testField0993 = 993;
+ private static int testField0994 = 994;
+ private static int testField0995 = 995;
+ private static int testField0996 = 996;
+ private static int testField0997 = 997;
+ private static int testField0998 = 998;
+ private static int testField0999 = 999;
+ private static int testField1000 = 1000;
+ private static int testField1001 = 1001;
+ private static int testField1002 = 1002;
+ private static int testField1003 = 1003;
+ private static int testField1004 = 1004;
+ private static int testField1005 = 1005;
+ private static int testField1006 = 1006;
+ private static int testField1007 = 1007;
+ private static int testField1008 = 1008;
+ private static int testField1009 = 1009;
+ private static int testField1010 = 1010;
+ private static int testField1011 = 1011;
+ private static int testField1012 = 1012;
+ private static int testField1013 = 1013;
+ private static int testField1014 = 1014;
+ private static int testField1015 = 1015;
+ private static int testField1016 = 1016;
+ private static int testField1017 = 1017;
+ private static int testField1018 = 1018;
+ private static int testField1019 = 1019;
+ private static int testField1020 = 1020;
+ private static int testField1021 = 1021;
+ private static int testField1022 = 1022;
+ private static int testField1023 = 1023;
+}
diff --git a/test/616-cha-abstract/src/Main.java b/test/616-cha-abstract/src/Main.java
index b33f575..e1d7db1 100644
--- a/test/616-cha-abstract/src/Main.java
+++ b/test/616-cha-abstract/src/Main.java
@@ -39,8 +39,8 @@
}
public class Main {
- static Base sMain1;
- static Base sMain2;
+ static Main1 sMain1;
+ static Main1 sMain2;
static boolean sIsOptimizing = true;
static boolean sHasJIT = true;
diff --git a/test/616-cha-interface-default/expected.txt b/test/616-cha-interface-default/expected.txt
deleted file mode 100644
index 6a5618e..0000000
--- a/test/616-cha-interface-default/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-JNI_OnLoad called
diff --git a/test/616-cha-interface-default/info.txt b/test/616-cha-interface-default/info.txt
deleted file mode 100644
index 11baa1f..0000000
--- a/test/616-cha-interface-default/info.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Test for Class Hierarchy Analysis (CHA) on interface method.
-Test it under multidex configuration to check cross-dex inlining.
diff --git a/test/616-cha-interface-default/multidex.jpp b/test/616-cha-interface-default/multidex.jpp
deleted file mode 100644
index b0d200e..0000000
--- a/test/616-cha-interface-default/multidex.jpp
+++ /dev/null
@@ -1,3 +0,0 @@
-Main:
- @@com.android.jack.annotations.ForceInMainDex
- class Main
diff --git a/test/616-cha-interface-default/src-multidex/Base.java b/test/616-cha-interface-default/src-multidex/Base.java
deleted file mode 100644
index 2cbcb50..0000000
--- a/test/616-cha-interface-default/src-multidex/Base.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-interface Base {
- default public int foo(int i) {
- if (i != 1) {
- return -2;
- }
- return i + 10;
- }
-
- // Test default method that's not inlined.
- default public int $noinline$bar() {
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- return -1;
- }
-
- default void printError(String msg) {
- System.out.println(msg);
- }
-}
diff --git a/test/616-cha-interface-default/src/Main.java b/test/616-cha-interface-default/src/Main.java
deleted file mode 100644
index 951607d..0000000
--- a/test/616-cha-interface-default/src/Main.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-class Main1 implements Base {
-}
-
-class Main2 extends Main1 {
- public void foobar() {}
-}
-
-class Main3 implements Base {
- public int foo(int i) {
- if (i != 3) {
- printError("error3");
- }
- return -(i + 10);
- }
-}
-
-public class Main {
- static Base sMain1;
- static Base sMain2;
- static Base sMain3;
-
- static boolean sIsOptimizing = true;
- static boolean sHasJIT = true;
- static volatile boolean sOtherThreadStarted;
-
- private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) {
- if (hasSingleImplementation(clazz, method_name) != b) {
- System.out.println(clazz + "." + method_name +
- " doesn't have single implementation value of " + b);
- }
- }
-
- static int getValue(Class<?> cls) {
- if (cls == Main1.class || cls == Main2.class) {
- return 1;
- }
- return 3;
- }
-
- // sMain1.foo()/sMain2.foo() will be always be Base.foo() before Main3 is loaded/linked.
- // So sMain1.foo() can be devirtualized to Base.foo() and be inlined.
- // After Dummy.createMain3() which links in Main3, live testImplement() on stack
- // should be deoptimized.
- static void testImplement(boolean createMain3, boolean wait, boolean setHasJIT) {
- if (setHasJIT) {
- if (isInterpreted()) {
- sHasJIT = false;
- }
- return;
- }
-
- if (createMain3 && (sIsOptimizing || sHasJIT)) {
- assertIsManaged();
- }
-
- if (sMain1.foo(getValue(sMain1.getClass())) != 11) {
- System.out.println("11 expected.");
- }
- if (sMain1.$noinline$bar() != -1) {
- System.out.println("-1 expected.");
- }
- if (sMain2.foo(getValue(sMain2.getClass())) != 11) {
- System.out.println("11 expected.");
- }
-
- if (createMain3) {
- // Wait for the other thread to start.
- while (!sOtherThreadStarted);
- // Create an Main2 instance and assign it to sMain2.
- // sMain1 is kept the same.
- sMain3 = Dummy.createMain3();
- // Wake up the other thread.
- synchronized(Main.class) {
- Main.class.notify();
- }
- } else if (wait) {
- // This is the other thread.
- synchronized(Main.class) {
- sOtherThreadStarted = true;
- // Wait for Main2 to be linked and deoptimization is triggered.
- try {
- Main.class.wait();
- } catch (Exception e) {
- }
- }
- }
-
- // There should be a deoptimization here right after Main3 is linked by
- // calling Dummy.createMain3(), even though sMain1 didn't change.
- // The behavior here would be different if inline-cache is used, which
- // doesn't deoptimize since sMain1 still hits the type cache.
- if (sMain1.foo(getValue(sMain1.getClass())) != 11) {
- System.out.println("11 expected.");
- }
- if ((createMain3 || wait) && sHasJIT && !sIsOptimizing) {
- // This method should be deoptimized right after Main3 is created.
- assertIsInterpreted();
- }
-
- if (sMain3 != null) {
- if (sMain3.foo(getValue(sMain3.getClass())) != -13) {
- System.out.println("-13 expected.");
- }
- }
- }
-
- // Test scenarios under which CHA-based devirtualization happens,
- // and class loading that implements a method can invalidate compiled code.
- public static void main(String[] args) {
- System.loadLibrary(args[0]);
-
- if (isInterpreted()) {
- sIsOptimizing = false;
- }
-
- // sMain1 is an instance of Main1.
- // sMain2 is an instance of Main2.
- // Neither Main1 nor Main2 override default method Base.foo().
- // Main3 hasn't bee loaded yet.
- sMain1 = new Main1();
- sMain2 = new Main2();
-
- ensureJitCompiled(Main.class, "testImplement");
- testImplement(false, false, true);
-
- if (sHasJIT && !sIsOptimizing) {
- assertSingleImplementation(Base.class, "foo", true);
- assertSingleImplementation(Main1.class, "foo", true);
- } else {
- // Main3 is verified ahead-of-time so it's linked in already.
- }
-
- // Create another thread that also calls sMain1.foo().
- // Try to test suspend and deopt another thread.
- new Thread() {
- public void run() {
- testImplement(false, true, false);
- }
- }.start();
-
- // This will create Main3 instance in the middle of testImplement().
- testImplement(true, false, false);
- assertSingleImplementation(Base.class, "foo", false);
- assertSingleImplementation(Main1.class, "foo", true);
- assertSingleImplementation(sMain3.getClass(), "foo", true);
- }
-
- private static native void ensureJitCompiled(Class<?> itf, String method_name);
- private static native void assertIsInterpreted();
- private static native void assertIsManaged();
- private static native boolean isInterpreted();
- private static native boolean hasSingleImplementation(Class<?> clazz, String method_name);
-}
-
-// Put createMain3() in another class to avoid class loading due to verifier.
-class Dummy {
- static Base createMain3() {
- return new Main3();
- }
-}
diff --git a/test/616-cha-interface/expected.txt b/test/616-cha-interface/expected.txt
deleted file mode 100644
index 6a5618e..0000000
--- a/test/616-cha-interface/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-JNI_OnLoad called
diff --git a/test/616-cha-interface/info.txt b/test/616-cha-interface/info.txt
deleted file mode 100644
index 1fd330a..0000000
--- a/test/616-cha-interface/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test for Class Hierarchy Analysis (CHA) on interface method.
diff --git a/test/616-cha-interface/run b/test/616-cha-interface/run
deleted file mode 100644
index d8b4f0d..0000000
--- a/test/616-cha-interface/run
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 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.
-
-# Run without an app image to prevent the classes to be loaded at startup.
-exec ${RUN} "${@}" --no-app-image
diff --git a/test/616-cha-interface/src/Main.java b/test/616-cha-interface/src/Main.java
deleted file mode 100644
index 3c93496..0000000
--- a/test/616-cha-interface/src/Main.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-interface Base {
- void foo(int i);
- void $noinline$bar();
-}
-
-class Main1 implements Base {
- public void foo(int i) {
- if (i != 1) {
- printError("error1");
- }
- }
-
- // Test rewriting invoke-interface into invoke-virtual when inlining fails.
- public void $noinline$bar() {
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- System.out.print("");
- }
-
- void printError(String msg) {
- System.out.println(msg);
- }
-}
-
-class Main2 extends Main1 {
- public void foo(int i) {
- if (i != 2) {
- printError("error2");
- }
- }
-}
-
-public class Main {
- static Base sMain1;
- static Base sMain2;
-
- static boolean sIsOptimizing = true;
- static boolean sHasJIT = true;
- static volatile boolean sOtherThreadStarted;
-
- private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) {
- if (hasSingleImplementation(clazz, method_name) != b) {
- System.out.println(clazz + "." + method_name +
- " doesn't have single implementation value of " + b);
- }
- }
-
- // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
- // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
- // After Dummy.createMain2() which links in Main2, live testImplement() on stack
- // should be deoptimized.
- static void testImplement(boolean createMain2, boolean wait, boolean setHasJIT) {
- if (setHasJIT) {
- if (isInterpreted()) {
- sHasJIT = false;
- }
- return;
- }
-
- if (createMain2 && (sIsOptimizing || sHasJIT)) {
- assertIsManaged();
- }
-
- sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
- sMain1.$noinline$bar();
-
- if (createMain2) {
- // Wait for the other thread to start.
- while (!sOtherThreadStarted);
- // Create an Main2 instance and assign it to sMain2.
- // sMain1 is kept the same.
- sMain2 = Dummy.createMain2();
- // Wake up the other thread.
- synchronized(Main.class) {
- Main.class.notify();
- }
- } else if (wait) {
- // This is the other thread.
- synchronized(Main.class) {
- sOtherThreadStarted = true;
- // Wait for Main2 to be linked and deoptimization is triggered.
- try {
- Main.class.wait();
- } catch (Exception e) {
- }
- }
- }
-
- // There should be a deoptimization here right after Main2 is linked by
- // calling Dummy.createMain2(), even though sMain1 didn't change.
- // The behavior here would be different if inline-cache is used, which
- // doesn't deoptimize since sMain1 still hits the type cache.
- sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
- if ((createMain2 || wait) && sHasJIT && !sIsOptimizing) {
- // This method should be deoptimized right after Main2 is created.
- assertIsInterpreted();
- }
-
- if (sMain2 != null) {
- sMain2.foo(sMain2.getClass() == Main1.class ? 1 : 2);
- }
- }
-
- // Test scenarios under which CHA-based devirtualization happens,
- // and class loading that overrides a method can invalidate compiled code.
- public static void main(String[] args) {
- System.loadLibrary(args[0]);
-
- if (isInterpreted()) {
- sIsOptimizing = false;
- }
-
- // sMain1 is an instance of Main1. Main2 hasn't bee loaded yet.
- sMain1 = new Main1();
-
- ensureJitCompiled(Main.class, "testImplement");
- testImplement(false, false, true);
-
- if (sHasJIT && !sIsOptimizing) {
- assertSingleImplementation(Base.class, "foo", true);
- assertSingleImplementation(Main1.class, "foo", true);
- } else {
- // Main2 is verified ahead-of-time so it's linked in already.
- }
-
- // Create another thread that also calls sMain1.foo().
- // Try to test suspend and deopt another thread.
- new Thread() {
- public void run() {
- testImplement(false, true, false);
- }
- }.start();
-
- // This will create Main2 instance in the middle of testImplement().
- testImplement(true, false, false);
- assertSingleImplementation(Base.class, "foo", false);
- assertSingleImplementation(Main1.class, "foo", false);
- }
-
- private static native void ensureJitCompiled(Class<?> itf, String method_name);
- private static native void assertIsInterpreted();
- private static native void assertIsManaged();
- private static native boolean isInterpreted();
- private static native boolean hasSingleImplementation(Class<?> clazz, String method_name);
-}
-
-// Put createMain2() in another class to avoid class loading due to verifier.
-class Dummy {
- static Main1 createMain2() {
- return new Main2();
- }
-}
diff --git a/test/616-cha-miranda/expected.txt b/test/616-cha-miranda/expected.txt
deleted file mode 100644
index 6a5618e..0000000
--- a/test/616-cha-miranda/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-JNI_OnLoad called
diff --git a/test/616-cha-miranda/info.txt b/test/616-cha-miranda/info.txt
deleted file mode 100644
index c46f33f..0000000
--- a/test/616-cha-miranda/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test for Class Hierarchy Analysis (CHA) on miranda method.
diff --git a/test/616-cha-miranda/run b/test/616-cha-miranda/run
deleted file mode 100644
index d8b4f0d..0000000
--- a/test/616-cha-miranda/run
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 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.
-
-# Run without an app image to prevent the classes to be loaded at startup.
-exec ${RUN} "${@}" --no-app-image
diff --git a/test/616-cha-miranda/src/Main.java b/test/616-cha-miranda/src/Main.java
deleted file mode 100644
index e548482..0000000
--- a/test/616-cha-miranda/src/Main.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-interface Iface {
- public void foo(int i);
-}
-
-abstract class Base implements Iface {
- // Iface.foo(int) will be added as a miranda method.
-
- void printError(String msg) {
- System.out.println(msg);
- }
-}
-
-class Main1 extends Base {
- public void foo(int i) {
- if (i != 1) {
- printError("error1");
- }
- }
-}
-
-class Main2 extends Main1 {
- public void foo(int i) {
- if (i != 2) {
- printError("error2");
- }
- }
-}
-
-public class Main {
- static Base sMain1;
- static Base sMain2;
-
- static boolean sIsOptimizing = true;
- static boolean sHasJIT = true;
- static volatile boolean sOtherThreadStarted;
-
- private static void assertSingleImplementation(Class<?> clazz, String method_name, boolean b) {
- if (hasSingleImplementation(clazz, method_name) != b) {
- System.out.println(clazz + "." + method_name +
- " doesn't have single implementation value of " + b);
- }
- }
-
- // sMain1.foo() will be always be Main1.foo() before Main2 is loaded/linked.
- // So sMain1.foo() can be devirtualized to Main1.foo() and be inlined.
- // After Dummy.createMain2() which links in Main2, live testOverride() on stack
- // should be deoptimized.
- static void testOverride(boolean createMain2, boolean wait, boolean setHasJIT) {
- if (setHasJIT) {
- if (isInterpreted()) {
- sHasJIT = false;
- }
- return;
- }
-
- if (createMain2 && (sIsOptimizing || sHasJIT)) {
- assertIsManaged();
- }
-
- sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
-
- if (createMain2) {
- // Wait for the other thread to start.
- while (!sOtherThreadStarted);
- // Create an Main2 instance and assign it to sMain2.
- // sMain1 is kept the same.
- sMain2 = Dummy.createMain2();
- // Wake up the other thread.
- synchronized(Main.class) {
- Main.class.notify();
- }
- } else if (wait) {
- // This is the other thread.
- synchronized(Main.class) {
- sOtherThreadStarted = true;
- // Wait for Main2 to be linked and deoptimization is triggered.
- try {
- Main.class.wait();
- } catch (Exception e) {
- }
- }
- }
-
- // There should be a deoptimization here right after Main2 is linked by
- // calling Dummy.createMain2(), even though sMain1 didn't change.
- // The behavior here would be different if inline-cache is used, which
- // doesn't deoptimize since sMain1 still hits the type cache.
- sMain1.foo(sMain1.getClass() == Main1.class ? 1 : 2);
- if ((createMain2 || wait) && sHasJIT && !sIsOptimizing) {
- // This method should be deoptimized right after Main2 is created.
- assertIsInterpreted();
- }
-
- if (sMain2 != null) {
- sMain2.foo(sMain2.getClass() == Main1.class ? 1 : 2);
- }
- }
-
- // Test scenarios under which CHA-based devirtualization happens,
- // and class loading that overrides a method can invalidate compiled code.
- public static void main(String[] args) {
- System.loadLibrary(args[0]);
-
- if (isInterpreted()) {
- sIsOptimizing = false;
- }
-
- // sMain1 is an instance of Main1. Main2 hasn't bee loaded yet.
- sMain1 = new Main1();
-
- ensureJitCompiled(Main.class, "testOverride");
- testOverride(false, false, true);
-
- if (sHasJIT && !sIsOptimizing) {
- assertSingleImplementation(Base.class, "foo", true);
- assertSingleImplementation(Main1.class, "foo", true);
- } else {
- // Main2 is verified ahead-of-time so it's linked in already.
- }
-
- // Create another thread that also calls sMain1.foo().
- // Try to test suspend and deopt another thread.
- new Thread() {
- public void run() {
- testOverride(false, true, false);
- }
- }.start();
-
- // This will create Main2 instance in the middle of testOverride().
- testOverride(true, false, false);
- assertSingleImplementation(Base.class, "foo", false);
- assertSingleImplementation(Main1.class, "foo", false);
- }
-
- private static native void ensureJitCompiled(Class<?> itf, String method_name);
- private static native void assertIsInterpreted();
- private static native void assertIsManaged();
- private static native boolean isInterpreted();
- private static native boolean hasSingleImplementation(Class<?> clazz, String method_name);
-}
-
-// Put createMain2() in another class to avoid class loading due to verifier.
-class Dummy {
- static Main1 createMain2() {
- return new Main2();
- }
-}
diff --git a/test/616-cha-proxy-method-inline/expected.txt b/test/616-cha-proxy-method-inline/expected.txt
deleted file mode 100644
index 6a5618e..0000000
--- a/test/616-cha-proxy-method-inline/expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-JNI_OnLoad called
diff --git a/test/616-cha-proxy-method-inline/info.txt b/test/616-cha-proxy-method-inline/info.txt
deleted file mode 100644
index 0126855..0000000
--- a/test/616-cha-proxy-method-inline/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test for Class Hierarchy Analysis (CHA) on inlining a cross-dex proxy method.
diff --git a/test/616-cha-proxy-method-inline/multidex.jpp b/test/616-cha-proxy-method-inline/multidex.jpp
deleted file mode 100644
index b0d200e..0000000
--- a/test/616-cha-proxy-method-inline/multidex.jpp
+++ /dev/null
@@ -1,3 +0,0 @@
-Main:
- @@com.android.jack.annotations.ForceInMainDex
- class Main
diff --git a/test/616-cha-proxy-method-inline/run b/test/616-cha-proxy-method-inline/run
deleted file mode 100644
index d8b4f0d..0000000
--- a/test/616-cha-proxy-method-inline/run
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 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.
-
-# Run without an app image to prevent the classes to be loaded at startup.
-exec ${RUN} "${@}" --no-app-image
diff --git a/test/616-cha-proxy-method-inline/src/Main.java b/test/616-cha-proxy-method-inline/src/Main.java
deleted file mode 100644
index be7bc82..0000000
--- a/test/616-cha-proxy-method-inline/src/Main.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
-
-class DebugProxy implements java.lang.reflect.InvocationHandler {
- private Object obj;
- static Class<?>[] interfaces = {Foo.class};
-
- public static Object newInstance(Object obj) {
- return java.lang.reflect.Proxy.newProxyInstance(
- Foo.class.getClassLoader(),
- interfaces,
- new DebugProxy(obj));
- }
-
- private DebugProxy(Object obj) {
- this.obj = obj;
- }
-
- public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
- Object result;
- if (obj == null) {
- return null;
- }
- try {
- System.out.println("before invoking method " + m.getName());
- result = m.invoke(obj, args);
- } catch (InvocationTargetException e) {
- throw e.getTargetException();
- } catch (Exception e) {
- throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
- } finally {
- System.out.println("after invoking method " + m.getName());
- }
- return result;
- }
-}
-
-public class Main {
- public static void call(Foo foo) {
- if (foo == null) {
- return;
- }
- foo.bar(null);
- }
-
- public static void main(String[] args) {
- System.loadLibrary(args[0]);
- Foo foo = (Foo)DebugProxy.newInstance(null);
- ensureJitCompiled(Main.class, "call");
- call(foo);
- }
-
- private static native void ensureJitCompiled(Class<?> itf, String method_name);
-}
diff --git a/test/981-dedup-original-dex/expected.txt b/test/981-dedup-original-dex/expected.txt
deleted file mode 100644
index e69de29..0000000
--- a/test/981-dedup-original-dex/expected.txt
+++ /dev/null
diff --git a/test/981-dedup-original-dex/info.txt b/test/981-dedup-original-dex/info.txt
deleted file mode 100644
index 62696e0..0000000
--- a/test/981-dedup-original-dex/info.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Tests basic functions in the jvmti plugin.
-
-This checks that we do not needlessly duplicate the contents of retransformed
-classes original dex files.
diff --git a/test/981-dedup-original-dex/run b/test/981-dedup-original-dex/run
deleted file mode 100755
index e92b873..0000000
--- a/test/981-dedup-original-dex/run
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2017 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.
-
-./default-run "$@" --jvmti
diff --git a/test/981-dedup-original-dex/src/Main.java b/test/981-dedup-original-dex/src/Main.java
deleted file mode 100644
index cd3f007..0000000
--- a/test/981-dedup-original-dex/src/Main.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.lang.reflect.Field;
-import java.util.Base64;
-
-import dalvik.system.ClassExt;
-
-public class Main {
-
- /**
- * base64 encoded class/dex file for
- * class Transform {
- * public void sayHi() {
- * System.out.println("Goodbye");
- * }
- * }
- */
- private static final byte[] DEX_BYTES_1 = Base64.getDecoder().decode(
- "ZGV4CjAzNQCLXSBQ5FiS3f16krSYZFF8xYZtFVp0GRXMAgAAcAAAAHhWNBIAAAAAAAAAACwCAAAO" +
- "AAAAcAAAAAYAAACoAAAAAgAAAMAAAAABAAAA2AAAAAQAAADgAAAAAQAAAAABAACsAQAAIAEAAGIB" +
- "AABqAQAAcwEAAIABAACXAQAAqwEAAL8BAADTAQAA4wEAAOYBAADqAQAA/gEAAAMCAAAMAgAAAgAA" +
- "AAMAAAAEAAAABQAAAAYAAAAIAAAACAAAAAUAAAAAAAAACQAAAAUAAABcAQAABAABAAsAAAAAAAAA" +
- "AAAAAAAAAAANAAAAAQABAAwAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAHAAAAAAAAAB4CAAAA" +
- "AAAAAQABAAEAAAATAgAABAAAAHAQAwAAAA4AAwABAAIAAAAYAgAACQAAAGIAAAAbAQEAAABuIAIA" +
- "EAAOAAAAAQAAAAMABjxpbml0PgAHR29vZGJ5ZQALTFRyYW5zZm9ybTsAFUxqYXZhL2lvL1ByaW50" +
- "U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xh" +
- "bmcvU3lzdGVtOwAOVHJhbnNmb3JtLmphdmEAAVYAAlZMABJlbWl0dGVyOiBqYWNrLTMuMzYAA291" +
- "dAAHcHJpbnRsbgAFc2F5SGkAEQAHDgATAAcOhQAAAAEBAICABKACAQG4Ag0AAAAAAAAAAQAAAAAA" +
- "AAABAAAADgAAAHAAAAACAAAABgAAAKgAAAADAAAAAgAAAMAAAAAEAAAAAQAAANgAAAAFAAAABAAA" +
- "AOAAAAAGAAAAAQAAAAABAAABIAAAAgAAACABAAABEAAAAQAAAFwBAAACIAAADgAAAGIBAAADIAAA" +
- "AgAAABMCAAAAIAAAAQAAAB4CAAAAEAAAAQAAACwCAAA=");
-
- /**
- * base64 encoded class/dex file for
- * class Transform2 {
- * public void sayHi() {
- * System.out.println("Goodbye2");
- * }
- * }
- */
- private static final byte[] DEX_BYTES_2 = Base64.getDecoder().decode(
- "ZGV4CjAzNQAjXDED2iflQ3NXbPtBRVjQVMqoDU9nDz/QAgAAcAAAAHhWNBIAAAAAAAAAADACAAAO" +
- "AAAAcAAAAAYAAACoAAAAAgAAAMAAAAABAAAA2AAAAAQAAADgAAAAAQAAAAABAACwAQAAIAEAAGIB" +
- "AABqAQAAdAEAAIIBAACZAQAArQEAAMEBAADVAQAA5gEAAOkBAADtAQAAAQIAAAYCAAAPAgAAAgAA" +
- "AAMAAAAEAAAABQAAAAYAAAAIAAAACAAAAAUAAAAAAAAACQAAAAUAAABcAQAABAABAAsAAAAAAAAA" +
- "AAAAAAAAAAANAAAAAQABAAwAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAHAAAAAAAAACECAAAA" +
- "AAAAAQABAAEAAAAWAgAABAAAAHAQAwAAAA4AAwABAAIAAAAbAgAACQAAAGIAAAAbAQEAAABuIAIA" +
- "EAAOAAAAAQAAAAMABjxpbml0PgAIR29vZGJ5ZTIADExUcmFuc2Zvcm0yOwAVTGphdmEvaW8vUHJp" +
- "bnRTdHJlYW07ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEv" +
- "bGFuZy9TeXN0ZW07AA9UcmFuc2Zvcm0yLmphdmEAAVYAAlZMABJlbWl0dGVyOiBqYWNrLTQuMzAA" +
- "A291dAAHcHJpbnRsbgAFc2F5SGkAAQAHDgADAAcOhwAAAAEBAICABKACAQG4AgANAAAAAAAAAAEA" +
- "AAAAAAAAAQAAAA4AAABwAAAAAgAAAAYAAACoAAAAAwAAAAIAAADAAAAABAAAAAEAAADYAAAABQAA" +
- "AAQAAADgAAAABgAAAAEAAAAAAQAAASAAAAIAAAAgAQAAARAAAAEAAABcAQAAAiAAAA4AAABiAQAA" +
- "AyAAAAIAAAAWAgAAACAAAAEAAAAhAgAAABAAAAEAAAAwAgAA");
-
- public static void main(String[] args) {
- try {
- doTest();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private static void assertSame(Object a, Object b) throws Exception {
- if (a != b) {
- throw new AssertionError("'" + (a != null ? a.toString() : "null") + "' is not the same as " +
- "'" + (b != null ? b.toString() : "null") + "'");
- }
- }
-
- private static Object getObjectField(Object o, String name) throws Exception {
- return getObjectField(o, o.getClass(), name);
- }
-
- private static Object getObjectField(Object o, Class<?> type, String name) throws Exception {
- Field f = type.getDeclaredField(name);
- f.setAccessible(true);
- return f.get(o);
- }
-
- private static Object getOriginalDexFile(Class<?> k) throws Exception {
- ClassExt ext_data_object = (ClassExt) getObjectField(k, "extData");
- if (ext_data_object == null) {
- return null;
- }
-
- return getObjectField(ext_data_object, "originalDexFile");
- }
-
- public static void doTest() throws Exception {
- // Make sure both of these are loaded prior to transformations being added so they have the same
- // original dex files.
- Transform t1 = new Transform();
- Transform2 t2 = new Transform2();
-
- assertSame(null, getOriginalDexFile(t1.getClass()));
- assertSame(null, getOriginalDexFile(t2.getClass()));
- assertSame(null, getOriginalDexFile(Main.class));
-
- addCommonTransformationResult("Transform", new byte[0], DEX_BYTES_1);
- addCommonTransformationResult("Transform2", new byte[0], DEX_BYTES_2);
- enableCommonRetransformation(true);
- doCommonClassRetransformation(Transform.class, Transform2.class);
-
- assertSame(getOriginalDexFile(t1.getClass()), getOriginalDexFile(t2.getClass()));
- assertSame(null, getOriginalDexFile(Main.class));
- // Make sure that the original dex file is a DexCache object.
- assertSame(getOriginalDexFile(t1.getClass()).getClass(), Class.forName("java.lang.DexCache"));
-
- // Check that we end up with a byte[] if we do a direct RedefineClasses
- enableCommonRetransformation(false);
- doCommonClassRedefinition(Transform.class, new byte[0], DEX_BYTES_1);
- assertSame((new byte[0]).getClass(), getOriginalDexFile(t1.getClass()).getClass());
- }
-
- // Transforms the class
- private static native void doCommonClassRetransformation(Class<?>... target);
- private static native void doCommonClassRedefinition(Class<?> target,
- byte[] class_file,
- byte[] dex_file);
- private static native void enableCommonRetransformation(boolean enable);
- private static native void addCommonTransformationResult(String target_name,
- byte[] class_bytes,
- byte[] dex_bytes);
-}
diff --git a/test/981-dedup-original-dex/src/Transform.java b/test/981-dedup-original-dex/src/Transform.java
deleted file mode 100644
index 3c97907..0000000
--- a/test/981-dedup-original-dex/src/Transform.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-class Transform {
- public void sayHi() {
- System.out.println("hello");
- }
-}
diff --git a/test/981-dedup-original-dex/src/Transform2.java b/test/981-dedup-original-dex/src/Transform2.java
deleted file mode 100644
index eb22842..0000000
--- a/test/981-dedup-original-dex/src/Transform2.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-class Transform2 {
- public void sayHi() {
- System.out.println("hello2");
- }
-}
diff --git a/test/run-test b/test/run-test
index 1715423..a6903ff 100755
--- a/test/run-test
+++ b/test/run-test
@@ -772,7 +772,7 @@
# Set a hard limit to encourage ART developers to increase the ulimit here if
# needed to support a test case rather than resetting the limit in the run
# script for the particular test in question.
-if ! ulimit -f -H 128000; then
+if ! ulimit -f 128000; then
err_echo "ulimit file size setting failed"
fi
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 9b99970..3203f7a 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -268,6 +268,16 @@
global semaphore
semaphore = threading.Semaphore(n_thread)
+ if not sys.stdout.isatty():
+ global COLOR_ERROR
+ global COLOR_PASS
+ global COLOR_SKIP
+ global COLOR_NORMAL
+ COLOR_ERROR = ''
+ COLOR_PASS = ''
+ COLOR_SKIP = ''
+ COLOR_NORMAL = ''
+
def run_tests(tests):
"""Creates thread workers to run the tests.
@@ -912,6 +922,7 @@
if options['gdb_arg']:
gdb_arg = options['gdb_arg']
timeout = options['timeout']
+
return test
def main():
diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc
index 8cb14bd..fddae3a 100644
--- a/test/ti-agent/common_load.cc
+++ b/test/ti-agent/common_load.cc
@@ -121,7 +121,6 @@
{ "943-private-recursive-jit", common_redefine::OnLoad, nullptr },
{ "944-transform-classloaders", common_redefine::OnLoad, nullptr },
{ "945-obsolete-native", common_redefine::OnLoad, nullptr },
- { "981-dedup-original-dex", common_retransform::OnLoad, nullptr },
};
static AgentLib* FindAgent(char* name) {
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index e0aae46..55b2c59 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -141,13 +141,6 @@
names: ["org.apache.harmony.tests.java.lang.ClassTest#test_forNameLjava_lang_String"]
},
{
- description: "TimeZoneTest.testAllDisplayNames times out, needs investigation",
- result: EXEC_TIMEOUT,
- modes: [device],
- names: ["libcore.java.util.TimeZoneTest#testAllDisplayNames"],
- bug: 22786792
-},
-{
description: "Lack of IPv6 on some buildbot slaves",
result: EXEC_FAILED,
names: ["libcore.io.OsTest#test_byteBufferPositions_sendto_recvfrom_af_inet6",