summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.common_build.mk13
-rw-r--r--compiler/driver/compiler_options.cc2
-rw-r--r--compiler/driver/compiler_options.h1
-rw-r--r--compiler/jit/jit_compiler.cc2
-rw-r--r--profman/profman.cc6
-rw-r--r--runtime/common_runtime_test.cc20
-rw-r--r--runtime/compiler_filter.h2
-rw-r--r--runtime/dex_file_verifier.cc21
-rw-r--r--runtime/dex_file_verifier_test.cc55
-rw-r--r--runtime/globals.h22
-rw-r--r--runtime/interpreter/interpreter.cc20
-rw-r--r--runtime/java_vm_ext.cc31
-rw-r--r--runtime/mem_map.cc5
-rw-r--r--runtime/mem_map.h4
-rw-r--r--runtime/oat_file_assistant.cc34
-rw-r--r--runtime/oat_file_assistant.h12
-rw-r--r--runtime/oat_file_assistant_test.cc58
-rw-r--r--runtime/oat_file_manager.cc9
-rw-r--r--runtime/oat_file_manager.h8
-rw-r--r--runtime/parsed_options.cc3
-rw-r--r--runtime/runtime.cc11
-rw-r--r--runtime/runtime_options.def1
-rw-r--r--test/004-JniTest/jni_test.cc334
-rw-r--r--test/004-ReferenceMap/stack_walk_refmap_jni.cc1
-rw-r--r--test/004-StackWalk/stack_walk_jni.cc1
-rw-r--r--test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc5
-rw-r--r--test/566-polymorphic-inlining/src/Main.java1
-rw-r--r--test/570-checker-osr/osr.cc2
-rw-r--r--test/595-profile-saving/profile-saving.cc1
-rw-r--r--test/595-profile-saving/run5
-rw-r--r--test/596-app-images/app_images.cc1
-rw-r--r--test/597-deopt-new-string/deopt.cc59
-rw-r--r--test/597-deopt-new-string/expected.txt2
-rw-r--r--test/597-deopt-new-string/info.txt1
-rw-r--r--test/597-deopt-new-string/run18
-rw-r--r--test/597-deopt-new-string/src/Main.java75
-rw-r--r--test/Android.libarttest.mk10
-rwxr-xr-xtest/etc/run-test-jar13
-rwxr-xr-xtest/run-test8
39 files changed, 560 insertions, 317 deletions
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk
index dde3cdb1d5..0235a308f8 100644
--- a/build/Android.common_build.mk
+++ b/build/Android.common_build.mk
@@ -363,11 +363,20 @@ ART_HOST_ASFLAGS += $(art_asflags)
ifndef LIBART_IMG_TARGET_BASE_ADDRESS
$(error LIBART_IMG_TARGET_BASE_ADDRESS unset)
endif
+
+ART_TARGET_CFLAGS += $(art_cflags) -DART_TARGET \
+ -DART_BASE_ADDRESS=$(LIBART_IMG_TARGET_BASE_ADDRESS) \
+
+ifeq ($(ART_TARGET_LINUX),true)
+# Setting ART_TARGET_LINUX to true compiles art/ assuming that the target device
+# will be running linux rather than android.
+ART_TARGET_CFLAGS += -DART_TARGET_LINUX
+else
# The ART_TARGET_ANDROID macro is passed to target builds, which check
# against it instead of against __ANDROID__ (which is provided by target
# toolchains).
-ART_TARGET_CFLAGS += $(art_cflags) -DART_TARGET -DART_TARGET_ANDROID \
- -DART_BASE_ADDRESS=$(LIBART_IMG_TARGET_BASE_ADDRESS) \
+ART_TARGET_CFLAGS += -DART_TARGET_ANDROID
+endif
ART_TARGET_CFLAGS += $(art_target_cflags)
ART_TARGET_ASFLAGS += $(art_asflags)
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index 1bd4c3ad80..f20dba34a6 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -21,7 +21,7 @@
namespace art {
CompilerOptions::CompilerOptions()
- : compiler_filter_(kDefaultCompilerFilter),
+ : compiler_filter_(CompilerFilter::kDefaultCompilerFilter),
huge_method_threshold_(kDefaultHugeMethodThreshold),
large_method_threshold_(kDefaultLargeMethodThreshold),
small_method_threshold_(kDefaultSmallMethodThreshold),
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index c67ab6ef14..6bbd3c5a19 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -31,7 +31,6 @@ namespace art {
class CompilerOptions FINAL {
public:
// Guide heuristics to determine whether to compile method if profile data not available.
- static const CompilerFilter::Filter kDefaultCompilerFilter = CompilerFilter::kSpeed;
static const size_t kDefaultHugeMethodThreshold = 10000;
static const size_t kDefaultLargeMethodThreshold = 600;
static const size_t kDefaultSmallMethodThreshold = 60;
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index c2d7ff7795..178533849b 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -88,7 +88,7 @@ NO_RETURN static void Usage(const char* fmt, ...) {
JitCompiler::JitCompiler() {
compiler_options_.reset(new CompilerOptions(
- CompilerOptions::kDefaultCompilerFilter,
+ CompilerFilter::kDefaultCompilerFilter,
CompilerOptions::kDefaultHugeMethodThreshold,
CompilerOptions::kDefaultLargeMethodThreshold,
CompilerOptions::kDefaultSmallMethodThreshold,
diff --git a/profman/profman.cc b/profman/profman.cc
index 3e632bce8b..b3454fa2e7 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -216,7 +216,11 @@ class ProfMan FINAL {
}
void LogCompletionTime() {
- LOG(INFO) << "profman took " << PrettyDuration(NanoTime() - start_ns_);
+ static constexpr uint64_t kLogThresholdTime = MsToNs(100); // 100ms
+ uint64_t time_taken = NanoTime() - start_ns_;
+ if (time_taken > kLogThresholdTime) {
+ LOG(WARNING) << "profman took " << PrettyDuration(NanoTime() - start_ns_);
+ }
}
std::vector<std::string> profile_files_;
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index f58af5a8da..5bdb36cafc 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -418,26 +418,6 @@ void CommonRuntimeTestImpl::TearDown() {
(*icu_cleanup_fn)();
Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test
-
- // Manually closing the JNI libraries.
- // Runtime does not support repeatedly doing JNI->CreateVM, thus we need to manually clean up the
- // dynamic linking loader so that gtests would not fail.
- // Bug: 25785594
- if (runtime_->IsStarted()) {
- {
- // We retrieve the handle by calling dlopen on the library. To close it, we need to call
- // dlclose twice, the first time to undo our dlopen and the second time to actually unload it.
- // See man dlopen.
- void* handle = dlopen("libjavacore.so", RTLD_LAZY);
- dlclose(handle);
- CHECK_EQ(0, dlclose(handle));
- }
- {
- void* handle = dlopen("libopenjdkd.so", RTLD_LAZY);
- dlclose(handle);
- CHECK_EQ(0, dlclose(handle));
- }
- }
}
static std::string GetDexFileName(const std::string& jar_prefix, bool host) {
diff --git a/runtime/compiler_filter.h b/runtime/compiler_filter.h
index 6289d8a22c..e8d74dd9e8 100644
--- a/runtime/compiler_filter.h
+++ b/runtime/compiler_filter.h
@@ -44,6 +44,8 @@ class CompilerFilter FINAL {
kEverything, // Compile everything capable of being compiled.
};
+ static const Filter kDefaultCompilerFilter = kSpeed;
+
// Returns true if an oat file with this compiler filter contains
// compiled executable code.
static bool IsCompilationEnabled(Filter filter);
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index 3df4e98c84..21ee4bd528 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -2358,7 +2358,8 @@ static bool CheckAtMostOneOfPublicProtectedPrivate(uint32_t flags) {
static std::string GetStringOrError(const uint8_t* const begin,
const DexFile::Header* const header,
uint32_t string_idx) {
- if (header->string_ids_size_ < string_idx) {
+ // The `string_idx` is not guaranteed to be valid yet.
+ if (header->string_ids_size_ <= string_idx) {
return "(error)";
}
@@ -2375,9 +2376,11 @@ static std::string GetStringOrError(const uint8_t* const begin,
static std::string GetClassOrError(const uint8_t* const begin,
const DexFile::Header* const header,
uint32_t class_idx) {
- if (header->type_ids_size_ < class_idx) {
- return "(error)";
- }
+ // The `class_idx` is either `FieldId::class_idx_` or `MethodId::class_idx_` and
+ // it has already been checked in `DexFileVerifier::CheckClassDataItemField()`
+ // or `DexFileVerifier::CheckClassDataItemMethod()`, respectively, to match
+ // a valid defining class.
+ CHECK_LT(class_idx, header->type_ids_size_);
const DexFile::TypeId* type_id =
reinterpret_cast<const DexFile::TypeId*>(begin + header->type_ids_off_) + class_idx;
@@ -2390,9 +2393,8 @@ static std::string GetClassOrError(const uint8_t* const begin,
static std::string GetFieldDescriptionOrError(const uint8_t* const begin,
const DexFile::Header* const header,
uint32_t idx) {
- if (header->field_ids_size_ < idx) {
- return "(error)";
- }
+ // The `idx` has already been checked in `DexFileVerifier::CheckClassDataItemField()`.
+ CHECK_LT(idx, header->field_ids_size_);
const DexFile::FieldId* field_id =
reinterpret_cast<const DexFile::FieldId*>(begin + header->field_ids_off_) + idx;
@@ -2408,9 +2410,8 @@ static std::string GetFieldDescriptionOrError(const uint8_t* const begin,
static std::string GetMethodDescriptionOrError(const uint8_t* const begin,
const DexFile::Header* const header,
uint32_t idx) {
- if (header->method_ids_size_ < idx) {
- return "(error)";
- }
+ // The `idx` has already been checked in `DexFileVerifier::CheckClassDataItemMethod()`.
+ CHECK_LT(idx, header->method_ids_size_);
const DexFile::MethodId* method_id =
reinterpret_cast<const DexFile::MethodId*>(begin + header->method_ids_off_) + idx;
diff --git a/runtime/dex_file_verifier_test.cc b/runtime/dex_file_verifier_test.cc
index 344d186ad4..84f48daccb 100644
--- a/runtime/dex_file_verifier_test.cc
+++ b/runtime/dex_file_verifier_test.cc
@@ -57,7 +57,7 @@ static const uint8_t kBase64Map[256] = {
255, 255, 255, 255
};
-static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
+static inline std::unique_ptr<uint8_t[]> DecodeBase64(const char* src, size_t* dst_size) {
std::vector<uint8_t> tmp;
uint32_t t = 0, y = 0;
int g = 3;
@@ -100,7 +100,7 @@ static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
*dst_size = 0;
}
std::copy(tmp.begin(), tmp.end(), dst.get());
- return dst.release();
+ return dst;
}
static void FixUpChecksum(uint8_t* dex_file) {
@@ -113,25 +113,18 @@ static void FixUpChecksum(uint8_t* dex_file) {
header->checksum_ = adler_checksum;
}
-// Custom deleter. Necessary to clean up the memory we use (to be able to mutate).
-struct DexFileDeleter {
- void operator()(DexFile* in) {
- if (in != nullptr) {
- delete[] in->Begin();
- delete in;
- }
- }
-};
-
-using DexFileUniquePtr = std::unique_ptr<DexFile, DexFileDeleter>;
-
class DexFileVerifierTest : public CommonRuntimeTest {
protected:
void VerifyModification(const char* dex_file_base64_content,
const char* location,
std::function<void(DexFile*)> f,
const char* expected_error) {
- DexFileUniquePtr dex_file(WrapAsDexFile(dex_file_base64_content));
+ size_t length;
+ std::unique_ptr<uint8_t[]> dex_bytes = DecodeBase64(dex_file_base64_content, &length);
+ CHECK(dex_bytes != nullptr);
+ // Note: `dex_file` will be destroyed before `dex_bytes`.
+ std::unique_ptr<DexFile> dex_file(
+ new DexFile(dex_bytes.get(), length, "tmp", 0, nullptr, nullptr));
f(dex_file.get());
FixUpChecksum(const_cast<uint8_t*>(dex_file->Begin()));
@@ -150,15 +143,6 @@ class DexFileVerifierTest : public CommonRuntimeTest {
}
}
}
-
- private:
- static DexFile* WrapAsDexFile(const char* dex_file_content_in_base_64) {
- // Decode base64.
- size_t length;
- uint8_t* dex_bytes = DecodeBase64(dex_file_content_in_base_64, &length);
- CHECK(dex_bytes != nullptr);
- return new DexFile(dex_bytes, length, "tmp", 0, nullptr, nullptr);
- }
};
static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
@@ -290,7 +274,9 @@ static const char kMethodFlagsTestDex[] =
// Find the method data for the first method with the given name (from class 0). Note: the pointer
// is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index
// delta.
-static const uint8_t* FindMethodData(const DexFile* dex_file, const char* name) {
+static const uint8_t* FindMethodData(const DexFile* dex_file,
+ const char* name,
+ /*out*/ uint32_t* method_idx = nullptr) {
const DexFile::ClassDef& class_def = dex_file->GetClassDef(0);
const uint8_t* class_data = dex_file->GetClassData(class_def);
@@ -316,6 +302,9 @@ static const uint8_t* FindMethodData(const DexFile* dex_file, const char* name)
const DexFile::StringId& string_id = dex_file->GetStringId(name_index);
const char* str = dex_file->GetStringData(string_id);
if (strcmp(name, str) == 0) {
+ if (method_idx != nullptr) {
+ *method_idx = method_index;
+ }
DecodeUnsignedLeb128(&trailing);
return trailing;
}
@@ -683,6 +672,22 @@ TEST_F(DexFileVerifierTest, MethodAccessFlagsIgnoredOK) {
}
}
+TEST_F(DexFileVerifierTest, B28552165) {
+ // Regression test for bad error string retrieval in different situations.
+ // Using invalid access flags to trigger the error.
+ VerifyModification(
+ kMethodFlagsTestDex,
+ "b28552165",
+ [](DexFile* dex_file) {
+ OrMaskToMethodFlags(dex_file, "foo", kAccPublic | kAccProtected);
+ uint32_t method_idx;
+ FindMethodData(dex_file, "foo", &method_idx);
+ auto* method_id = const_cast<DexFile::MethodId*>(&dex_file->GetMethodId(method_idx));
+ method_id->name_idx_ = dex_file->NumStringIds();
+ },
+ "Method may have only one of public/protected/private, LMethodFlags;.(error)");
+}
+
// Set of dex files for interface method tests. As it's not as easy to mutate method names, it's
// just easier to break up bad cases.
diff --git a/runtime/globals.h b/runtime/globals.h
index e7ea6f3788..477cbdf5d4 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -51,11 +51,31 @@ static constexpr bool kIsDebugBuild = false;
static constexpr bool kIsDebugBuild = true;
#endif
-// Whether or not this is a target (vs host) build. Useful in conditionals where ART_TARGET isn't.
+// ART_TARGET - Defined for target builds of ART.
+// ART_TARGET_LINUX - Defined for target Linux builds of ART.
+// ART_TARGET_ANDROID - Defined for target Android builds of ART.
+// Note: Either ART_TARGET_LINUX or ART_TARGET_ANDROID need to be set when ART_TARGET is set.
+// Note: When ART_TARGET_LINUX is defined mem_map.h will not be using Ashmem for memory mappings
+// (usually only available on Android kernels).
#if defined(ART_TARGET)
+// Useful in conditionals where ART_TARGET isn't.
static constexpr bool kIsTargetBuild = true;
+#if defined(ART_TARGET_LINUX)
+static constexpr bool kIsTargetLinux = true;
+#elif defined(ART_TARGET_ANDROID)
+static constexpr bool kIsTargetLinux = false;
+#else
+#error "Either ART_TARGET_LINUX or ART_TARGET_ANDROID needs to be defined for target builds."
+#endif
#else
static constexpr bool kIsTargetBuild = false;
+#if defined(ART_TARGET_LINUX)
+#error "ART_TARGET_LINUX defined for host build."
+#elif defined(ART_TARGET_ANDROID)
+#error "ART_TARGET_ANDROID defined for host build."
+#else
+static constexpr bool kIsTargetLinux = false;
+#endif
#endif
// Garbage collector constants.
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 81a396a925..6c630cc48f 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -515,8 +515,24 @@ void EnterInterpreterFromDeoptimize(Thread* self,
// instruction, as it already executed.
// TODO: should be tested more once b/17586779 is fixed.
const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
- DCHECK(instr->IsInvoke());
- new_dex_pc = dex_pc + instr->SizeInCodeUnits();
+ if (instr->IsInvoke()) {
+ new_dex_pc = dex_pc + instr->SizeInCodeUnits();
+ } else if (instr->Opcode() == Instruction::NEW_INSTANCE) {
+ // It's possible to deoptimize at a NEW_INSTANCE dex instruciton that's for a
+ // java string, which is turned into a call into StringFactory.newEmptyString();
+ if (kIsDebugBuild) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ mirror::Class* klass = class_linker->ResolveType(
+ instr->VRegB_21c(), shadow_frame->GetMethod());
+ DCHECK(klass->IsStringClass());
+ }
+ // Skip the dex instruction since we essentially come back from an invocation.
+ new_dex_pc = dex_pc + instr->SizeInCodeUnits();
+ } else {
+ DCHECK(false) << "Unexpected instruction opcode " << instr->Opcode()
+ << " at dex_pc " << dex_pc
+ << " of method: " << PrettyMethod(shadow_frame->GetMethod(), false);
+ }
} else {
// Nothing to do, the dex_pc is the one at which the code requested
// the deoptimization.
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 79c320309c..3de718b397 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -74,6 +74,10 @@ class SharedLibrary {
if (self != nullptr) {
self->GetJniEnv()->DeleteWeakGlobalRef(class_loader_);
}
+
+ if (!needs_native_bridge_) {
+ android::CloseNativeLibrary(handle_);
+ }
}
jweak GetClassLoader() const {
@@ -271,8 +275,7 @@ class Libraries {
REQUIRES(!Locks::jni_libraries_lock_)
SHARED_REQUIRES(Locks::mutator_lock_) {
ScopedObjectAccessUnchecked soa(Thread::Current());
- typedef void (*JNI_OnUnloadFn)(JavaVM*, void*);
- std::vector<JNI_OnUnloadFn> unload_functions;
+ std::vector<SharedLibrary*> unload_libraries;
{
MutexLock mu(soa.Self(), *Locks::jni_libraries_lock_);
for (auto it = libraries_.begin(); it != libraries_.end(); ) {
@@ -283,15 +286,7 @@ class Libraries {
// the native libraries of the boot class loader.
if (class_loader != nullptr &&
soa.Self()->IsJWeakCleared(class_loader)) {
- void* const sym = library->FindSymbol("JNI_OnUnload", nullptr);
- if (sym == nullptr) {
- VLOG(jni) << "[No JNI_OnUnload found in \"" << library->GetPath() << "\"]";
- } else {
- VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]";
- JNI_OnUnloadFn jni_on_unload = reinterpret_cast<JNI_OnUnloadFn>(sym);
- unload_functions.push_back(jni_on_unload);
- }
- delete library;
+ unload_libraries.push_back(library);
it = libraries_.erase(it);
} else {
++it;
@@ -299,9 +294,17 @@ class Libraries {
}
}
// Do this without holding the jni libraries lock to prevent possible deadlocks.
- for (JNI_OnUnloadFn fn : unload_functions) {
- VLOG(jni) << "Calling JNI_OnUnload";
- (*fn)(soa.Vm(), nullptr);
+ typedef void (*JNI_OnUnloadFn)(JavaVM*, void*);
+ for (auto library : unload_libraries) {
+ void* const sym = library->FindSymbol("JNI_OnUnload", nullptr);
+ if (sym == nullptr) {
+ VLOG(jni) << "[No JNI_OnUnload found in \"" << library->GetPath() << "\"]";
+ } else {
+ VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]: Calling...";
+ JNI_OnUnloadFn jni_on_unload = reinterpret_cast<JNI_OnUnloadFn>(sym);
+ jni_on_unload(soa.Vm(), nullptr);
+ }
+ delete library;
}
}
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index 5d89c21803..771f8ed290 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -302,8 +302,9 @@ MemMap* MemMap::MapAnonymous(const char* name,
if (use_ashmem) {
if (!kIsTargetBuild) {
- // When not on Android ashmem is faked using files in /tmp. Ensure that such files won't
- // fail due to ulimit restrictions. If they will then use a regular mmap.
+ // When not on Android (either host or assuming a linux target) ashmem is faked using
+ // files in /tmp. Ensure that such files won't fail due to ulimit restrictions. If they
+ // will then use a regular mmap.
struct rlimit rlimit_fsize;
CHECK_EQ(getrlimit(RLIMIT_FSIZE, &rlimit_fsize), 0);
use_ashmem = (rlimit_fsize.rlim_cur == RLIM_INFINITY) ||
diff --git a/runtime/mem_map.h b/runtime/mem_map.h
index 3eaf576845..597f0d46e1 100644
--- a/runtime/mem_map.h
+++ b/runtime/mem_map.h
@@ -68,7 +68,7 @@ class MemMap {
bool low_4gb,
bool reuse,
std::string* error_msg,
- bool use_ashmem = true);
+ bool use_ashmem = !kIsTargetLinux);
// Create placeholder for a region allocated by direct call to mmap.
// This is useful when we do not have control over the code calling mmap,
@@ -172,7 +172,7 @@ class MemMap {
const char* tail_name,
int tail_prot,
std::string* error_msg,
- bool use_ashmem = true);
+ bool use_ashmem = !kIsTargetLinux);
static bool CheckNoGaps(MemMap* begin_map, MemMap* end_map)
REQUIRES(!Locks::mem_maps_lock_);
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 3f95772b4f..a508e87c87 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -179,11 +179,38 @@ OatFileAssistant::DexOptNeeded OatFileAssistant::GetDexOptNeeded(CompilerFilter:
return HasOriginalDexFiles() ? kDex2OatNeeded : kNoDexOptNeeded;
}
+// Figure out the currently specified compile filter option in the runtime.
+// Returns true on success, false if the compiler filter is invalid, in which
+// case error_msg describes the problem.
+static bool GetRuntimeCompilerFilterOption(CompilerFilter::Filter* filter,
+ std::string* error_msg) {
+ CHECK(filter != nullptr);
+ CHECK(error_msg != nullptr);
+
+ *filter = CompilerFilter::kDefaultCompilerFilter;
+ for (StringPiece option : Runtime::Current()->GetCompilerOptions()) {
+ if (option.starts_with("--compiler-filter=")) {
+ const char* compiler_filter_string = option.substr(strlen("--compiler-filter=")).data();
+ if (!CompilerFilter::ParseCompilerFilter(compiler_filter_string, filter)) {
+ *error_msg = std::string("Unknown --compiler-filter value: ")
+ + std::string(compiler_filter_string);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
OatFileAssistant::ResultOfAttemptToUpdate
-OatFileAssistant::MakeUpToDate(CompilerFilter::Filter target, std::string* error_msg) {
+OatFileAssistant::MakeUpToDate(std::string* error_msg) {
+ CompilerFilter::Filter target;
+ if (!GetRuntimeCompilerFilterOption(&target, error_msg)) {
+ return kUpdateNotAttempted;
+ }
+
switch (GetDexOptNeeded(target)) {
case kNoDexOptNeeded: return kUpdateSucceeded;
- case kDex2OatNeeded: return GenerateOatFile(target, error_msg);
+ case kDex2OatNeeded: return GenerateOatFile(error_msg);
case kPatchOatNeeded: return RelocateOatFile(OdexFileName(), error_msg);
case kSelfPatchOatNeeded: return RelocateOatFile(OatFileName(), error_msg);
}
@@ -634,7 +661,7 @@ OatFileAssistant::RelocateOatFile(const std::string* input_file, std::string* er
}
OatFileAssistant::ResultOfAttemptToUpdate
-OatFileAssistant::GenerateOatFile(CompilerFilter::Filter target, std::string* error_msg) {
+OatFileAssistant::GenerateOatFile(std::string* error_msg) {
CHECK(error_msg != nullptr);
Runtime* runtime = Runtime::Current();
@@ -678,7 +705,6 @@ OatFileAssistant::GenerateOatFile(CompilerFilter::Filter target, std::string* er
args.push_back("--dex-file=" + dex_location_);
args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
args.push_back("--oat-location=" + oat_file_name);
- args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(target));
if (!Dex2Oat(args, error_msg)) {
// Manually delete the file. This ensures there is no garbage left over if
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index d3228deac7..85f4a47868 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -159,15 +159,12 @@ class OatFileAssistant {
};
// Attempts to generate or relocate the oat file as needed to make it up to
- // date with in a way that is at least as good as an oat file generated with
- // the given compiler filter.
- // Returns the result of attempting to update the code.
+ // date based on the current runtime and compiler options.
//
// If the result is not kUpdateSucceeded, the value of error_msg will be set
// to a string describing why there was a failure or the update was not
// attempted. error_msg must not be null.
- ResultOfAttemptToUpdate MakeUpToDate(CompilerFilter::Filter target_compiler_filter,
- std::string* error_msg);
+ ResultOfAttemptToUpdate MakeUpToDate(std::string* error_msg);
// Returns an oat file that can be used for loading dex files.
// Returns null if no suitable oat file was found.
@@ -250,14 +247,15 @@ class OatFileAssistant {
// attempted. error_msg must not be null.
ResultOfAttemptToUpdate RelocateOatFile(const std::string* input_file, std::string* error_msg);
- // Generate the oat file from the dex file using the given compiler filter.
+ // Generate the oat file from the dex file using the current runtime
+ // compiler options.
// This does not check the current status before attempting to generate the
// oat file.
//
// If the result is not kUpdateSucceeded, the value of error_msg will be set
// to a string describing why there was a failure or the update was not
// attempted. error_msg must not be null.
- ResultOfAttemptToUpdate GenerateOatFile(CompilerFilter::Filter filter, std::string* error_msg);
+ ResultOfAttemptToUpdate GenerateOatFile(std::string* error_msg);
// Executes dex2oat using the current runtime configuration overridden with
// the given arguments. This does not check to see if dex2oat is enabled in
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index f50d1cb748..764b969eaa 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -453,8 +453,7 @@ TEST_F(OatFileAssistantTest, NoDexNoOat) {
// Trying to make the oat file up to date should not fail or crash.
std::string error_msg;
- EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
- oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg));
+ EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, oat_file_assistant.MakeUpToDate(&error_msg));
// Trying to get the best oat file should fail, but not crash.
std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
@@ -705,8 +704,9 @@ TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
// Make the oat file up to date.
std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
- oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+ oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
@@ -768,8 +768,9 @@ TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
// Make the oat file up to date.
std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
- oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+ oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
@@ -825,8 +826,9 @@ TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
// Make the oat file up to date. This should have no effect.
std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
- oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+ oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
@@ -876,8 +878,9 @@ TEST_F(OatFileAssistantTest, SelfRelocation) {
// Make the oat file up to date.
std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
- oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+ oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
@@ -920,8 +923,9 @@ TEST_F(OatFileAssistantTest, NoSelfRelocation) {
// Make the oat file up to date.
std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
- oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+ oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
@@ -1100,8 +1104,9 @@ TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) {
OatFileAssistant oat_file_assistant(
dex_location.c_str(), oat_location.c_str(), kRuntimeISA, false, true);
std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
- oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg;
+ oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
ASSERT_TRUE(oat_file.get() != nullptr);
@@ -1131,8 +1136,9 @@ TEST_F(OatFileAssistantTest, LoadDexUnwriteableAlternateOat) {
OatFileAssistant oat_file_assistant(
dex_location.c_str(), oat_location.c_str(), kRuntimeISA, false, true);
std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
ASSERT_EQ(OatFileAssistant::kUpdateNotAttempted,
- oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg));
+ oat_file_assistant.MakeUpToDate(&error_msg));
std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
ASSERT_TRUE(oat_file.get() == nullptr);
@@ -1147,8 +1153,9 @@ TEST_F(OatFileAssistantTest, GenNoDex) {
OatFileAssistant oat_file_assistant(
dex_location.c_str(), oat_location.c_str(), kRuntimeISA, false, true);
std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
- oat_file_assistant.GenerateOatFile(CompilerFilter::kSpeed, &error_msg));
+ oat_file_assistant.GenerateOatFile(&error_msg));
}
// Turn an absolute path into a path relative to the current working
@@ -1227,8 +1234,9 @@ TEST_F(OatFileAssistantTest, ShortDexLocation) {
// Trying to make it up to date should have no effect.
std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
- oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg));
+ oat_file_assistant.MakeUpToDate(&error_msg));
EXPECT_TRUE(error_msg.empty());
}
@@ -1368,6 +1376,34 @@ TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
EXPECT_EQ(2u, dex_files.size());
}
+TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) {
+ std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar";
+ Copy(GetDexSrc1(), dex_location);
+
+ OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false);
+
+ std::string error_msg;
+ Runtime::Current()->AddCompilerOption("--compiler-filter=interpret-only");
+ EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
+ oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
+ EXPECT_EQ(OatFileAssistant::kDex2OatNeeded,
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+
+ Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
+ EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
+ oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
+ EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
+ oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
+
+ Runtime::Current()->AddCompilerOption("--compiler-filter=bogus");
+ EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
+ oat_file_assistant.MakeUpToDate(&error_msg));
+}
+
TEST(OatFileAssistantUtilsTest, DexFilenameToOdexFilename) {
std::string error_msg;
std::string odex_file;
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 9ab0072ea9..bc01da4fc4 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -44,8 +44,6 @@ static constexpr bool kDuplicateClassesCheck = kIsDebugBuild;
// If true, then we attempt to load the application image if it exists.
static constexpr bool kEnableAppImage = true;
-CompilerFilter::Filter OatFileManager::filter_ = CompilerFilter::Filter::kSpeed;
-
const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file) {
WriterMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
DCHECK(oat_file != nullptr);
@@ -341,9 +339,10 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
const OatFile* source_oat_file = nullptr;
- // Update the oat file on disk if we can. This may fail, but that's okay.
- // Best effort is all that matters here.
- switch (oat_file_assistant.MakeUpToDate(filter_, /*out*/ &error_msg)) {
+ // Update the oat file on disk if we can, based on the --compiler-filter
+ // option derived from the current runtime options.
+ // This may fail, but that's okay. Best effort is all that matters here.
+ switch (oat_file_assistant.MakeUpToDate(/*out*/ &error_msg)) {
case OatFileAssistant::kUpdateFailed:
LOG(WARNING) << error_msg;
break;
diff --git a/runtime/oat_file_manager.h b/runtime/oat_file_manager.h
index f98102e844..7017dfc6ec 100644
--- a/runtime/oat_file_manager.h
+++ b/runtime/oat_file_manager.h
@@ -25,7 +25,6 @@
#include "base/macros.h"
#include "base/mutex.h"
-#include "compiler_filter.h"
#include "jni.h"
namespace art {
@@ -116,10 +115,6 @@ class OatFileManager {
void DumpForSigQuit(std::ostream& os);
- static void SetCompilerFilter(CompilerFilter::Filter filter) {
- filter_ = filter;
- }
-
private:
// Check for duplicate class definitions of the given oat file against all open oat files.
// Return true if there are any class definition collisions in the oat_file.
@@ -133,9 +128,6 @@ class OatFileManager {
std::unordered_map<std::string, size_t> oat_file_count_ GUARDED_BY(Locks::oat_file_count_lock_);
bool have_non_pic_oat_file_;
- // The compiler filter used for oat files loaded by the oat file manager.
- static CompilerFilter::Filter filter_;
-
DISALLOW_COPY_AND_ASSIGN(OatFileManager);
};
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index b25a1bb90f..eac5b43ff2 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -292,9 +292,6 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize
.IntoKey(M::Experimental)
.Define("-Xforce-nb-testing")
.IntoKey(M::ForceNativeBridge)
- .Define("-XOatFileManagerCompilerFilter:_")
- .WithType<std::string>()
- .IntoKey(M::OatFileManagerCompilerFilter)
.Ignore({
"-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa",
"-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_",
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index bb19cbd255..45ba7d0fc2 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -60,7 +60,6 @@
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
#include "compiler_callbacks.h"
-#include "compiler_filter.h"
#include "debugger.h"
#include "elf_file.h"
#include "entrypoints/runtime_asm_entrypoints.h"
@@ -967,16 +966,6 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
experimental_flags_ = runtime_options.GetOrDefault(Opt::Experimental);
is_low_memory_mode_ = runtime_options.Exists(Opt::LowMemoryMode);
- {
- CompilerFilter::Filter filter;
- std::string filter_str = runtime_options.GetOrDefault(Opt::OatFileManagerCompilerFilter);
- if (!CompilerFilter::ParseCompilerFilter(filter_str.c_str(), &filter)) {
- LOG(ERROR) << "Cannot parse compiler filter " << filter_str;
- return false;
- }
- OatFileManager::SetCompilerFilter(filter);
- }
-
XGcOption xgc_option = runtime_options.GetOrDefault(Opt::GcOption);
heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
runtime_options.GetOrDefault(Opt::HeapGrowthLimit),
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index 2a96703109..6db0cb2cb6 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -134,6 +134,5 @@ RUNTIME_OPTIONS_KEY (void (*)(int32_t status), \
// We don't call abort(3) by default; see
// Runtime::Abort.
RUNTIME_OPTIONS_KEY (void (*)(), HookAbort, nullptr)
-RUNTIME_OPTIONS_KEY (std::string, OatFileManagerCompilerFilter, "speed")
#undef RUNTIME_OPTIONS_KEY
diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc
index 2bdf8d1e71..8619ff7f3e 100644
--- a/test/004-JniTest/jni_test.cc
+++ b/test/004-JniTest/jni_test.cc
@@ -14,23 +14,22 @@
* limitations under the License.
*/
-#include <assert.h>
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <vector>
+#include "art_method-inl.h"
+#include "base/logging.h"
#include "jni.h"
-#if defined(NDEBUG)
-#error test code compiled without NDEBUG
-#endif
+namespace art {
static JavaVM* jvm = nullptr;
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void*) {
- assert(vm != nullptr);
- assert(jvm == nullptr);
+ CHECK(vm != nullptr);
+ CHECK(jvm == nullptr);
jvm = vm;
std::cout << "JNI_OnLoad called" << std::endl;
return JNI_VERSION_1_6;
@@ -39,24 +38,24 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void*) {
extern "C" JNIEXPORT void JNI_OnUnload(JavaVM*, void*) {
// std::cout since LOG(INFO) adds extra stuff like pid.
std::cout << "JNI_OnUnload called" << std::endl;
- // Clear jvm for assert in test 004-JniTest.
+ // Clear jvm for CHECK in test 004-JniTest.
jvm = nullptr;
}
static void* AttachHelper(void* arg) {
- assert(jvm != nullptr);
+ CHECK(jvm != nullptr);
JNIEnv* env = nullptr;
JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, nullptr };
int attach_result = jvm->AttachCurrentThread(&env, &args);
- assert(attach_result == 0);
+ CHECK_EQ(attach_result, 0);
typedef void (*Fn)(JNIEnv*);
Fn fn = reinterpret_cast<Fn>(arg);
fn(env);
int detach_result = jvm->DetachCurrentThread();
- assert(detach_result == 0);
+ CHECK_EQ(detach_result, 0);
return nullptr;
}
@@ -64,19 +63,19 @@ static void PthreadHelper(void (*fn)(JNIEnv*)) {
pthread_t pthread;
int pthread_create_result = pthread_create(&pthread, nullptr, AttachHelper,
reinterpret_cast<void*>(fn));
- assert(pthread_create_result == 0);
+ CHECK_EQ(pthread_create_result, 0);
int pthread_join_result = pthread_join(pthread, nullptr);
- assert(pthread_join_result == 0);
+ CHECK_EQ(pthread_join_result, 0);
}
static void testFindClassOnAttachedNativeThread(JNIEnv* env) {
jclass clazz = env->FindClass("Main");
- assert(clazz != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(clazz != nullptr);
+ CHECK(!env->ExceptionCheck());
jobjectArray array = env->NewObjectArray(0, clazz, nullptr);
- assert(array != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(array != nullptr);
+ CHECK(!env->ExceptionCheck());
}
// http://b/10994325
@@ -86,12 +85,12 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testFindClassOnAttachedNativeThread(
static void testFindFieldOnAttachedNativeThread(JNIEnv* env) {
jclass clazz = env->FindClass("Main");
- assert(clazz != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(clazz != nullptr);
+ CHECK(!env->ExceptionCheck());
jfieldID field = env->GetStaticFieldID(clazz, "testFindFieldOnAttachedNativeThreadField", "Z");
- assert(field != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(field != nullptr);
+ CHECK(!env->ExceptionCheck());
env->SetStaticBooleanField(clazz, field, JNI_TRUE);
}
@@ -103,38 +102,38 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testFindFieldOnAttachedNativeThreadN
static void testReflectFieldGetFromAttachedNativeThread(JNIEnv* env) {
jclass clazz = env->FindClass("Main");
- assert(clazz != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(clazz != nullptr);
+ CHECK(!env->ExceptionCheck());
jclass class_clazz = env->FindClass("java/lang/Class");
- assert(class_clazz != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(class_clazz != nullptr);
+ CHECK(!env->ExceptionCheck());
jmethodID getFieldMetodId = env->GetMethodID(class_clazz, "getField",
"(Ljava/lang/String;)Ljava/lang/reflect/Field;");
- assert(getFieldMetodId != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(getFieldMetodId != nullptr);
+ CHECK(!env->ExceptionCheck());
jstring field_name = env->NewStringUTF("testReflectFieldGetFromAttachedNativeThreadField");
- assert(field_name != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(field_name != nullptr);
+ CHECK(!env->ExceptionCheck());
jobject field = env->CallObjectMethod(clazz, getFieldMetodId, field_name);
- assert(field != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(field != nullptr);
+ CHECK(!env->ExceptionCheck());
jclass field_clazz = env->FindClass("java/lang/reflect/Field");
- assert(field_clazz != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(field_clazz != nullptr);
+ CHECK(!env->ExceptionCheck());
jmethodID getBooleanMetodId = env->GetMethodID(field_clazz, "getBoolean",
"(Ljava/lang/Object;)Z");
- assert(getBooleanMetodId != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(getBooleanMetodId != nullptr);
+ CHECK(!env->ExceptionCheck());
jboolean value = env->CallBooleanMethod(field, getBooleanMetodId, /* ignored */ clazz);
- assert(value == false);
- assert(!env->ExceptionCheck());
+ CHECK(value == false);
+ CHECK(!env->ExceptionCheck());
}
// http://b/15539150
@@ -148,22 +147,22 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testReflectFieldGetFromAttachedNativ
extern "C" JNIEXPORT void JNICALL Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env,
jclass) {
jclass super_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SuperClass");
- assert(super_class != nullptr);
+ CHECK(super_class != nullptr);
jmethodID execute = env->GetStaticMethodID(super_class, "execute", "()V");
- assert(execute != nullptr);
+ CHECK(execute != nullptr);
jclass sub_class = env->FindClass("Main$testCallStaticVoidMethodOnSubClass_SubClass");
- assert(sub_class != nullptr);
+ CHECK(sub_class != nullptr);
env->CallStaticVoidMethod(sub_class, execute);
}
extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass) {
jclass abstract_class = env->FindClass("Main$testGetMirandaMethod_MirandaAbstract");
- assert(abstract_class != nullptr);
+ CHECK(abstract_class != nullptr);
jmethodID miranda_method = env->GetMethodID(abstract_class, "inInterface", "()Z");
- assert(miranda_method != nullptr);
+ CHECK(miranda_method != nullptr);
return env->ToReflectedMethod(abstract_class, miranda_method, JNI_FALSE);
}
@@ -171,11 +170,11 @@ extern "C" JNIEXPORT jobject JNICALL Java_Main_testGetMirandaMethodNative(JNIEnv
extern "C" void JNICALL Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass) {
std::vector<uint8_t> buffer(1);
jobject byte_buffer = env->NewDirectByteBuffer(&buffer[0], 0);
- assert(byte_buffer != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(byte_buffer != nullptr);
+ CHECK(!env->ExceptionCheck());
- assert(env->GetDirectBufferAddress(byte_buffer) == &buffer[0]);
- assert(env->GetDirectBufferCapacity(byte_buffer) == 0);
+ CHECK_EQ(env->GetDirectBufferAddress(byte_buffer), &buffer[0]);
+ CHECK_EQ(env->GetDirectBufferCapacity(byte_buffer), 0);
}
constexpr size_t kByteReturnSize = 7;
@@ -185,18 +184,18 @@ extern "C" jbyte JNICALL Java_Main_byteMethod(JNIEnv*, jclass, jbyte b1, jbyte b
jbyte b3, jbyte b4, jbyte b5, jbyte b6,
jbyte b7, jbyte b8, jbyte b9, jbyte b10) {
// We use b1 to drive the output.
- assert(b2 == 2);
- assert(b3 == -3);
- assert(b4 == 4);
- assert(b5 == -5);
- assert(b6 == 6);
- assert(b7 == -7);
- assert(b8 == 8);
- assert(b9 == -9);
- assert(b10 == 10);
-
- assert(0 <= b1);
- assert(b1 < static_cast<jbyte>(kByteReturnSize));
+ CHECK_EQ(b2, 2);
+ CHECK_EQ(b3, -3);
+ CHECK_EQ(b4, 4);
+ CHECK_EQ(b5, -5);
+ CHECK_EQ(b6, 6);
+ CHECK_EQ(b7, -7);
+ CHECK_EQ(b8, 8);
+ CHECK_EQ(b9, -9);
+ CHECK_EQ(b10, 10);
+
+ CHECK_LE(0, b1);
+ CHECK_LT(b1, static_cast<jbyte>(kByteReturnSize));
return byte_returns[b1];
}
@@ -210,18 +209,18 @@ extern "C" jshort JNICALL Java_Main_shortMethod(JNIEnv*, jclass, jshort s1, jsho
jshort s3, jshort s4, jshort s5, jshort s6,
jshort s7, jshort s8, jshort s9, jshort s10) {
// We use s1 to drive the output.
- assert(s2 == 2);
- assert(s3 == -3);
- assert(s4 == 4);
- assert(s5 == -5);
- assert(s6 == 6);
- assert(s7 == -7);
- assert(s8 == 8);
- assert(s9 == -9);
- assert(s10 == 10);
-
- assert(0 <= s1);
- assert(s1 < static_cast<jshort>(kShortReturnSize));
+ CHECK_EQ(s2, 2);
+ CHECK_EQ(s3, -3);
+ CHECK_EQ(s4, 4);
+ CHECK_EQ(s5, -5);
+ CHECK_EQ(s6, 6);
+ CHECK_EQ(s7, -7);
+ CHECK_EQ(s8, 8);
+ CHECK_EQ(s9, -9);
+ CHECK_EQ(s10, 10);
+
+ CHECK_LE(0, s1);
+ CHECK_LT(s1, static_cast<jshort>(kShortReturnSize));
return short_returns[s1];
}
@@ -231,17 +230,17 @@ extern "C" jboolean JNICALL Java_Main_booleanMethod(JNIEnv*, jclass, jboolean b1
jboolean b5, jboolean b6, jboolean b7,
jboolean b8, jboolean b9, jboolean b10) {
// We use b1 to drive the output.
- assert(b2 == JNI_TRUE);
- assert(b3 == JNI_FALSE);
- assert(b4 == JNI_TRUE);
- assert(b5 == JNI_FALSE);
- assert(b6 == JNI_TRUE);
- assert(b7 == JNI_FALSE);
- assert(b8 == JNI_TRUE);
- assert(b9 == JNI_FALSE);
- assert(b10 == JNI_TRUE);
-
- assert(b1 == JNI_TRUE || b1 == JNI_FALSE);
+ CHECK_EQ(b2, JNI_TRUE);
+ CHECK_EQ(b3, JNI_FALSE);
+ CHECK_EQ(b4, JNI_TRUE);
+ CHECK_EQ(b5, JNI_FALSE);
+ CHECK_EQ(b6, JNI_TRUE);
+ CHECK_EQ(b7, JNI_FALSE);
+ CHECK_EQ(b8, JNI_TRUE);
+ CHECK_EQ(b9, JNI_FALSE);
+ CHECK_EQ(b10, JNI_TRUE);
+
+ CHECK(b1 == JNI_TRUE || b1 == JNI_FALSE);
return b1;
}
@@ -252,17 +251,17 @@ extern "C" jchar JNICALL Java_Main_charMethod(JNIEnv*, jclass, jchar c1, jchar c
jchar c3, jchar c4, jchar c5, jchar c6, jchar c7,
jchar c8, jchar c9, jchar c10) {
// We use c1 to drive the output.
- assert(c2 == 'a');
- assert(c3 == 'b');
- assert(c4 == 'c');
- assert(c5 == '0');
- assert(c6 == '1');
- assert(c7 == '2');
- assert(c8 == 1234);
- assert(c9 == 2345);
- assert(c10 == 3456);
-
- assert(c1 < static_cast<jchar>(kCharReturnSize));
+ CHECK_EQ(c2, 'a');
+ CHECK_EQ(c3, 'b');
+ CHECK_EQ(c4, 'c');
+ CHECK_EQ(c5, '0');
+ CHECK_EQ(c6, '1');
+ CHECK_EQ(c7, '2');
+ CHECK_EQ(c8, 1234);
+ CHECK_EQ(c9, 2345);
+ CHECK_EQ(c10, 3456);
+
+ CHECK_LT(c1, static_cast<jchar>(kCharReturnSize));
return char_returns[c1];
}
@@ -281,39 +280,39 @@ static void testShallowGetCallingClassLoader(JNIEnv* env) {
// Test direct call.
{
jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
- assert(vmstack_clazz != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(vmstack_clazz != nullptr);
+ CHECK(!env->ExceptionCheck());
jmethodID getCallingClassLoaderMethodId = env->GetStaticMethodID(vmstack_clazz,
"getCallingClassLoader",
"()Ljava/lang/ClassLoader;");
- assert(getCallingClassLoaderMethodId != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(getCallingClassLoaderMethodId != nullptr);
+ CHECK(!env->ExceptionCheck());
jobject class_loader = env->CallStaticObjectMethod(vmstack_clazz,
getCallingClassLoaderMethodId);
- assert(class_loader == nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(class_loader == nullptr);
+ CHECK(!env->ExceptionCheck());
}
// Test one-level call. Use System.loadLibrary().
{
jclass system_clazz = env->FindClass("java/lang/System");
- assert(system_clazz != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(system_clazz != nullptr);
+ CHECK(!env->ExceptionCheck());
jmethodID loadLibraryMethodId = env->GetStaticMethodID(system_clazz, "loadLibrary",
"(Ljava/lang/String;)V");
- assert(loadLibraryMethodId != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(loadLibraryMethodId != nullptr);
+ CHECK(!env->ExceptionCheck());
// Create a string object.
jobject library_string = env->NewStringUTF("non_existing_library");
- assert(library_string != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(library_string != nullptr);
+ CHECK(!env->ExceptionCheck());
env->CallStaticVoidMethod(system_clazz, loadLibraryMethodId, library_string);
- assert(env->ExceptionCheck());
+ CHECK(env->ExceptionCheck());
// We expect UnsatisfiedLinkError.
jthrowable thrown = env->ExceptionOccurred();
@@ -321,7 +320,7 @@ static void testShallowGetCallingClassLoader(JNIEnv* env) {
jclass unsatisfied_link_error_clazz = env->FindClass("java/lang/UnsatisfiedLinkError");
jclass thrown_class = env->GetObjectClass(thrown);
- assert(env->IsSameObject(unsatisfied_link_error_clazz, thrown_class));
+ CHECK(env->IsSameObject(unsatisfied_link_error_clazz, thrown_class));
}
}
@@ -333,31 +332,31 @@ extern "C" JNIEXPORT void JNICALL Java_Main_nativeTestShallowGetCallingClassLoad
static void testShallowGetStackClass2(JNIEnv* env) {
jclass vmstack_clazz = env->FindClass("dalvik/system/VMStack");
- assert(vmstack_clazz != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(vmstack_clazz != nullptr);
+ CHECK(!env->ExceptionCheck());
// Test direct call.
{
jmethodID getStackClass2MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass2",
"()Ljava/lang/Class;");
- assert(getStackClass2MethodId != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(getStackClass2MethodId != nullptr);
+ CHECK(!env->ExceptionCheck());
jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass2MethodId);
- assert(caller_class == nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(caller_class == nullptr);
+ CHECK(!env->ExceptionCheck());
}
// Test one-level call. Use VMStack.getStackClass1().
{
jmethodID getStackClass1MethodId = env->GetStaticMethodID(vmstack_clazz, "getStackClass1",
"()Ljava/lang/Class;");
- assert(getStackClass1MethodId != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(getStackClass1MethodId != nullptr);
+ CHECK(!env->ExceptionCheck());
jobject caller_class = env->CallStaticObjectMethod(vmstack_clazz, getStackClass1MethodId);
- assert(caller_class == nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(caller_class == nullptr);
+ CHECK(!env->ExceptionCheck());
}
// For better testing we would need to compile against libcore and have a two-deep stack
@@ -416,8 +415,8 @@ class JniCallNonvirtualVoidMethodTest {
env_->ExceptionDescribe();
env_->FatalError(__FUNCTION__);
}
- assert(!env_->ExceptionCheck());
- assert(c != nullptr);
+ CHECK(!env_->ExceptionCheck());
+ CHECK(c != nullptr);
return c;
}
@@ -429,7 +428,7 @@ class JniCallNonvirtualVoidMethodTest {
env_->ExceptionDescribe();
env_->FatalError(__FUNCTION__);
}
- assert(m != nullptr);
+ CHECK(m != nullptr);
return m;
}
@@ -439,7 +438,7 @@ class JniCallNonvirtualVoidMethodTest {
env_->ExceptionDescribe();
env_->FatalError(__FUNCTION__);
}
- assert(o != nullptr);
+ CHECK(o != nullptr);
return o;
}
@@ -467,7 +466,7 @@ class JniCallNonvirtualVoidMethodTest {
env_->ExceptionDescribe();
env_->FatalError(__FUNCTION__);
}
- assert(m != nullptr);
+ CHECK(m != nullptr);
return m;
}
@@ -508,21 +507,21 @@ class JniCallNonvirtualVoidMethodTest {
jobject sub_super = CallConstructor(sub_, super_constructor_);
jobject sub_sub = CallConstructor(sub_, sub_constructor_);
- assert(env_->IsInstanceOf(super_super, super_));
- assert(!env_->IsInstanceOf(super_super, sub_));
+ CHECK(env_->IsInstanceOf(super_super, super_));
+ CHECK(!env_->IsInstanceOf(super_super, sub_));
// Note that even though we called (and ran) the subclass
// constructor, we are not the subclass.
- assert(env_->IsInstanceOf(super_sub, super_));
- assert(!env_->IsInstanceOf(super_sub, sub_));
+ CHECK(env_->IsInstanceOf(super_sub, super_));
+ CHECK(!env_->IsInstanceOf(super_sub, sub_));
// Note that even though we called the superclass constructor, we
// are still the subclass.
- assert(env_->IsInstanceOf(sub_super, super_));
- assert(env_->IsInstanceOf(sub_super, sub_));
+ CHECK(env_->IsInstanceOf(sub_super, super_));
+ CHECK(env_->IsInstanceOf(sub_super, sub_));
- assert(env_->IsInstanceOf(sub_sub, super_));
- assert(env_->IsInstanceOf(sub_sub, sub_));
+ CHECK(env_->IsInstanceOf(sub_sub, super_));
+ CHECK(env_->IsInstanceOf(sub_sub, sub_));
}
void TestnonstaticCallNonvirtualMethod(bool super_object, bool super_class, bool super_method, const char* test_case) {
@@ -542,8 +541,8 @@ class JniCallNonvirtualVoidMethodTest {
CallMethod(o, c, m, true, test_case);
jboolean super_field = GetBooleanField(o, super_field_);
jboolean sub_field = GetBooleanField(o, sub_field_);
- assert(super_field == super_method);
- assert(sub_field != super_method);
+ CHECK_EQ(super_field, super_method);
+ CHECK_NE(sub_field, super_method);
}
void TestnonstaticCallNonvirtualMethod() {
@@ -565,20 +564,20 @@ extern "C" void JNICALL Java_Main_testCallNonvirtual(JNIEnv* env, jclass) {
extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jclass) {
jclass c = env->FindClass("java/lang/String");
- assert(c != nullptr);
+ CHECK(c != nullptr);
jmethodID mid1 = env->GetMethodID(c, "<init>", "()V");
- assert(mid1 != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(mid1 != nullptr);
+ CHECK(!env->ExceptionCheck());
jmethodID mid2 = env->GetMethodID(c, "<init>", "([B)V");
- assert(mid2 != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(mid2 != nullptr);
+ CHECK(!env->ExceptionCheck());
jmethodID mid3 = env->GetMethodID(c, "<init>", "([C)V");
- assert(mid3 != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(mid3 != nullptr);
+ CHECK(!env->ExceptionCheck());
jmethodID mid4 = env->GetMethodID(c, "<init>", "(Ljava/lang/String;)V");
- assert(mid4 != nullptr);
- assert(!env->ExceptionCheck());
+ CHECK(mid4 != nullptr);
+ CHECK(!env->ExceptionCheck());
const char* test_array = "Test";
int byte_array_length = strlen(test_array);
@@ -587,22 +586,22 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jcl
// Test NewObject
jstring s = reinterpret_cast<jstring>(env->NewObject(c, mid2, byte_array));
- assert(s != nullptr);
- assert(env->GetStringLength(s) == byte_array_length);
- assert(env->GetStringUTFLength(s) == byte_array_length);
+ CHECK(s != nullptr);
+ CHECK_EQ(env->GetStringLength(s), byte_array_length);
+ CHECK_EQ(env->GetStringUTFLength(s), byte_array_length);
const char* chars = env->GetStringUTFChars(s, nullptr);
- assert(strcmp(test_array, chars) == 0);
+ CHECK_EQ(strcmp(test_array, chars), 0);
env->ReleaseStringUTFChars(s, chars);
// Test AllocObject and Call(Nonvirtual)VoidMethod
jstring s1 = reinterpret_cast<jstring>(env->AllocObject(c));
- assert(s1 != nullptr);
+ CHECK(s1 != nullptr);
jstring s2 = reinterpret_cast<jstring>(env->AllocObject(c));
- assert(s2 != nullptr);
+ CHECK(s2 != nullptr);
jstring s3 = reinterpret_cast<jstring>(env->AllocObject(c));
- assert(s3 != nullptr);
+ CHECK(s3 != nullptr);
jstring s4 = reinterpret_cast<jstring>(env->AllocObject(c));
- assert(s4 != nullptr);
+ CHECK(s4 != nullptr);
jcharArray char_array = env->NewCharArray(5);
jstring string_arg = env->NewStringUTF("helloworld");
@@ -621,18 +620,18 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testNewStringObject(JNIEnv* env, jcl
// Test with global and weak global references
jstring s5 = reinterpret_cast<jstring>(env->AllocObject(c));
- assert(s5 != nullptr);
+ CHECK(s5 != nullptr);
s5 = reinterpret_cast<jstring>(env->NewGlobalRef(s5));
jstring s6 = reinterpret_cast<jstring>(env->AllocObject(c));
- assert(s6 != nullptr);
+ CHECK(s6 != nullptr);
s6 = reinterpret_cast<jstring>(env->NewWeakGlobalRef(s6));
env->CallVoidMethod(s5, mid1);
env->CallNonvirtualVoidMethod(s6, c, mid2, byte_array);
- assert(env->GetStringLength(s5) == 0);
- assert(env->GetStringLength(s6) == byte_array_length);
+ CHECK_EQ(env->GetStringLength(s5), 0);
+ CHECK_EQ(env->GetStringLength(s6), byte_array_length);
const char* chars6 = env->GetStringUTFChars(s6, nullptr);
- assert(strcmp(test_array, chars6) == 0);
+ CHECK_EQ(strcmp(test_array, chars6), 0);
env->ReleaseStringUTFChars(s6, chars6);
}
@@ -664,8 +663,8 @@ class JniCallDefaultMethodsTest {
public:
explicit JniCallDefaultMethodsTest(JNIEnv* env)
: env_(env), concrete_class_(env_->FindClass("ConcreteClass")) {
- assert(!env_->ExceptionCheck());
- assert(concrete_class_ != nullptr);
+ CHECK(!env_->ExceptionCheck());
+ CHECK(concrete_class_ != nullptr);
}
void Test() {
@@ -688,14 +687,14 @@ class JniCallDefaultMethodsTest {
void TestCalls(const char* declaring_class, std::vector<const char*> methods) {
jmethodID new_method = env_->GetMethodID(concrete_class_, "<init>", "()V");
jobject obj = env_->NewObject(concrete_class_, new_method);
- assert(!env_->ExceptionCheck());
- assert(obj != nullptr);
+ CHECK(!env_->ExceptionCheck());
+ CHECK(obj != nullptr);
jclass decl_class = env_->FindClass(declaring_class);
- assert(!env_->ExceptionCheck());
- assert(decl_class != nullptr);
+ CHECK(!env_->ExceptionCheck());
+ CHECK(decl_class != nullptr);
for (const char* method : methods) {
jmethodID method_id = env_->GetMethodID(decl_class, method, "()V");
- assert(!env_->ExceptionCheck());
+ CHECK(!env_->ExceptionCheck());
printf("Calling method %s->%s on object of type ConcreteClass\n", declaring_class, method);
env_->CallVoidMethod(obj, method_id);
if (env_->ExceptionCheck()) {
@@ -704,10 +703,10 @@ class JniCallDefaultMethodsTest {
jmethodID to_string = env_->GetMethodID(
env_->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;");
jstring exception_string = (jstring) env_->CallObjectMethod(thrown, to_string);
- assert(!env_->ExceptionCheck());
+ CHECK(!env_->ExceptionCheck());
const char* exception_string_utf8 = env_->GetStringUTFChars(exception_string, nullptr);
- assert(!env_->ExceptionCheck());
- assert(exception_string_utf8 != nullptr);
+ CHECK(!env_->ExceptionCheck());
+ CHECK(exception_string_utf8 != nullptr);
printf("EXCEPTION OCCURED: %s\n", exception_string_utf8);
env_->ReleaseStringUTFChars(exception_string, exception_string_utf8);
}
@@ -724,12 +723,12 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testCallDefaultMethods(JNIEnv* env)
static void InvokeSpecificMethod(JNIEnv* env, jobject obj, const char* method) {
jclass lambda_class = env->FindClass("LambdaInterface");
- assert(!env->ExceptionCheck());
- assert(lambda_class != nullptr);
+ CHECK(!env->ExceptionCheck());
+ CHECK(lambda_class != nullptr);
jmethodID method_id = env->GetMethodID(lambda_class, method, "()V");
- assert(!env->ExceptionCheck());
+ CHECK(!env->ExceptionCheck());
env->CallVoidMethod(obj, method_id);
- assert(!env->ExceptionCheck());
+ CHECK(!env->ExceptionCheck());
}
extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaDefaultMethod(
@@ -740,3 +739,6 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaDefaultMethod(
extern "C" JNIEXPORT void JNICALL Java_Main_testInvokeLambdaMethod(JNIEnv* e, jclass, jobject l) {
InvokeSpecificMethod(e, l, "sayHi");
}
+
+} // namespace art
+
diff --git a/test/004-ReferenceMap/stack_walk_refmap_jni.cc b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
index 284e5544fb..5304590ad0 100644
--- a/test/004-ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "art_method-inl.h"
#include "check_reference_map_visitor.h"
#include "jni.h"
diff --git a/test/004-StackWalk/stack_walk_jni.cc b/test/004-StackWalk/stack_walk_jni.cc
index 51bb68f24a..420224dd21 100644
--- a/test/004-StackWalk/stack_walk_jni.cc
+++ b/test/004-StackWalk/stack_walk_jni.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "art_method-inl.h"
#include "check_reference_map_visitor.h"
#include "jni.h"
diff --git a/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc
index 54879fbad9..c9110a905d 100644
--- a/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc
+++ b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <dlfcn.h>
#include <iostream>
#include "base/casts.h"
@@ -45,6 +46,10 @@ extern "C" JNIEXPORT void JNICALL Java_Main_destroyJavaVMAndExit(JNIEnv* env, jc
self->SetTopOfShadowStack(nullptr);
JavaVM* vm = down_cast<JNIEnvExt*>(env)->vm;
vm->DetachCurrentThread();
+ // Open ourself again to make sure the native library does not get unloaded from
+ // underneath us due to DestroyJavaVM. b/28406866
+ void* handle = dlopen(kIsDebugBuild ? "libarttestd.so" : "libarttest.so", RTLD_NOW);
+ CHECK(handle != nullptr);
vm->DestroyJavaVM();
vm_was_shutdown.store(true);
// Give threads some time to get stuck in ExceptionCheck.
diff --git a/test/566-polymorphic-inlining/src/Main.java b/test/566-polymorphic-inlining/src/Main.java
index 286f0d996e..a59ce5b344 100644
--- a/test/566-polymorphic-inlining/src/Main.java
+++ b/test/566-polymorphic-inlining/src/Main.java
@@ -98,6 +98,7 @@ public class Main implements Itf {
public static native void ensureJittedAndPolymorphicInline();
public void increment() {
+ field.getClass(); // null check to ensure we get an inlined frame in the CodeInfo
counter++;
}
public static int counter = 0;
diff --git a/test/570-checker-osr/osr.cc b/test/570-checker-osr/osr.cc
index bd8f0a9520..2fa5800e5c 100644
--- a/test/570-checker-osr/osr.cc
+++ b/test/570-checker-osr/osr.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "art_method.h"
+#include "art_method-inl.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "jit/profiling_info.h"
diff --git a/test/595-profile-saving/profile-saving.cc b/test/595-profile-saving/profile-saving.cc
index a7e6f8ba8c..0d26f454c6 100644
--- a/test/595-profile-saving/profile-saving.cc
+++ b/test/595-profile-saving/profile-saving.cc
@@ -16,6 +16,7 @@
#include "dex_file.h"
+#include "art_method-inl.h"
#include "jit/offline_profiling_info.h"
#include "jit/profile_saver.h"
#include "jni.h"
diff --git a/test/595-profile-saving/run b/test/595-profile-saving/run
index f12fac9207..068ad03ce0 100644
--- a/test/595-profile-saving/run
+++ b/test/595-profile-saving/run
@@ -16,13 +16,12 @@
# Use
# --compiler-filter=interpret-only to make sure that the test is not compiled AOT
-# -XOatFileManagerCompilerFilter:interpret-only to make sure the test is not compiled
-# when loaded (by PathClassLoader)
+# and to make sure the test is not compiled when loaded (by PathClassLoader)
# -Xjitsaveprofilinginfo to enable profile saving
# -Xusejit:false to disable jit and only test profiles.
exec ${RUN} \
-Xcompiler-option --compiler-filter=interpret-only \
- --runtime-option -XOatFileManagerCompilerFilter:interpret-only \
+ --runtime-option '-Xcompiler-option --compiler-filter=interpret-only' \
--runtime-option -Xjitsaveprofilinginfo \
--runtime-option -Xusejit:false \
"${@}"
diff --git a/test/596-app-images/app_images.cc b/test/596-app-images/app_images.cc
index 11c0f424ba..a5bbf5fbaa 100644
--- a/test/596-app-images/app_images.cc
+++ b/test/596-app-images/app_images.cc
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <assert.h>
#include <iostream>
#include <pthread.h>
#include <stdio.h>
diff --git a/test/597-deopt-new-string/deopt.cc b/test/597-deopt-new-string/deopt.cc
new file mode 100644
index 0000000000..844a786e1e
--- /dev/null
+++ b/test/597-deopt-new-string/deopt.cc
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+#include "mirror/class-inl.h"
+#include "runtime.h"
+#include "thread_list.h"
+#include "thread_state.h"
+#include "gc/gc_cause.h"
+#include "gc/scoped_gc_critical_section.h"
+
+namespace art {
+
+extern "C" JNIEXPORT void JNICALL Java_Main_deoptimizeAll(
+ JNIEnv* env,
+ jclass cls ATTRIBUTE_UNUSED) {
+ ScopedObjectAccess soa(env);
+ ScopedThreadSuspension sts(Thread::Current(), kWaitingForDeoptimization);
+ gc::ScopedGCCriticalSection gcs(Thread::Current(),
+ gc::kGcCauseInstrumentation,
+ gc::kCollectorTypeInstrumentation);
+ // We need to suspend mutator threads first.
+ ScopedSuspendAll ssa(__FUNCTION__);
+ static bool first = true;
+ if (first) {
+ // We need to enable deoptimization once in order to call DeoptimizeEverything().
+ Runtime::Current()->GetInstrumentation()->EnableDeoptimization();
+ first = false;
+ }
+ Runtime::Current()->GetInstrumentation()->DeoptimizeEverything("test");
+}
+
+extern "C" JNIEXPORT void JNICALL Java_Main_undeoptimizeAll(
+ JNIEnv* env,
+ jclass cls ATTRIBUTE_UNUSED) {
+ ScopedObjectAccess soa(env);
+ ScopedThreadSuspension sts(Thread::Current(), kWaitingForDeoptimization);
+ gc::ScopedGCCriticalSection gcs(Thread::Current(),
+ gc::kGcCauseInstrumentation,
+ gc::kCollectorTypeInstrumentation);
+ // We need to suspend mutator threads first.
+ ScopedSuspendAll ssa(__FUNCTION__);
+ Runtime::Current()->GetInstrumentation()->UndeoptimizeEverything("test");
+}
+
+} // namespace art
diff --git a/test/597-deopt-new-string/expected.txt b/test/597-deopt-new-string/expected.txt
new file mode 100644
index 0000000000..f993efcdad
--- /dev/null
+++ b/test/597-deopt-new-string/expected.txt
@@ -0,0 +1,2 @@
+JNI_OnLoad called
+Finishing
diff --git a/test/597-deopt-new-string/info.txt b/test/597-deopt-new-string/info.txt
new file mode 100644
index 0000000000..1bd1f79c04
--- /dev/null
+++ b/test/597-deopt-new-string/info.txt
@@ -0,0 +1 @@
+Regression test for b/28555675
diff --git a/test/597-deopt-new-string/run b/test/597-deopt-new-string/run
new file mode 100644
index 0000000000..9776ab3eb4
--- /dev/null
+++ b/test/597-deopt-new-string/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# 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.
+
+# We want to run in debuggable mode which keeps the call into StringFactory.newEmptyString().
+exec ${RUN} -Xcompiler-option --debuggable "${@}"
diff --git a/test/597-deopt-new-string/src/Main.java b/test/597-deopt-new-string/src/Main.java
new file mode 100644
index 0000000000..1224e407b0
--- /dev/null
+++ b/test/597-deopt-new-string/src/Main.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+public class Main implements Runnable {
+ static final int numberOfThreads = 2;
+ static final int totalOperations = 40000;
+ static boolean sFlag = false;
+ static volatile boolean done = false;
+ int threadIndex;
+
+ public static native void deoptimizeAll();
+ public static native void undeoptimizeAll();
+
+ Main(int index) {
+ threadIndex = index;
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+
+ final Thread[] threads = new Thread[numberOfThreads];
+ for (int t = 0; t < threads.length; t++) {
+ threads[t] = new Thread(new Main(t));
+ threads[t].start();
+ }
+ for (Thread t : threads) {
+ t.join();
+ }
+ System.out.println("Finishing");
+ }
+
+ public String $noinline$run0() {
+ // Prevent inlining.
+ if (sFlag) {
+ throw new Error();
+ }
+ char[] arr = {'a', 'b', 'c'};
+ return new String(arr, 0, arr.length);
+ }
+
+ public void run() {
+ if (threadIndex == 0) {
+ // This thread keeps doing deoptimization of all threads.
+ // Hopefully that will trigger one deoptimization when returning from
+ // StringFactory.newEmptyString() in one of the other threads.
+ for (int i = 0; i < totalOperations; ++i) {
+ if (i % 50 == 0) {
+ deoptimizeAll();
+ }
+ if (i % 50 == 25) {
+ undeoptimizeAll();
+ }
+ }
+ done = true;
+ } else {
+ // This thread keeps doing new String() from a char array.
+ while (!done) {
+ $noinline$run0();
+ }
+ }
+ }
+}
diff --git a/test/Android.libarttest.mk b/test/Android.libarttest.mk
index d6f5d372a9..21f8141c66 100644
--- a/test/Android.libarttest.mk
+++ b/test/Android.libarttest.mk
@@ -43,7 +43,8 @@ LIBARTTEST_COMMON_SRC_FILES := \
566-polymorphic-inlining/polymorphic_inline.cc \
570-checker-osr/osr.cc \
595-profile-saving/profile-saving.cc \
- 596-app-images/app_images.cc
+ 596-app-images/app_images.cc \
+ 597-deopt-new-string/deopt.cc
ART_TARGET_LIBARTTEST_$(ART_PHONY_TEST_TARGET_SUFFIX) += $(ART_TARGET_TEST_OUT)/$(TARGET_ARCH)/libarttest.so
ART_TARGET_LIBARTTEST_$(ART_PHONY_TEST_TARGET_SUFFIX) += $(ART_TARGET_TEST_OUT)/$(TARGET_ARCH)/libarttestd.so
@@ -92,7 +93,12 @@ define build-libarttest
include $(BUILD_SHARED_LIBRARY)
else # host
LOCAL_CLANG := $(ART_HOST_CLANG)
- LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
+ LOCAL_CFLAGS := $(ART_HOST_CFLAGS)
+ ifeq ($$(suffix),d)
+ LOCAL_CFLAGS += $(ART_HOST_DEBUG_CFLAGS)
+ else
+ LOCAL_CFLAGS += $(ART_HOST_NON_DEBUG_CFLAGS)
+ endif
LOCAL_ASFLAGS := $(ART_HOST_ASFLAGS)
LOCAL_LDLIBS := $(ART_HOST_LDLIBS) -ldl -lpthread
LOCAL_IS_HOST_MODULE := true
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index d61fc8f8fc..01114b7690 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -323,11 +323,14 @@ fi
if [ "$INTERPRETER" = "y" ]; then
INT_OPTS="-Xint"
if [ "$VERIFY" = "y" ] ; then
+ INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=interpret-only"
COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=interpret-only"
elif [ "$VERIFY" = "s" ]; then
+ INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify-at-runtime"
COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-at-runtime"
DEX_VERIFY="${DEX_VERIFY} -Xverify:softfail"
else # VERIFY = "n"
+ INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify-none"
COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-none"
DEX_VERIFY="${DEX_VERIFY} -Xverify:none"
fi
@@ -336,18 +339,12 @@ fi
if [ "$JIT" = "y" ]; then
INT_OPTS="-Xusejit:true"
if [ "$VERIFY" = "y" ] ; then
+ INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify-at-runtime"
COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-at-runtime"
- if [ "$PREBUILD" = "n" ]; then
- # Make sure that if we have noprebuild we still JIT as DexClassLoader will
- # try to compile the dex file.
- INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify-at-runtime"
- fi
else
+ INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify-none"
COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-none"
DEX_VERIFY="${DEX_VERIFY} -Xverify:none"
- if [ "$PREBUILD" = "n" ]; then
- INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify-none"
- fi
fi
fi
diff --git a/test/run-test b/test/run-test
index fc57d0914f..424c54f2c9 100755
--- a/test/run-test
+++ b/test/run-test
@@ -244,11 +244,11 @@ while true; do
run_args="${run_args} --zygote"
shift
elif [ "x$1" = "x--interpreter" ]; then
- run_args="${run_args} --interpreter --runtime-option -XOatFileManagerCompilerFilter:verify-at-runtime"
+ run_args="${run_args} --interpreter"
image_suffix="-interpreter"
shift
elif [ "x$1" = "x--jit" ]; then
- run_args="${run_args} --jit --runtime-option -XOatFileManagerCompilerFilter:verify-at-runtime"
+ run_args="${run_args} --jit"
image_suffix="-jit"
shift
elif [ "x$1" = "x--optimizing" ]; then
@@ -256,10 +256,10 @@ while true; do
image_suffix="-optimizing"
shift
elif [ "x$1" = "x--no-verify" ]; then
- run_args="${run_args} --no-verify --runtime-option -XOatFileManagerCompilerFilter:verify-none"
+ run_args="${run_args} --no-verify"
shift
elif [ "x$1" = "x--verify-soft-fail" ]; then
- run_args="${run_args} --verify-soft-fail --runtime-option -XOatFileManagerCompilerFilter:verify-at-runtime"
+ run_args="${run_args} --verify-soft-fail"
image_suffix="-interp-ac"
shift
elif [ "x$1" = "x--no-optimize" ]; then