summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/code_sinking.cc5
-rw-r--r--dex2oat/dex2oat.cc8
-rw-r--r--dex2oat/dex2oat_test.cc33
-rw-r--r--libdexfile/dex/dex_file_loader.cc2
-rw-r--r--runtime/class_linker.cc8
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc10
-rw-r--r--runtime/hidden_api.h4
-rw-r--r--runtime/jit/jit.cc7
-rw-r--r--runtime/native/dalvik_system_VMDebug.cc45
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.cc1
-rw-r--r--runtime/runtime.cc1
-rw-r--r--runtime/trace.cc100
-rw-r--r--runtime/trace.h43
-rw-r--r--runtime/verifier/method_verifier.cc375
-rw-r--r--runtime/verifier/method_verifier.h17
-rw-r--r--test/121-modifiers/classes/A$B.classbin223 -> 0 bytes
-rw-r--r--test/121-modifiers/classes/A$C.classbin130 -> 0 bytes
-rw-r--r--test/121-modifiers/classes/A.classbin248 -> 0 bytes
-rw-r--r--test/121-modifiers/classes/Inf.classbin128 -> 0 bytes
-rw-r--r--test/121-modifiers/classes/Main.classbin3772 -> 0 bytes
-rw-r--r--test/121-modifiers/classes/NonInf.classbin1026 -> 0 bytes
-rw-r--r--test/121-modifiers/info.txt6
-rw-r--r--test/161-final-abstract-class/smali/Main.smali214
-rw-r--r--test/161-final-abstract-class/src/Main.java48
-rw-r--r--test/1929-exception-catch-exception/expected.txt158
-rw-r--r--test/1929-exception-catch-exception/src/art/Test1929.java93
-rw-r--r--test/1935-get-set-current-frame-jit/expected.txt4
-rw-r--r--test/1935-get-set-current-frame-jit/src/Main.java8
-rwxr-xr-xtest/1940-ddms-ext/check2
-rw-r--r--test/1940-ddms-ext/expected_error.txt4
-rwxr-xr-xtest/1940-ddms-ext/remove_error.py38
-rw-r--r--test/674-hiddenapi/src-ex/ChildClass.java34
-rw-r--r--test/674-hiddenapi/src-ex/Linking.java11
-rw-r--r--test/674-hiddenapi/src-ex/OverrideClass.java35
-rw-r--r--test/679-locks/expected.txt2
-rw-r--r--test/679-locks/info.txt2
-rw-r--r--test/679-locks/run18
-rw-r--r--test/679-locks/src/Main.java50
-rw-r--r--test/680-sink-regression/expected.txt1
-rw-r--r--test/680-sink-regression/info.txt1
-rw-r--r--test/680-sink-regression/src/Main.java87
-rw-r--r--test/Android.run-test.mk3
-rwxr-xr-xtest/etc/default-build22
-rw-r--r--test/knownfailures.json3
-rwxr-xr-xtest/run-test12
-rw-r--r--test/testrunner/env.py5
-rwxr-xr-xtest/testrunner/testrunner.py15
-rw-r--r--tools/ahat/Android.bp25
-rw-r--r--tools/ahat/Android.mk17
-rw-r--r--tools/veridex/Android.bp27
-rw-r--r--tools/veridex/resolver.cc58
-rw-r--r--tools/veridex/resolver.h46
-rw-r--r--tools/veridex/veridex.cc179
-rw-r--r--tools/veridex/veridex.h72
54 files changed, 1266 insertions, 693 deletions
diff --git a/compiler/optimizing/code_sinking.cc b/compiler/optimizing/code_sinking.cc
index f4760d661f..2e31d35584 100644
--- a/compiler/optimizing/code_sinking.cc
+++ b/compiler/optimizing/code_sinking.cc
@@ -214,6 +214,11 @@ static HInstruction* FindIdealPosition(HInstruction* instruction,
DCHECK(target_block != nullptr);
}
+ // Bail if the instruction can throw and we are about to move into a catch block.
+ if (instruction->CanThrow() && target_block->GetTryCatchInformation() != nullptr) {
+ return nullptr;
+ }
+
// Find insertion position. No need to filter anymore, as we have found a
// target block.
HInstruction* insert_pos = nullptr;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 9b370178f7..6950b93e51 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1609,11 +1609,9 @@ class Dex2Oat FINAL {
// Unzip or copy dex files straight to the oat file.
std::vector<std::unique_ptr<MemMap>> opened_dex_files_map;
std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
- // No need to verify the dex file for:
- // 1) Dexlayout since it does the verification. It also may not pass the verification since
- // we don't update the dex checksum.
- // 2) when we have a vdex file, which means it was already verified.
- const bool verify = !DoDexLayoutOptimizations() && (input_vdex_file_ == nullptr);
+ // No need to verify the dex file when we have a vdex file, which means it was already
+ // verified.
+ const bool verify = (input_vdex_file_ == nullptr);
if (!oat_writers_[i]->WriteAndOpenDexFiles(
vdex_files_[i].get(),
rodata_.back(),
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 5590c8b3ab..5e9782aadf 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -2013,4 +2013,37 @@ TEST_F(Dex2oatTest, QuickenedInput) {
ASSERT_EQ(vdex_unquickened->FlushCloseOrErase(), 0) << "Could not flush and close";
}
+// Test that compact dex generation with invalid dex files doesn't crash dex2oat. b/75970654
+TEST_F(Dex2oatTest, CompactDexInvalidSource) {
+ ScratchFile invalid_dex;
+ {
+ FILE* file = fdopen(invalid_dex.GetFd(), "w+b");
+ ZipWriter writer(file);
+ writer.StartEntry("classes.dex", ZipWriter::kAlign32);
+ DexFile::Header header = {};
+ StandardDexFile::WriteMagic(header.magic_);
+ StandardDexFile::WriteCurrentVersion(header.magic_);
+ header.file_size_ = 4 * KB;
+ header.data_size_ = 4 * KB;
+ header.data_off_ = 10 * MB;
+ header.map_off_ = 10 * MB;
+ header.class_defs_off_ = 10 * MB;
+ header.class_defs_size_ = 10000;
+ ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
+ writer.FinishEntry();
+ writer.Finish();
+ ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
+ }
+ const std::string dex_location = invalid_dex.GetFilename();
+ const std::string odex_location = GetOdexDir() + "/output.odex";
+ std::string error_msg;
+ int status = GenerateOdexForTestWithStatus(
+ {dex_location},
+ odex_location,
+ CompilerFilter::kQuicken,
+ &error_msg,
+ { "--compact-dex-level=fast" });
+ ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
+}
+
} // namespace art
diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc
index 758a2f0599..1e0f5ac6ae 100644
--- a/libdexfile/dex/dex_file_loader.cc
+++ b/libdexfile/dex/dex_file_loader.cc
@@ -348,6 +348,8 @@ std::unique_ptr<DexFile> DexFileLoader::OpenCommon(const uint8_t* base,
location_checksum,
oat_dex_file,
std::move(container)));
+ // Disable verification for CompactDex input.
+ verify = false;
} else {
*error_msg = "Invalid or truncated dex file";
}
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 8a29ff33b7..1d72b46f6c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -5863,14 +5863,6 @@ bool ClassLinker::LinkVirtualMethods(
// smaller as we go on.
uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator);
if (hash_index != hash_table.GetNotFoundIndex()) {
- // Run a check whether we are going to override a method which is hidden
- // to `klass`, but ignore the result as we only warn at the moment.
- // We cannot do this test earlier because we need to establish that
- // a method is being overridden first. ShouldBlockAccessToMember would
- // print bogus warnings otherwise.
- hiddenapi::ShouldBlockAccessToMember(
- super_method, klass->GetClassLoader(), hiddenapi::kOverride);
-
ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(
hash_index, image_pointer_size_);
if (super_method->IsFinal()) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 7a0850d4b8..2284100564 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -2338,10 +2338,6 @@ extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self, ArtMethod**
ArtMethod* called = *sp;
DCHECK(called->IsNative()) << called->PrettyMethod(true);
Runtime* runtime = Runtime::Current();
- jit::Jit* jit = runtime->GetJit();
- if (jit != nullptr) {
- jit->AddSamples(self, called, 1u, /*with_backedges*/ false);
- }
uint32_t shorty_len = 0;
const char* shorty = called->GetShorty(&shorty_len);
bool critical_native = called->IsCriticalNative();
@@ -2367,6 +2363,12 @@ extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self, ArtMethod**
self->VerifyStack();
+ // We can now walk the stack if needed by JIT GC from MethodEntered() for JIT-on-first-use.
+ jit::Jit* jit = runtime->GetJit();
+ if (jit != nullptr) {
+ jit->MethodEntered(self, called);
+ }
+
uint32_t cookie;
uint32_t* sp32;
// Skip calling JniMethodStart for @CriticalNative.
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 321d55d9b7..5c6b4b56bc 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -55,7 +55,6 @@ enum AccessMethod {
kReflection,
kJNI,
kLinking,
- kOverride,
};
inline std::ostream& operator<<(std::ostream& os, AccessMethod value) {
@@ -69,9 +68,6 @@ inline std::ostream& operator<<(std::ostream& os, AccessMethod value) {
case kLinking:
os << "linking";
break;
- case kOverride:
- os << "override";
- break;
}
return os;
}
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 23cf071d56..813430f0bb 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -718,10 +718,11 @@ void Jit::MethodEntered(Thread* thread, ArtMethod* method) {
Runtime* runtime = Runtime::Current();
if (UNLIKELY(runtime->UseJitCompilation() && runtime->GetJit()->JitAtFirstUse())) {
ArtMethod* np_method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
- DCHECK(!np_method->IsNative());
if (np_method->IsCompilable()) {
- // The compiler requires a ProfilingInfo object.
- ProfilingInfo::Create(thread, np_method, /* retry_allocation */ true);
+ if (!np_method->IsNative()) {
+ // The compiler requires a ProfilingInfo object for non-native methods.
+ ProfilingInfo::Create(thread, np_method, /* retry_allocation */ true);
+ }
JitCompileTask compile_task(method, JitCompileTask::kCompile);
compile_task.Run(thread);
}
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index fc9426650e..3692a308d8 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -89,17 +89,27 @@ static void VMDebug_resetAllocCount(JNIEnv*, jclass, jint kinds) {
static void VMDebug_startMethodTracingDdmsImpl(JNIEnv*, jclass, jint bufferSize, jint flags,
jboolean samplingEnabled, jint intervalUs) {
- Trace::Start("[DDMS]", -1, bufferSize, flags, Trace::TraceOutputMode::kDDMS,
- samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
- intervalUs);
-}
-
-static void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceFilename,
- jint javaFd, jint bufferSize, jint flags,
- jboolean samplingEnabled, jint intervalUs,
+ Trace::StartDDMS(bufferSize,
+ flags,
+ samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
+ intervalUs);
+}
+
+static void VMDebug_startMethodTracingFd(JNIEnv* env,
+ jclass,
+ jstring javaTraceFilename ATTRIBUTE_UNUSED,
+ jint javaFd,
+ jint bufferSize,
+ jint flags,
+ jboolean samplingEnabled,
+ jint intervalUs,
jboolean streamingOutput) {
int originalFd = javaFd;
if (originalFd < 0) {
+ ScopedObjectAccess soa(env);
+ soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
+ "Trace fd is invalid: %d",
+ originalFd);
return;
}
@@ -107,18 +117,20 @@ static void VMDebug_startMethodTracingFd(JNIEnv* env, jclass, jstring javaTraceF
if (fd < 0) {
ScopedObjectAccess soa(env);
soa.Self()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
- "dup(%d) failed: %s", originalFd, strerror(errno));
+ "dup(%d) failed: %s",
+ originalFd,
+ strerror(errno));
return;
}
- ScopedUtfChars traceFilename(env, javaTraceFilename);
- if (traceFilename.c_str() == nullptr) {
- return;
- }
+ // Ignore the traceFilename.
Trace::TraceOutputMode outputMode = streamingOutput
? Trace::TraceOutputMode::kStreaming
: Trace::TraceOutputMode::kFile;
- Trace::Start(traceFilename.c_str(), fd, bufferSize, flags, outputMode,
+ Trace::Start(fd,
+ bufferSize,
+ flags,
+ outputMode,
samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
intervalUs);
}
@@ -130,7 +142,10 @@ static void VMDebug_startMethodTracingFilename(JNIEnv* env, jclass, jstring java
if (traceFilename.c_str() == nullptr) {
return;
}
- Trace::Start(traceFilename.c_str(), -1, bufferSize, flags, Trace::TraceOutputMode::kFile,
+ Trace::Start(traceFilename.c_str(),
+ bufferSize,
+ flags,
+ Trace::TraceOutputMode::kFile,
samplingEnabled ? Trace::TraceMode::kSampling : Trace::TraceMode::kMethodTracing,
intervalUs);
}
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index cbc2aeb41f..d9a5096331 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -343,7 +343,6 @@ static void ZygoteHooks_nativePostForkChild(JNIEnv* env,
std::string trace_file = StringPrintf("/data/misc/trace/%s.trace.bin", proc_name.c_str());
Trace::Start(trace_file.c_str(),
- -1,
buffer_size,
0, // TODO: Expose flags.
output_mode,
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 53982ae833..9a626bab00 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -839,7 +839,6 @@ bool Runtime::Start() {
if (trace_config_.get() != nullptr && trace_config_->trace_file != "") {
ScopedThreadStateChange tsc(self, kWaitingForMethodTracingStart);
Trace::Start(trace_config_->trace_file.c_str(),
- -1,
static_cast<int>(trace_config_->trace_file_size),
0,
trace_config_->trace_output_mode,
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 0f321b6591..91d2b3779e 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -319,8 +319,74 @@ void* Trace::RunSamplingThread(void* arg) {
return nullptr;
}
-void Trace::Start(const char* trace_filename, int trace_fd, size_t buffer_size, int flags,
- TraceOutputMode output_mode, TraceMode trace_mode, int interval_us) {
+void Trace::Start(const char* trace_filename,
+ size_t buffer_size,
+ int flags,
+ TraceOutputMode output_mode,
+ TraceMode trace_mode,
+ int interval_us) {
+ std::unique_ptr<File> file(OS::CreateEmptyFileWriteOnly(trace_filename));
+ if (file == nullptr) {
+ std::string msg = android::base::StringPrintf("Unable to open trace file '%s'", trace_filename);
+ PLOG(ERROR) << msg;
+ ScopedObjectAccess soa(Thread::Current());
+ Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;", msg.c_str());
+ return;
+ }
+ Start(std::move(file), buffer_size, flags, output_mode, trace_mode, interval_us);
+}
+
+void Trace::Start(int trace_fd,
+ size_t buffer_size,
+ int flags,
+ TraceOutputMode output_mode,
+ TraceMode trace_mode,
+ int interval_us) {
+ if (trace_fd < 0) {
+ std::string msg = android::base::StringPrintf("Unable to start tracing with invalid fd %d",
+ trace_fd);
+ LOG(ERROR) << msg;
+ ScopedObjectAccess soa(Thread::Current());
+ Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;", msg.c_str());
+ return;
+ }
+ std::unique_ptr<File> file(new File(trace_fd, "tracefile"));
+ Start(std::move(file), buffer_size, flags, output_mode, trace_mode, interval_us);
+}
+
+void Trace::StartDDMS(size_t buffer_size,
+ int flags,
+ TraceMode trace_mode,
+ int interval_us) {
+ Start(std::unique_ptr<File>(),
+ buffer_size,
+ flags,
+ TraceOutputMode::kDDMS,
+ trace_mode,
+ interval_us);
+}
+
+void Trace::Start(std::unique_ptr<File>&& trace_file_in,
+ size_t buffer_size,
+ int flags,
+ TraceOutputMode output_mode,
+ TraceMode trace_mode,
+ int interval_us) {
+ // We own trace_file now and are responsible for closing it. To account for error situations, use
+ // a specialized unique_ptr to ensure we close it on the way out (if it hasn't been passed to a
+ // Trace instance).
+ auto deleter = [](File* file) {
+ if (file != nullptr) {
+ file->MarkUnchecked(); // Don't deal with flushing requirements.
+ int result ATTRIBUTE_UNUSED = file->Close();
+ delete file;
+ }
+ };
+ std::unique_ptr<File, decltype(deleter)> trace_file(trace_file_in.release(), deleter);
+ if (trace_file != nullptr) {
+ trace_file->DisableAutoClose();
+ }
+
Thread* self = Thread::Current();
{
MutexLock mu(self, *Locks::trace_lock_);
@@ -338,23 +404,6 @@ void Trace::Start(const char* trace_filename, int trace_fd, size_t buffer_size,
return;
}
- // Open trace file if not going directly to ddms.
- std::unique_ptr<File> trace_file;
- if (output_mode != TraceOutputMode::kDDMS) {
- if (trace_fd < 0) {
- trace_file.reset(OS::CreateEmptyFileWriteOnly(trace_filename));
- } else {
- trace_file.reset(new File(trace_fd, "tracefile"));
- trace_file->DisableAutoClose();
- }
- if (trace_file.get() == nullptr) {
- PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'";
- ScopedObjectAccess soa(self);
- ThrowRuntimeException("Unable to open trace file '%s'", trace_filename);
- return;
- }
- }
-
Runtime* runtime = Runtime::Current();
// Enable count of allocs if specified in the flags.
@@ -372,8 +421,7 @@ void Trace::Start(const char* trace_filename, int trace_fd, size_t buffer_size,
LOG(ERROR) << "Trace already in progress, ignoring this request";
} else {
enable_stats = (flags && kTraceCountAllocs) != 0;
- the_trace_ = new Trace(trace_file.release(), trace_filename, buffer_size, flags, output_mode,
- trace_mode);
+ the_trace_ = new Trace(trace_file.release(), buffer_size, flags, output_mode, trace_mode);
if (trace_mode == TraceMode::kSampling) {
CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, nullptr, &RunSamplingThread,
reinterpret_cast<void*>(interval_us)),
@@ -595,8 +643,11 @@ TracingMode Trace::GetMethodTracingMode() {
static constexpr size_t kMinBufSize = 18U; // Trace header is up to 18B.
-Trace::Trace(File* trace_file, const char* trace_name, size_t buffer_size, int flags,
- TraceOutputMode output_mode, TraceMode trace_mode)
+Trace::Trace(File* trace_file,
+ size_t buffer_size,
+ int flags,
+ TraceOutputMode output_mode,
+ TraceMode trace_mode)
: trace_file_(trace_file),
buf_(new uint8_t[std::max(kMinBufSize, buffer_size)]()),
flags_(flags), trace_output_mode_(output_mode), trace_mode_(trace_mode),
@@ -605,6 +656,8 @@ Trace::Trace(File* trace_file, const char* trace_name, size_t buffer_size, int f
start_time_(MicroTime()), clock_overhead_ns_(GetClockOverheadNanoSeconds()), cur_offset_(0),
overflow_(false), interval_us_(0), streaming_lock_(nullptr),
unique_methods_lock_(new Mutex("unique methods lock", kTracingUniqueMethodsLock)) {
+ CHECK(trace_file != nullptr || output_mode == TraceOutputMode::kDDMS);
+
uint16_t trace_version = GetTraceVersion(clock_source_);
if (output_mode == TraceOutputMode::kStreaming) {
trace_version |= 0xF0U;
@@ -625,7 +678,6 @@ Trace::Trace(File* trace_file, const char* trace_name, size_t buffer_size, int f
cur_offset_.StoreRelaxed(kTraceHeaderLength);
if (output_mode == TraceOutputMode::kStreaming) {
- streaming_file_name_ = trace_name;
streaming_lock_ = new Mutex("tracing lock", LockLevel::kTracingStreamingLock);
seen_threads_.reset(new ThreadIDBitSet());
}
diff --git a/runtime/trace.h b/runtime/trace.h
index 86b8d00d51..7171f759c9 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -33,6 +33,10 @@
#include "globals.h"
#include "instrumentation.h"
+namespace unix_file {
+class FdFile;
+} // namespace unix_file
+
namespace art {
class ArtField;
@@ -115,10 +119,37 @@ class Trace FINAL : public instrumentation::InstrumentationListener {
static void SetDefaultClockSource(TraceClockSource clock_source);
- static void Start(const char* trace_filename, int trace_fd, size_t buffer_size, int flags,
- TraceOutputMode output_mode, TraceMode trace_mode, int interval_us)
+ static void Start(const char* trace_filename,
+ size_t buffer_size,
+ int flags,
+ TraceOutputMode output_mode,
+ TraceMode trace_mode,
+ int interval_us)
+ REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
+ !Locks::trace_lock_);
+ static void Start(int trace_fd,
+ size_t buffer_size,
+ int flags,
+ TraceOutputMode output_mode,
+ TraceMode trace_mode,
+ int interval_us)
+ REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
+ !Locks::trace_lock_);
+ static void Start(std::unique_ptr<unix_file::FdFile>&& file,
+ size_t buffer_size,
+ int flags,
+ TraceOutputMode output_mode,
+ TraceMode trace_mode,
+ int interval_us)
+ REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
+ !Locks::trace_lock_);
+ static void StartDDMS(size_t buffer_size,
+ int flags,
+ TraceMode trace_mode,
+ int interval_us)
REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
!Locks::trace_lock_);
+
static void Pause() REQUIRES(!Locks::trace_lock_, !Locks::thread_list_lock_);
static void Resume() REQUIRES(!Locks::trace_lock_);
@@ -212,8 +243,11 @@ class Trace FINAL : public instrumentation::InstrumentationListener {
static bool IsTracingEnabled() REQUIRES(!Locks::trace_lock_);
private:
- Trace(File* trace_file, const char* trace_name, size_t buffer_size, int flags,
- TraceOutputMode output_mode, TraceMode trace_mode);
+ Trace(File* trace_file,
+ size_t buffer_size,
+ int flags,
+ TraceOutputMode output_mode,
+ TraceMode trace_mode);
// The sampling interval in microseconds is passed as an argument.
static void* RunSamplingThread(void* arg) REQUIRES(!Locks::trace_lock_);
@@ -318,7 +352,6 @@ class Trace FINAL : public instrumentation::InstrumentationListener {
int interval_us_;
// Streaming mode data.
- std::string streaming_file_name_;
Mutex* streaming_lock_;
std::map<const DexFile*, DexIndexBitSet*> seen_methods_;
std::unique_ptr<ThreadIDBitSet> seen_threads_;
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index b07001e595..cee717610d 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2765,47 +2765,61 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
break;
case Instruction::IGET_BOOLEAN:
+ case Instruction::IGET_BOOLEAN_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Boolean(), true, false);
break;
case Instruction::IGET_BYTE:
+ case Instruction::IGET_BYTE_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Byte(), true, false);
break;
case Instruction::IGET_CHAR:
+ case Instruction::IGET_CHAR_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Char(), true, false);
break;
case Instruction::IGET_SHORT:
+ case Instruction::IGET_SHORT_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Short(), true, false);
break;
case Instruction::IGET:
+ case Instruction::IGET_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Integer(), true, false);
break;
case Instruction::IGET_WIDE:
+ case Instruction::IGET_WIDE_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.LongLo(), true, false);
break;
case Instruction::IGET_OBJECT:
+ case Instruction::IGET_OBJECT_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.JavaLangObject(false), false,
false);
break;
case Instruction::IPUT_BOOLEAN:
+ case Instruction::IPUT_BOOLEAN_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Boolean(), true, false);
break;
case Instruction::IPUT_BYTE:
+ case Instruction::IPUT_BYTE_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Byte(), true, false);
break;
case Instruction::IPUT_CHAR:
+ case Instruction::IPUT_CHAR_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Char(), true, false);
break;
case Instruction::IPUT_SHORT:
+ case Instruction::IPUT_SHORT_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Short(), true, false);
break;
case Instruction::IPUT:
+ case Instruction::IPUT_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Integer(), true, false);
break;
case Instruction::IPUT_WIDE:
+ case Instruction::IPUT_WIDE_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.LongLo(), true, false);
break;
case Instruction::IPUT_OBJECT:
+ case Instruction::IPUT_OBJECT_QUICK:
VerifyISFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.JavaLangObject(false), false,
false);
break;
@@ -2859,9 +2873,12 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
case Instruction::INVOKE_VIRTUAL:
case Instruction::INVOKE_VIRTUAL_RANGE:
case Instruction::INVOKE_SUPER:
- case Instruction::INVOKE_SUPER_RANGE: {
+ case Instruction::INVOKE_SUPER_RANGE:
+ case Instruction::INVOKE_VIRTUAL_QUICK:
+ case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE ||
- inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
+ inst->Opcode() == Instruction::INVOKE_SUPER_RANGE ||
+ inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
bool is_super = (inst->Opcode() == Instruction::INVOKE_SUPER ||
inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
MethodType type = is_super ? METHOD_SUPER : METHOD_VIRTUAL;
@@ -2881,7 +2898,7 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
}
}
if (return_type == nullptr) {
- uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
+ uint32_t method_idx = GetMethodIdxOfInvoke(inst);
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
dex::TypeIndex return_type_idx =
dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
@@ -3368,67 +3385,6 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
}
}
break;
- // Note: the following instructions encode offsets derived from class linking.
- // As such they use Class*/Field*/Executable* as these offsets only have
- // meaning if the class linking and resolution were successful.
- case Instruction::IGET_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Integer(), true);
- break;
- case Instruction::IGET_WIDE_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.LongLo(), true);
- break;
- case Instruction::IGET_OBJECT_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.JavaLangObject(false), false);
- break;
- case Instruction::IGET_BOOLEAN_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Boolean(), true);
- break;
- case Instruction::IGET_BYTE_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Byte(), true);
- break;
- case Instruction::IGET_CHAR_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Char(), true);
- break;
- case Instruction::IGET_SHORT_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Short(), true);
- break;
- case Instruction::IPUT_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Integer(), true);
- break;
- case Instruction::IPUT_BOOLEAN_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Boolean(), true);
- break;
- case Instruction::IPUT_BYTE_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Byte(), true);
- break;
- case Instruction::IPUT_CHAR_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Char(), true);
- break;
- case Instruction::IPUT_SHORT_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.Short(), true);
- break;
- case Instruction::IPUT_WIDE_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.LongLo(), true);
- break;
- case Instruction::IPUT_OBJECT_QUICK:
- VerifyQuickFieldAccess<FieldAccessType::kAccPut>(inst, reg_types_.JavaLangObject(false), false);
- break;
- case Instruction::INVOKE_VIRTUAL_QUICK:
- case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
- bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
- ArtMethod* called_method = VerifyInvokeVirtualQuickArgs(inst, is_range);
- if (called_method != nullptr) {
- const char* descriptor = called_method->GetReturnTypeDescriptor();
- const RegType& return_type = reg_types_.FromDescriptor(GetClassLoader(), descriptor, false);
- if (!return_type.IsLowHalf()) {
- work_line_->SetResultRegisterType(this, return_type);
- } else {
- work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
- }
- just_set_result = true;
- }
- break;
- }
/* These should never appear during verification. */
case Instruction::UNUSED_3E ... Instruction::UNUSED_43:
@@ -3995,7 +3951,7 @@ ArtMethod* MethodVerifier::VerifyInvocationArgsFromIterator(
}
} else {
// Check whether the name of the called method is "<init>"
- const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
+ const uint32_t method_idx = GetMethodIdxOfInvoke(inst);
if (strcmp(dex_file_->GetMethodName(dex_file_->GetMethodId(method_idx)), "<init>") != 0) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "'this' arg must be initialized";
return nullptr;
@@ -4017,7 +3973,7 @@ ArtMethod* MethodVerifier::VerifyInvocationArgsFromIterator(
res_method_class = &FromClass(klass->GetDescriptor(&temp), klass,
klass->CannotBeAssignedFromOtherTypes());
} else {
- const uint32_t method_idx = inst->VRegB();
+ const uint32_t method_idx = GetMethodIdxOfInvoke(inst);
const dex::TypeIndex class_idx = dex_file_->GetMethodId(method_idx).class_idx_;
res_method_class = &reg_types_.FromDescriptor(
GetClassLoader(),
@@ -4108,7 +4064,7 @@ void MethodVerifier::VerifyInvocationArgsUnresolvedMethod(const Instruction* ins
// As the method may not have been resolved, make this static check against what we expect.
// The main reason for this code block is to fail hard when we find an illegal use, e.g.,
// wrong number of arguments or wrong primitive types, even if the method could not be resolved.
- const uint32_t method_idx = inst->VRegB();
+ const uint32_t method_idx = GetMethodIdxOfInvoke(inst);
DexFileParameterIterator it(*dex_file_,
dex_file_->GetProtoId(dex_file_->GetMethodId(method_idx).proto_idx_));
VerifyInvocationArgsFromIterator(&it, inst, method_type, is_range, nullptr);
@@ -4181,7 +4137,7 @@ ArtMethod* MethodVerifier::VerifyInvocationArgs(
const Instruction* inst, MethodType method_type, bool is_range) {
// Resolve the method. This could be an abstract or concrete method depending on what sort of call
// we're making.
- const uint32_t method_idx = inst->VRegB();
+ const uint32_t method_idx = GetMethodIdxOfInvoke(inst);
ArtMethod* res_method = ResolveMethodAndCheckAccess(method_idx, method_type);
if (res_method == nullptr) { // error or class is unresolved
// Check what we can statically.
@@ -4334,122 +4290,34 @@ bool MethodVerifier::CheckSignaturePolymorphicReceiver(const Instruction* inst)
return true;
}
-ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst, bool is_range) {
- if (is_range) {
- DCHECK_EQ(inst->Opcode(), Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
- } else {
- DCHECK_EQ(inst->Opcode(), Instruction::INVOKE_VIRTUAL_QUICK);
- }
-
- DCHECK(method_being_verified_ != nullptr);
- uint16_t method_idx = method_being_verified_->GetIndexFromQuickening(work_insn_idx_);
- CHECK_NE(method_idx, DexFile::kDexNoIndex16);
- return ResolveMethodAndCheckAccess(method_idx, METHOD_VIRTUAL);
-}
-
-ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instruction* inst, bool is_range) {
- DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_)
- << dex_file_->PrettyMethod(dex_method_idx_, true) << "@" << work_insn_idx_;
-
- ArtMethod* res_method = GetQuickInvokedMethod(inst, is_range);
- if (res_method == nullptr) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer method from " << inst->Name();
- return nullptr;
- }
- if (FailOrAbort(!res_method->IsDirect(),
- "Quick-invoked method is direct at ",
- work_insn_idx_)) {
- return nullptr;
- }
- if (FailOrAbort(!res_method->IsStatic(),
- "Quick-invoked method is static at ",
- work_insn_idx_)) {
- return nullptr;
- }
-
- // We use vAA as our expected arg count, rather than res_method->insSize, because we need to
- // match the call to the signature. Also, we might be calling through an abstract method
- // definition (which doesn't have register count values).
- const RegType& actual_arg_type = work_line_->GetInvocationThis(this, inst);
- if (actual_arg_type.IsConflict()) { // GetInvocationThis failed.
- return nullptr;
- }
- const size_t expected_args = (is_range) ? inst->VRegA_3rc() : inst->VRegA_35c();
- /* caught by static verifier */
- DCHECK(is_range || expected_args <= 5);
- if (expected_args > code_item_accessor_.OutsSize()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid argument count (" << expected_args
- << ") exceeds outsSize (" << code_item_accessor_.OutsSize() << ")";
- return nullptr;
- }
-
- /*
- * Check the "this" argument, which must be an instance of the class that declared the method.
- * For an interface class, we don't do the full interface merge (see JoinClass), so we can't do a
- * rigorous check here (which is okay since we have to do it at runtime).
- */
- // Note: given an uninitialized type, this should always fail. Constructors aren't virtual.
- if (actual_arg_type.IsUninitializedTypes() && !res_method->IsConstructor()) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "'this' arg must be initialized";
- return nullptr;
- }
- if (!actual_arg_type.IsZeroOrNull()) {
- mirror::Class* klass = res_method->GetDeclaringClass();
- std::string temp;
- const RegType& res_method_class =
- FromClass(klass->GetDescriptor(&temp), klass, klass->CannotBeAssignedFromOtherTypes());
- if (!res_method_class.IsAssignableFrom(actual_arg_type, this)) {
- Fail(actual_arg_type.IsUninitializedTypes() // Just overcautious - should have never
- ? VERIFY_ERROR_BAD_CLASS_HARD // quickened this.
- : actual_arg_type.IsUnresolvedTypes()
- ? VERIFY_ERROR_NO_CLASS
- : VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
- << "' not instance of '" << res_method_class << "'";
- return nullptr;
- }
- }
- /*
- * Process the target method's signature. This signature may or may not
- * have been verified, so we can't assume it's properly formed.
- */
- const DexFile::TypeList* params = res_method->GetParameterTypeList();
- size_t params_size = params == nullptr ? 0 : params->Size();
- uint32_t arg[5];
- if (!is_range) {
- inst->GetVarArgs(arg);
- }
- size_t actual_args = 1;
- for (size_t param_index = 0; param_index < params_size; param_index++) {
- if (actual_args >= expected_args) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invalid call to '"
- << res_method->PrettyMethod()
- << "'. Expected " << expected_args
- << " arguments, processing argument " << actual_args
- << " (where longs/doubles count twice).";
- return nullptr;
- }
- const char* descriptor =
- res_method->GetTypeDescriptorFromTypeIdx(params->GetTypeItem(param_index).type_idx_);
- if (descriptor == nullptr) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation of "
- << res_method->PrettyMethod()
- << " missing signature component";
- return nullptr;
+uint16_t MethodVerifier::GetMethodIdxOfInvoke(const Instruction* inst) {
+ switch (inst->Opcode()) {
+ case Instruction::INVOKE_VIRTUAL_RANGE_QUICK:
+ case Instruction::INVOKE_VIRTUAL_QUICK: {
+ DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_)
+ << dex_file_->PrettyMethod(dex_method_idx_, true) << "@" << work_insn_idx_;
+ DCHECK(method_being_verified_ != nullptr);
+ uint16_t method_idx = method_being_verified_->GetIndexFromQuickening(work_insn_idx_);
+ CHECK_NE(method_idx, DexFile::kDexNoIndex16);
+ return method_idx;
}
- const RegType& reg_type = reg_types_.FromDescriptor(GetClassLoader(), descriptor, false);
- uint32_t get_reg = is_range ? inst->VRegC_3rc() + actual_args : arg[actual_args];
- if (!work_line_->VerifyRegisterType(this, get_reg, reg_type)) {
- return res_method;
+ default: {
+ return inst->VRegB();
}
- actual_args = reg_type.IsLongOrDoubleTypes() ? actual_args + 2 : actual_args + 1;
}
- if (actual_args != expected_args) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation of "
- << res_method->PrettyMethod() << " expected "
- << expected_args << " arguments, found " << actual_args;
- return nullptr;
+}
+
+uint16_t MethodVerifier::GetFieldIdxOfFieldAccess(const Instruction* inst, bool is_static) {
+ if (is_static) {
+ return inst->VRegB_21c();
+ } else if (inst->IsQuickened()) {
+ DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_);
+ DCHECK(method_being_verified_ != nullptr);
+ uint16_t field_idx = method_being_verified_->GetIndexFromQuickening(work_insn_idx_);
+ CHECK_NE(field_idx, DexFile::kDexNoIndex16);
+ return field_idx;
} else {
- return res_method;
+ return inst->VRegC_22c();
}
}
@@ -4819,7 +4687,7 @@ ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_id
template <MethodVerifier::FieldAccessType kAccType>
void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType& insn_type,
bool is_primitive, bool is_static) {
- uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
+ uint32_t field_idx = GetFieldIdxOfFieldAccess(inst, is_static);
ArtField* field;
if (is_static) {
field = GetStaticField(field_idx);
@@ -4972,151 +4840,6 @@ void MethodVerifier::VerifyISFieldAccess(const Instruction* inst, const RegType&
}
}
-ArtField* MethodVerifier::GetQuickAccessedField() {
- DCHECK(method_being_verified_ != nullptr);
- uint16_t field_idx = method_being_verified_->GetIndexFromQuickening(work_insn_idx_);
- CHECK_NE(field_idx, DexFile::kDexNoIndex16);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ArtField* field = class_linker->ResolveFieldJLS(field_idx, dex_cache_, class_loader_);
- if (field == nullptr) {
- DCHECK(self_->IsExceptionPending());
- self_->ClearException();
- }
- return field;
-}
-
-template <MethodVerifier::FieldAccessType kAccType>
-void MethodVerifier::VerifyQuickFieldAccess(const Instruction* inst, const RegType& insn_type,
- bool is_primitive) {
- DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_);
-
- ArtField* field = GetQuickAccessedField();
- if (field == nullptr) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer field from " << inst->Name();
- return;
- }
-
- // For an IPUT_QUICK, we now test for final flag of the field.
- if (kAccType == FieldAccessType::kAccPut) {
- if (field->IsFinal() && field->GetDeclaringClass() != GetDeclaringClass().GetClass()) {
- Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << field->PrettyField()
- << " from other class " << GetDeclaringClass();
- return;
- }
- }
-
- // Get the field type.
- const RegType* field_type;
- {
- ObjPtr<mirror::Class> field_type_class =
- can_load_classes_ ? field->ResolveType() : field->LookupResolvedType();
-
- if (field_type_class != nullptr) {
- field_type = &FromClass(field->GetTypeDescriptor(),
- field_type_class.Ptr(),
- field_type_class->CannotBeAssignedFromOtherTypes());
- } else {
- Thread* self = Thread::Current();
- DCHECK(!can_load_classes_ || self->IsExceptionPending());
- self->ClearException();
- field_type = &reg_types_.FromDescriptor(field->GetDeclaringClass()->GetClassLoader(),
- field->GetTypeDescriptor(),
- false);
- }
- if (field_type == nullptr) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer field type from " << inst->Name();
- return;
- }
- }
-
- const uint32_t vregA = inst->VRegA_22c();
- static_assert(kAccType == FieldAccessType::kAccPut || kAccType == FieldAccessType::kAccGet,
- "Unexpected third access type");
- if (kAccType == FieldAccessType::kAccPut) {
- if (is_primitive) {
- // Primitive field assignability rules are weaker than regular assignability rules
- bool instruction_compatible;
- bool value_compatible;
- const RegType& value_type = work_line_->GetRegisterType(this, vregA);
- if (field_type->IsIntegralTypes()) {
- instruction_compatible = insn_type.IsIntegralTypes();
- value_compatible = value_type.IsIntegralTypes();
- } else if (field_type->IsFloat()) {
- instruction_compatible = insn_type.IsInteger(); // no [is]put-float, so expect [is]put-int
- value_compatible = value_type.IsFloatTypes();
- } else if (field_type->IsLong()) {
- instruction_compatible = insn_type.IsLong();
- value_compatible = value_type.IsLongTypes();
- } else if (field_type->IsDouble()) {
- instruction_compatible = insn_type.IsLong(); // no [is]put-double, so expect [is]put-long
- value_compatible = value_type.IsDoubleTypes();
- } else {
- instruction_compatible = false; // reference field with primitive store
- value_compatible = false; // unused
- }
- if (!instruction_compatible) {
- // This is a global failure rather than a class change failure as the instructions and
- // the descriptors for the type should have been consistent within the same file at
- // compile time
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected field " << ArtField::PrettyField(field)
- << " to be of type '" << insn_type
- << "' but found type '" << *field_type
- << "' in put";
- return;
- }
- if (!value_compatible) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected value in v" << vregA
- << " of type " << value_type
- << " but expected " << *field_type
- << " for store to " << ArtField::PrettyField(field) << " in put";
- return;
- }
- } else {
- if (!insn_type.IsAssignableFrom(*field_type, this)) {
- Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << ArtField::PrettyField(field)
- << " to be compatible with type '" << insn_type
- << "' but found type '" << *field_type
- << "' in put-object";
- return;
- }
- work_line_->VerifyRegisterType(this, vregA, *field_type);
- }
- } else if (kAccType == FieldAccessType::kAccGet) {
- if (is_primitive) {
- if (field_type->Equals(insn_type) ||
- (field_type->IsFloat() && insn_type.IsIntegralTypes()) ||
- (field_type->IsDouble() && insn_type.IsLongTypes())) {
- // expected that read is of the correct primitive type or that int reads are reading
- // floats or long reads are reading doubles
- } else {
- // This is a global failure rather than a class change failure as the instructions and
- // the descriptors for the type should have been consistent within the same file at
- // compile time
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected field " << ArtField::PrettyField(field)
- << " to be of type '" << insn_type
- << "' but found type '" << *field_type << "' in Get";
- return;
- }
- } else {
- if (!insn_type.IsAssignableFrom(*field_type, this)) {
- Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << ArtField::PrettyField(field)
- << " to be compatible with type '" << insn_type
- << "' but found type '" << *field_type
- << "' in get-object";
- work_line_->SetRegisterType<LockOp::kClear>(this, vregA, reg_types_.Conflict());
- return;
- }
- }
- if (!field_type->IsLowHalf()) {
- work_line_->SetRegisterType<LockOp::kClear>(this, vregA, *field_type);
- } else {
- work_line_->SetRegisterTypeWide(this, vregA, *field_type, field_type->HighHalf(&reg_types_));
- }
- } else {
- LOG(FATAL) << "Unexpected case.";
- }
-}
-
bool MethodVerifier::CheckNotMoveException(const uint16_t* insns, int insn_idx) {
if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid use of move-exception";
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 9237a8b44b..531d3dabfa 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -209,12 +209,12 @@ class MethodVerifier {
const RegType& ResolveCheckedClass(dex::TypeIndex class_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Returns the method of a quick invoke or null if it cannot be found.
- ArtMethod* GetQuickInvokedMethod(const Instruction* inst, bool is_range)
+ // Returns the method index of an invoke instruction.
+ uint16_t GetMethodIdxOfInvoke(const Instruction* inst)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ // Returns the field index of a field access instruction.
+ uint16_t GetFieldIdxOfFieldAccess(const Instruction* inst, bool is_static)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Returns the access field of a quick field access (iget/iput-quick) or null
- // if it cannot be found.
- ArtField* GetQuickAccessedField() REQUIRES_SHARED(Locks::mutator_lock_);
uint32_t GetEncounteredFailureTypes() {
return encountered_failure_types_;
@@ -575,10 +575,6 @@ class MethodVerifier {
bool is_primitive, bool is_static)
REQUIRES_SHARED(Locks::mutator_lock_);
- template <FieldAccessType kAccType>
- void VerifyQuickFieldAccess(const Instruction* inst, const RegType& insn_type, bool is_primitive)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
enum class CheckAccess { // private.
kYes,
kNo,
@@ -642,9 +638,6 @@ class MethodVerifier {
ArtMethod* res_method)
REQUIRES_SHARED(Locks::mutator_lock_);
- ArtMethod* VerifyInvokeVirtualQuickArgs(const Instruction* inst, bool is_range)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
/*
* Verify the arguments present for a call site. Returns "true" if all is well, "false" otherwise.
*/
diff --git a/test/121-modifiers/classes/A$B.class b/test/121-modifiers/classes/A$B.class
deleted file mode 100644
index bd7ebfe11d..0000000000
--- a/test/121-modifiers/classes/A$B.class
+++ /dev/null
Binary files differ
diff --git a/test/121-modifiers/classes/A$C.class b/test/121-modifiers/classes/A$C.class
deleted file mode 100644
index 3ae872e356..0000000000
--- a/test/121-modifiers/classes/A$C.class
+++ /dev/null
Binary files differ
diff --git a/test/121-modifiers/classes/A.class b/test/121-modifiers/classes/A.class
deleted file mode 100644
index d89d029796..0000000000
--- a/test/121-modifiers/classes/A.class
+++ /dev/null
Binary files differ
diff --git a/test/121-modifiers/classes/Inf.class b/test/121-modifiers/classes/Inf.class
deleted file mode 100644
index e8dd68029d..0000000000
--- a/test/121-modifiers/classes/Inf.class
+++ /dev/null
Binary files differ
diff --git a/test/121-modifiers/classes/Main.class b/test/121-modifiers/classes/Main.class
deleted file mode 100644
index e044074269..0000000000
--- a/test/121-modifiers/classes/Main.class
+++ /dev/null
Binary files differ
diff --git a/test/121-modifiers/classes/NonInf.class b/test/121-modifiers/classes/NonInf.class
deleted file mode 100644
index 0f1e826fb7..0000000000
--- a/test/121-modifiers/classes/NonInf.class
+++ /dev/null
Binary files differ
diff --git a/test/121-modifiers/info.txt b/test/121-modifiers/info.txt
index 335df53f3d..7dba1133d1 100644
--- a/test/121-modifiers/info.txt
+++ b/test/121-modifiers/info.txt
@@ -10,9 +10,9 @@ Finally, compile with jack/jill or dx, and run baksmali.
javac Inf.java NonInf.java Main.java
javac -cp asm.jar:asm-tree.jar:. Asm.java
java -cp asm.jar:asm-tree.jar:. Asm
-mv Inf.out classes/Inf.class
-mv NonInf.out classes/NonInf.class
-mv Main.class A.class A\$B.class A\$C.class classes/
+mv Inf.out classes_tmp/Inf.class
+mv NonInf.out classes_tmp/NonInf.class
+mv Main.class A.class A\$B.class A\$C.class classes_tmp/
dx --debug --dex --output=classes.dex classes
baksmali disassemble classes.dex
mv out/*.smali smali/
diff --git a/test/161-final-abstract-class/smali/Main.smali b/test/161-final-abstract-class/smali/Main.smali
new file mode 100644
index 0000000000..588854cf52
--- /dev/null
+++ b/test/161-final-abstract-class/smali/Main.smali
@@ -0,0 +1,214 @@
+# Created with baksmali.
+
+# Java file for reference.
+
+# import java.lang.reflect.InvocationTargetException;
+# import java.lang.reflect.Method;
+#
+# public class Main {
+# public static void main(String[] args) {
+# try {
+# // Make sure that the abstract final class is marked as erroneous.
+# Class.forName("AbstractFinal");
+# System.out.println("UNREACHABLE!");
+# } catch (VerifyError expected) {
+# } catch (Throwable t) {
+# t.printStackTrace(System.out);
+# }
+# try {
+# // Verification of TestClass.test() used to crash when processing
+# // the final abstract (erroneous) class.
+# Class<?> tc = Class.forName("TestClass");
+# Method test = tc.getDeclaredMethod("test");
+# test.invoke(null);
+# System.out.println("UNREACHABLE!");
+# } catch (InvocationTargetException ite) {
+# if (ite.getCause() instanceof InstantiationError) {
+# System.out.println(
+# ite.getCause().getClass().getName() + ": " + ite.getCause().getMessage());
+# } else {
+# ite.printStackTrace(System.out);
+# }
+# } catch (Throwable t) {
+# t.printStackTrace(System.out);
+# }
+# }
+# }
+
+.class public LMain;
+.super Ljava/lang/Object;
+.source "Main.java"
+
+
+# direct methods
+.method public constructor <init>()V
+ .registers 1
+
+ .line 20
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+
+ return-void
+.end method
+
+.method public static main([Ljava/lang/String;)V
+ .registers 4
+
+ .line 24
+ :try_start_0
+ const-string p0, "AbstractFinal"
+
+ invoke-static {p0}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class;
+
+ .line 25
+ sget-object p0, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ const-string v0, "UNREACHABLE!"
+
+ invoke-virtual {p0, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
+ :try_end_c
+ .catch Ljava/lang/VerifyError; {:try_start_0 .. :try_end_c} :catch_14
+ .catch Ljava/lang/Throwable; {:try_start_0 .. :try_end_c} :catch_d
+
+ goto :goto_15
+
+ .line 27
+ :catch_d
+ move-exception p0
+
+ .line 28
+ sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ invoke-virtual {p0, v0}, Ljava/lang/Throwable;->printStackTrace(Ljava/io/PrintStream;)V
+
+ goto :goto_16
+
+ .line 26
+ :catch_14
+ move-exception p0
+
+ .line 29
+ :goto_15
+ nop
+
+ .line 33
+ :goto_16
+ :try_start_16
+ const-string p0, "TestClass"
+
+ invoke-static {p0}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class;
+
+ move-result-object p0
+
+ .line 34
+ const-string v0, "test"
+
+ const/4 v1, 0x0
+
+ new-array v2, v1, [Ljava/lang/Class;
+
+ invoke-virtual {p0, v0, v2}, Ljava/lang/Class;->getDeclaredMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
+
+ move-result-object p0
+
+ .line 35
+ const/4 v0, 0x0
+
+ new-array v1, v1, [Ljava/lang/Object;
+
+ invoke-virtual {p0, v0, v1}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
+
+ .line 36
+ sget-object p0, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ const-string v0, "UNREACHABLE!"
+
+ invoke-virtual {p0, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
+ :try_end_32
+ .catch Ljava/lang/reflect/InvocationTargetException; {:try_start_16 .. :try_end_32} :catch_3a
+ .catch Ljava/lang/Throwable; {:try_start_16 .. :try_end_32} :catch_33
+
+ goto :goto_76
+
+ .line 44
+ :catch_33
+ move-exception p0
+
+ .line 45
+ sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ invoke-virtual {p0, v0}, Ljava/lang/Throwable;->printStackTrace(Ljava/io/PrintStream;)V
+
+ goto :goto_77
+
+ .line 37
+ :catch_3a
+ move-exception p0
+
+ .line 38
+ invoke-virtual {p0}, Ljava/lang/reflect/InvocationTargetException;->getCause()Ljava/lang/Throwable;
+
+ move-result-object v0
+
+ instance-of v0, v0, Ljava/lang/InstantiationError;
+
+ if-eqz v0, :cond_71
+
+ .line 39
+ sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ new-instance v1, Ljava/lang/StringBuilder;
+
+ invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
+
+ .line 40
+ invoke-virtual {p0}, Ljava/lang/reflect/InvocationTargetException;->getCause()Ljava/lang/Throwable;
+
+ move-result-object v2
+
+ invoke-virtual {v2}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
+
+ move-result-object v2
+
+ invoke-virtual {v2}, Ljava/lang/Class;->getName()Ljava/lang/String;
+
+ move-result-object v2
+
+ invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+ const-string v2, ": "
+
+ invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+ invoke-virtual {p0}, Ljava/lang/reflect/InvocationTargetException;->getCause()Ljava/lang/Throwable;
+
+ move-result-object p0
+
+ invoke-virtual {p0}, Ljava/lang/Throwable;->getMessage()Ljava/lang/String;
+
+ move-result-object p0
+
+ invoke-virtual {v1, p0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
+
+ invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
+
+ move-result-object p0
+
+ .line 39
+ invoke-virtual {v0, p0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
+
+ goto :goto_76
+
+ .line 42
+ :cond_71
+ sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ invoke-virtual {p0, v0}, Ljava/lang/reflect/InvocationTargetException;->printStackTrace(Ljava/io/PrintStream;)V
+
+ .line 46
+ :goto_76
+ nop
+
+ .line 47
+ :goto_77
+ return-void
+.end method
diff --git a/test/161-final-abstract-class/src/Main.java b/test/161-final-abstract-class/src/Main.java
deleted file mode 100644
index 2452490226..0000000000
--- a/test/161-final-abstract-class/src/Main.java
+++ /dev/null
@@ -1,48 +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.InvocationTargetException;
-import java.lang.reflect.Method;
-
-public class Main {
- public static void main(String[] args) {
- try {
- // Make sure that the abstract final class is marked as erroneous.
- Class.forName("AbstractFinal");
- System.out.println("UNREACHABLE!");
- } catch (VerifyError expected) {
- } catch (Throwable t) {
- t.printStackTrace(System.out);
- }
- try {
- // Verification of TestClass.test() used to crash when processing
- // the final abstract (erroneous) class.
- Class<?> tc = Class.forName("TestClass");
- Method test = tc.getDeclaredMethod("test");
- test.invoke(null);
- System.out.println("UNREACHABLE!");
- } catch (InvocationTargetException ite) {
- if (ite.getCause() instanceof InstantiationError) {
- System.out.println(
- ite.getCause().getClass().getName() + ": " + ite.getCause().getMessage());
- } else {
- ite.printStackTrace(System.out);
- }
- } catch (Throwable t) {
- t.printStackTrace(System.out);
- }
- }
-}
diff --git a/test/1929-exception-catch-exception/expected.txt b/test/1929-exception-catch-exception/expected.txt
index bc5608ac4e..a82b732eda 100644
--- a/test/1929-exception-catch-exception/expected.txt
+++ b/test/1929-exception-catch-exception/expected.txt
@@ -1,11 +1,11 @@
Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$DoNothingHandler"
-main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 298 caught class art.Test1929$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 298
Test "art.Test1929$DoThrowClass": Caught error art.Test1929$TestException:"doThrow" with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowClass": Finished running with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handler "art.Test1929$DoNothingHandler"
@@ -17,71 +17,71 @@ main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchBaseTestException() @ line = 140
public void art.Test1929$DoThrowCatchBaseTestException.run() @ line = 149
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Doing nothing!
Caught art.Test1929$TestException: "throwCatchBaseTestException"
Test "art.Test1929$DoThrowCatchBaseTestException": No error caught with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchBaseTestException": Finished running with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with handler "art.Test1929$DoNothingHandler"
-main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
+main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 157 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
- public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 197
- public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 201
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 157
+ public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 203
+ public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 210
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Caught art.Test1929$TestException: "throwCatchBaseTestExceptionTwice"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": No error caught with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Finished running with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "art.Test1929$DoNothingHandler"
-main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
+main: public static void art.Test1929.throwCatchTestException() @ line = 216 caught class art.Test1929$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.throwCatchTestException() @ line = 207
- public void art.Test1929$DoThrowCatchTestException.run() @ line = 216
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929.throwCatchTestException() @ line = 216
+ public void art.Test1929$DoThrowCatchTestException.run() @ line = 225
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Doing nothing!
Caught art.Test1929$TestException: "throwCatchTestException"
Test "art.Test1929$DoThrowCatchTestException": No error caught with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchTestException": Finished running with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with handler "art.Test1929$DoNothingHandler"
-main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
+main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 175 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
- public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 222
- public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 226
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 175
+ public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 234
+ public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 241
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Caught art.Test1929$TestException: "throwCatchTestExceptionTwice"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": No error caught with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": Finished running with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with handler "art.Test1929$DoNothingHandler"
-main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 298 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 298
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1929$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1929$DoNothingHandler"
Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
-main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 298 caught class art.Test1929$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 298
Test "art.Test1929$DoThrowClass": Caught error art.Test1929$TestException:"doThrow" with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowClass": Finished running with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
@@ -93,73 +93,73 @@ main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchBaseTestException() @ line = 140
public void art.Test1929$DoThrowCatchBaseTestException.run() @ line = 149
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Throwing BaseTestException and catching it!
Caught art.Test1929$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1929.throwCatchBaseTestException() @ line = 140"
Caught art.Test1929$TestException: "throwCatchBaseTestException"
Test "art.Test1929$DoThrowCatchBaseTestException": No error caught with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchBaseTestException": Finished running with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
-main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
+main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 157 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
- public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 197
- public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 201
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 157
+ public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 203
+ public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 210
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Caught art.Test1929$TestException: "throwCatchBaseTestExceptionTwice"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": No error caught with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Finished running with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
-main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
+main: public static void art.Test1929.throwCatchTestException() @ line = 216 caught class art.Test1929$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.throwCatchTestException() @ line = 207
- public void art.Test1929$DoThrowCatchTestException.run() @ line = 216
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929.throwCatchTestException() @ line = 216
+ public void art.Test1929$DoThrowCatchTestException.run() @ line = 225
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Throwing BaseTestException and catching it!
-Caught art.Test1929$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1929.throwCatchTestException() @ line = 207"
+Caught art.Test1929$BaseTestException: "ThrowBaseHandler during throw from public static void art.Test1929.throwCatchTestException() @ line = 216"
Caught art.Test1929$TestException: "throwCatchTestException"
Test "art.Test1929$DoThrowCatchTestException": No error caught with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchTestException": Finished running with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
-main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
+main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 175 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
- public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 222
- public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 226
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 175
+ public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 234
+ public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 241
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Caught art.Test1929$TestException: "throwCatchTestExceptionTwice"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": No error caught with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": Finished running with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with handler "art.Test1929$ThrowCatchBase"
-main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 298 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 298
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1929$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1929$ThrowCatchBase"
Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
-main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 298 caught class art.Test1929$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 298
Test "art.Test1929$DoThrowClass": Caught error art.Test1929$TestException:"doThrow" with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowClass": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
@@ -171,69 +171,69 @@ main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchBaseTestException() @ line = 140
public void art.Test1929$DoThrowCatchBaseTestException.run() @ line = 149
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Throwing BaseTestException!
Test "art.Test1929$DoThrowCatchBaseTestException": Caught error art.Test1929$BaseTestException:"ThrowBaseHandler during throw from public static void art.Test1929.throwCatchBaseTestException() @ line = 140" with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchBaseTestException": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
-main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
+main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 157 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
- public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 197
- public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 201
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 157
+ public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 203
+ public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 210
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Caught art.Test1929$TestException: "throwCatchBaseTestExceptionTwice"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": No error caught with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
-main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
+main: public static void art.Test1929.throwCatchTestException() @ line = 216 caught class art.Test1929$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.throwCatchTestException() @ line = 207
- public void art.Test1929$DoThrowCatchTestException.run() @ line = 216
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929.throwCatchTestException() @ line = 216
+ public void art.Test1929$DoThrowCatchTestException.run() @ line = 225
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Throwing BaseTestException!
-Test "art.Test1929$DoThrowCatchTestException": Caught error art.Test1929$BaseTestException:"ThrowBaseHandler during throw from public static void art.Test1929.throwCatchTestException() @ line = 207" with handler "art.Test1929$ThrowBaseTestExceptionHandler"
+Test "art.Test1929$DoThrowCatchTestException": Caught error art.Test1929$BaseTestException:"ThrowBaseHandler during throw from public static void art.Test1929.throwCatchTestException() @ line = 216" with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchTestException": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
-main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
+main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 175 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
- public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 222
- public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 226
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 175
+ public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 234
+ public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 241
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Caught art.Test1929$TestException: "throwCatchTestExceptionTwice"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": No error caught with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with handler "art.Test1929$ThrowBaseTestExceptionHandler"
-main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 298 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 298
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1929$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1929$ThrowBaseTestExceptionHandler"
Test "art.Test1929$DoThrowClass": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
-main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: doThrow
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 298 caught class art.Test1929$TestException: doThrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 298
Test "art.Test1929$DoThrowClass": Caught error art.Test1929$TestException:"doThrow" with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowClass": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchBaseTestException": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
@@ -245,58 +245,58 @@ main: public static void art.Test1929.throwCatchBaseTestException() @ line = 140
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
public static void art.Test1929.throwCatchBaseTestException() @ line = 140
public void art.Test1929$DoThrowCatchBaseTestException.run() @ line = 149
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Throwing TestExceptionNoRethrow!
Test "art.Test1929$DoThrowCatchBaseTestException": Caught error art.Test1929$TestExceptionNoRethrow:"ThrowTestExceptionNoRethrowHandler during throw from public static void art.Test1929.throwCatchBaseTestException() @ line = 140" with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchBaseTestException": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
-main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
+main: public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 157 caught class art.Test1929$TestException: throwCatchBaseTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 161
- public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 197
- public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 201
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929$Impl.throwCatchBaseTestExceptionTwiceImpl() @ line = 157
+ public static void art.Test1929.throwCatchBaseTestExceptionTwice() @ line = 203
+ public void art.Test1929$DoThrowCatchBaseTestExceptionTwice.run() @ line = 210
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Caught art.Test1929$TestException: "throwCatchBaseTestExceptionTwice"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": No error caught with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchBaseTestExceptionTwice": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchTestException": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
-main: public static void art.Test1929.throwCatchTestException() @ line = 207 caught class art.Test1929$TestException: throwCatchTestException
+main: public static void art.Test1929.throwCatchTestException() @ line = 216 caught class art.Test1929$TestException: throwCatchTestException
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.throwCatchTestException() @ line = 207
- public void art.Test1929$DoThrowCatchTestException.run() @ line = 216
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929.throwCatchTestException() @ line = 216
+ public void art.Test1929$DoThrowCatchTestException.run() @ line = 225
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Throwing TestExceptionNoRethrow!
-Test "art.Test1929$DoThrowCatchTestException": Caught error art.Test1929$TestExceptionNoRethrow:"ThrowTestExceptionNoRethrowHandler during throw from public static void art.Test1929.throwCatchTestException() @ line = 207" with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
+Test "art.Test1929$DoThrowCatchTestException": Caught error art.Test1929$TestExceptionNoRethrow:"ThrowTestExceptionNoRethrowHandler during throw from public static void art.Test1929.throwCatchTestException() @ line = 216" with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchTestException": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
-main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
+main: public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 175 caught class art.Test1929$TestException: throwCatchTestExceptionTwice
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 179
- public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 222
- public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 226
- public static void art.Test1929.run() throws java.lang.Exception @ line = 280
+ public static void art.Test1929$Impl.throwCatchTestExceptionTwiceImpl() @ line = 175
+ public static void art.Test1929.throwCatchTestExceptionTwice() @ line = 234
+ public void art.Test1929$DoThrowCatchTestExceptionTwice.run() @ line = 241
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 295
Caught art.Test1929$TestException: "throwCatchTestExceptionTwice"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": No error caught with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchTestExceptionTwice": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Running breakpoint with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
-main: public static void art.Test1929.run() throws java.lang.Exception @ line = 283 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
+main: public static void art.Test1929.run() throws java.lang.Exception @ line = 298 caught class art.Test1929$TestException: throwCatchTestExceptionNoRethrow
Current Stack:
private static native art.StackTrace$StackFrameData[] art.StackTrace.nativeGetStackTrace(java.lang.Thread) @ line = -1
public static art.StackTrace$StackFrameData[] art.StackTrace.GetStackTrace(java.lang.Thread) @ line = 61
private static void art.Test1929.PrintStack() @ line = 52
public static void art.Test1929.ExceptionCatchEvent(java.lang.Thread,java.lang.reflect.Executable,long,java.lang.Throwable) @ line = 65
- public static void art.Test1929.run() throws java.lang.Exception @ line = 283
+ public static void art.Test1929.run() throws java.lang.Exception @ line = 298
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Caught error art.Test1929$TestException:"throwCatchTestExceptionNoRethrow" with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
Test "art.Test1929$DoThrowCatchTestExceptionNoRethrow": Finished running with handler "art.Test1929$ThrowTestExceptionNoRethrowHandler"
diff --git a/test/1929-exception-catch-exception/src/art/Test1929.java b/test/1929-exception-catch-exception/src/art/Test1929.java
index 07d2087a0f..e2deb3f85f 100644
--- a/test/1929-exception-catch-exception/src/art/Test1929.java
+++ b/test/1929-exception-catch-exception/src/art/Test1929.java
@@ -152,49 +152,58 @@ public class Test1929 {
// dx/d8/jack all do an optimization around catch blocks that (while legal) breaks assumptions
// this test relies on so we have the actual implementation be corrected smali. This does work
// for RI however.
- public static final class Impl {
- private Impl() {}
- public static void throwCatchBaseTestExceptionTwiceImpl() {
- try {
- try {
- throw new TestException("throwCatchBaseTestExceptionTwice");
- } catch (BaseTestException t) {
- System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
- if (PRINT_FULL_EXCEPTION) {
- t.printStackTrace(System.out);
- }
- }
- } catch (BaseTestException t) {
- System.out.println("2nd Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
- if (PRINT_FULL_EXCEPTION) {
- t.printStackTrace(System.out);
- }
- }
- }
- public static void throwCatchTestExceptionTwiceImpl() {
- try {
- try {
- throw new TestException("throwCatchTestExceptionTwice");
- } catch (TestException t) {
- System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
- if (PRINT_FULL_EXCEPTION) {
- t.printStackTrace(System.out);
- }
- }
- } catch (TestException t) {
- System.out.println("2nd Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
- if (PRINT_FULL_EXCEPTION) {
- t.printStackTrace(System.out);
- }
- }
- }
- }
+ // For reference:
+
+ // public static final class Impl {
+ // private Impl() {}
+ // public static void throwCatchBaseTestExceptionTwiceImpl() {
+ // try {
+ // try {
+ // throw new TestException("throwCatchBaseTestExceptionTwice");
+ // } catch (BaseTestException t) {
+ // System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+ // if (PRINT_FULL_EXCEPTION) {
+ // t.printStackTrace(System.out);
+ // }
+ // }
+ // } catch (BaseTestException t) {
+ // System.out.println("2nd Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+ // if (PRINT_FULL_EXCEPTION) {
+ // t.printStackTrace(System.out);
+ // }
+ // }
+ // }
+
+ // public static void throwCatchTestExceptionTwiceImpl() {
+ // try {
+ // try {
+ // throw new TestException("throwCatchTestExceptionTwice");
+ // } catch (TestException t) {
+ // System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+ // if (PRINT_FULL_EXCEPTION) {
+ // t.printStackTrace(System.out);
+ // }
+ // }
+ // } catch (TestException t) {
+ // System.out.println("2nd Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
+ // if (PRINT_FULL_EXCEPTION) {
+ // t.printStackTrace(System.out);
+ // }
+ // }
+ // }
+ // }
public static void throwCatchBaseTestExceptionTwice() {
// The implementation of this has to change depending upon the runtime slightly due to compiler
// optimizations present in DX/D8/Jack.
- Impl.throwCatchBaseTestExceptionTwiceImpl();
+ try {
+ Class<?> Impl = Class.forName("art.Test1929$Impl");
+ Method m = Impl.getMethod("throwCatchBaseTestExceptionTwiceImpl");
+ m.invoke(null);
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ }
}
public static class DoThrowCatchBaseTestExceptionTwice implements Runnable {
@@ -219,7 +228,13 @@ public class Test1929 {
public static void throwCatchTestExceptionTwice() {
// The implementation of this has to change depending upon the runtime slightly due to compiler
// optimizations present in DX/D8/Jack.
- Impl.throwCatchTestExceptionTwiceImpl();
+ try {
+ Class<?> Impl = Class.forName("art.Test1929$Impl");
+ Method m = Impl.getMethod("throwCatchTestExceptionTwiceImpl");
+ m.invoke(null);
+ } catch (Exception e) {
+ e.printStackTrace(System.out);
+ }
}
public static class DoThrowCatchTestExceptionTwice implements Runnable {
diff --git a/test/1935-get-set-current-frame-jit/expected.txt b/test/1935-get-set-current-frame-jit/expected.txt
index fed993cc1a..cdb8f6a825 100644
--- a/test/1935-get-set-current-frame-jit/expected.txt
+++ b/test/1935-get-set-current-frame-jit/expected.txt
@@ -1,7 +1,7 @@
JNI_OnLoad called
From GetLocalInt(), value is 42
-isInterpreted? true
+isInOsrCode? false
Value is '42'
Setting TARGET to 1337
-isInterpreted? true
+isInOsrCode? false
Value is '1337'
diff --git a/test/1935-get-set-current-frame-jit/src/Main.java b/test/1935-get-set-current-frame-jit/src/Main.java
index eb0a6374d2..714a98aaf3 100644
--- a/test/1935-get-set-current-frame-jit/src/Main.java
+++ b/test/1935-get-set-current-frame-jit/src/Main.java
@@ -64,9 +64,9 @@ public class Main {
Main.ensureJitCompiled(IntRunner.class, "run");
i++;
}
- // We shouldn't be doing OSR since we are using JVMTI and the get/set local will push us to
- // interpreter.
- System.out.println("isInterpreted? " + Main.isInterpreted());
+ // We shouldn't be doing OSR since we are using JVMTI and the get/set prevents OSR.
+ // Set local will also push us to interpreter but the get local may remain in compiled code.
+ System.out.println("isInOsrCode? " + (hasJit() && Main.isInOsrCode("run")));
reportValue(TARGET);
}
public void waitForBusyLoopStart() { while (!inBusyLoop) {} }
@@ -159,4 +159,6 @@ public class Main {
public static native void ensureJitCompiled(Class k, String f);
public static native boolean isInterpreted();
+ public static native boolean isInOsrCode(String methodName);
+ public static native boolean hasJit();
}
diff --git a/test/1940-ddms-ext/check b/test/1940-ddms-ext/check
index d2c03841fc..91966b41a0 100755
--- a/test/1940-ddms-ext/check
+++ b/test/1940-ddms-ext/check
@@ -16,6 +16,6 @@
# Need to pull out the describeException ouput since that won't be there on
# device.
-sed -e '/\t.*$/d' "$2" | sed -e '/java.lang.ArrayIndexOutOfBoundsException:.*$/d' > "$2.tmp"
+./remove_error.py "$2" "./expected_error.txt" > "$2.tmp"
./default-check "$1" "$2.tmp"
diff --git a/test/1940-ddms-ext/expected_error.txt b/test/1940-ddms-ext/expected_error.txt
new file mode 100644
index 0000000000..73883b46e2
--- /dev/null
+++ b/test/1940-ddms-ext/expected_error.txt
@@ -0,0 +1,4 @@
+java.lang.ArrayIndexOutOfBoundsException: byte[] offset=12 length=55 src.length=1
+ at art.Test1940.processChunk(Native Method)
+ at art.Test1940.run(Test1940.java:156)
+ at Main.main(Main.java:19)
diff --git a/test/1940-ddms-ext/remove_error.py b/test/1940-ddms-ext/remove_error.py
new file mode 100755
index 0000000000..638c479a31
--- /dev/null
+++ b/test/1940-ddms-ext/remove_error.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('input_data', type=open)
+ parser.add_argument('expected_error', type=str)
+ args = parser.parse_args()
+
+ for line in map(str.rstrip, args.input_data.readlines()):
+ print_full = True
+ with open(args.expected_error) as err_file:
+ for err_line in map(str.rstrip, err_file):
+ if line.startswith(err_line):
+ print_full = False
+ if line != err_line:
+ print(line[len(err_line):])
+ break
+ if print_full and line != '':
+ print(line)
+
+if __name__ == '__main__':
+ main()
diff --git a/test/674-hiddenapi/src-ex/ChildClass.java b/test/674-hiddenapi/src-ex/ChildClass.java
index 8cd237ab6f..582e907ca3 100644
--- a/test/674-hiddenapi/src-ex/ChildClass.java
+++ b/test/674-hiddenapi/src-ex/ChildClass.java
@@ -123,9 +123,6 @@ public class ChildClass {
// Check whether one can use an interface default method.
String name = "method" + visibility.name() + "Default" + hiddenness.name();
checkMethod(ParentInterface.class, name, /*isStatic*/ false, visibility, expected);
-
- // Check whether one can override this method.
- checkOverriding(suffix, isStatic, visibility, expected);
}
// Test whether static linking succeeds.
@@ -406,37 +403,6 @@ public class ChildClass {
}
}
- private static void checkOverriding(String suffix,
- boolean isStatic,
- Visibility visibility,
- Behaviour behaviour) throws Exception {
- if (isStatic || visibility == Visibility.Private) {
- // Does not make sense to override a static or private method.
- return;
- }
-
- // The classes are in the same package, but will be able to access each
- // other only if loaded with the same class loader, here the boot class loader.
- boolean canAccess = (visibility != Visibility.Package) || (isParentInBoot && isChildInBoot);
- boolean setsWarning = false; // warnings may be set during vtable linking
-
- String methodName = "callMethod" + visibility.name() + suffix;
-
- // Force the test class to link its vtable, which may cause warnings, before
- // the actual test.
- new OverrideClass().methodPublicWhitelist();
-
- clearWarning();
- if (Linking.canOverride(methodName) != canAccess) {
- throw new RuntimeException("Expected to " + (canAccess ? "" : "not ") +
- "be able to override " + methodName + "." +
- "isParentInBoot = " + isParentInBoot + ", " + "isChildInBoot = " + isChildInBoot);
- }
- if (canAccess && hasPendingWarning() != setsWarning) {
- throwWarningException(ParentClass.class, methodName, false, "static linking", setsWarning);
- }
- }
-
private static void throwDiscoveryException(Class<?> klass, String name, boolean isField,
String fn, boolean canAccess) {
throw new RuntimeException("Expected " + (isField ? "field " : "method ") + klass.getName() +
diff --git a/test/674-hiddenapi/src-ex/Linking.java b/test/674-hiddenapi/src-ex/Linking.java
index b416250953..a89b92b2b9 100644
--- a/test/674-hiddenapi/src-ex/Linking.java
+++ b/test/674-hiddenapi/src-ex/Linking.java
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Linking {
@@ -35,16 +34,6 @@ public class Linking {
}
}
}
-
- public static boolean canOverride(String methodName) throws Exception {
- // ParentClass returns only positive numbers, OverrideClass only negative.
- // This way we can tell if OverrideClass managed to override the original
- // method or not.
- Method method = ParentClass.class.getDeclaredMethod(methodName);
- int result1 = (int) method.invoke(new ParentClass());
- int result2 = (int) method.invoke(new OverrideClass());
- return (result1 > 0) && (result2 < 0);
- }
}
// INSTANCE FIELD GET
diff --git a/test/674-hiddenapi/src-ex/OverrideClass.java b/test/674-hiddenapi/src-ex/OverrideClass.java
deleted file mode 100644
index 1f1f4d6aac..0000000000
--- a/test/674-hiddenapi/src-ex/OverrideClass.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-public class OverrideClass extends ParentClass {
-
- @Override public int methodPublicWhitelist() { return -411; }
- @Override int methodPackageWhitelist() { return -412; }
- @Override protected int methodProtectedWhitelist() { return -413; }
-
- @Override public int methodPublicLightGreylist() { return -421; }
- @Override int methodPackageLightGreylist() { return -422; }
- @Override protected int methodProtectedLightGreylist() { return -423; }
-
- @Override public int methodPublicDarkGreylist() { return -431; }
- @Override int methodPackageDarkGreylist() { return -432; }
- @Override protected int methodProtectedDarkGreylist() { return -433; }
-
- @Override public int methodPublicBlacklist() { return -441; }
- @Override int methodPackageBlacklist() { return -442; }
- @Override protected int methodProtectedBlacklist() { return -443; }
-
-}
diff --git a/test/679-locks/expected.txt b/test/679-locks/expected.txt
new file mode 100644
index 0000000000..85a20bea2f
--- /dev/null
+++ b/test/679-locks/expected.txt
@@ -0,0 +1,2 @@
+JNI_OnLoad called
+MyString
diff --git a/test/679-locks/info.txt b/test/679-locks/info.txt
new file mode 100644
index 0000000000..7ada4900c6
--- /dev/null
+++ b/test/679-locks/info.txt
@@ -0,0 +1,2 @@
+Ensure FindLocksAtDexPc is able to pass through quickened instructions related
+to unresolved classes.
diff --git a/test/679-locks/run b/test/679-locks/run
new file mode 100644
index 0000000000..0cc87f3168
--- /dev/null
+++ b/test/679-locks/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.i
+
+# Run without an app image to prevent the class NotLoaded to be loaded at startup.
+exec ${RUN} "${@}" --no-app-image
diff --git a/test/679-locks/src/Main.java b/test/679-locks/src/Main.java
new file mode 100644
index 0000000000..fbc8c53833
--- /dev/null
+++ b/test/679-locks/src/Main.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class NotLoaded {
+ public void foo() {}
+}
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+ TestSync.run();
+ }
+
+ public static void run() {
+ testVisitLocks();
+ }
+
+ static Object myStatic;
+
+ // Note: declared in 167-visit-locks.
+ public static native void testVisitLocks();
+}
+
+// 167-visit-locks/visit-locks.cc looks at the locks held in TestSync.run().
+class TestSync {
+ public static void run() {
+ Object o = Main.myStatic;
+ if (o != null) {
+ if (o instanceof NotLoaded) {
+ ((NotLoaded)o).foo();
+ }
+ }
+ synchronized ("MyString") {
+ Main.testVisitLocks();
+ }
+ }
+}
diff --git a/test/680-sink-regression/expected.txt b/test/680-sink-regression/expected.txt
new file mode 100644
index 0000000000..b0aad4deb5
--- /dev/null
+++ b/test/680-sink-regression/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/680-sink-regression/info.txt b/test/680-sink-regression/info.txt
new file mode 100644
index 0000000000..547e3b801a
--- /dev/null
+++ b/test/680-sink-regression/info.txt
@@ -0,0 +1 @@
+Regression test for code sinking with exceptions (b/75971227).
diff --git a/test/680-sink-regression/src/Main.java b/test/680-sink-regression/src/Main.java
new file mode 100644
index 0000000000..642c3abdf4
--- /dev/null
+++ b/test/680-sink-regression/src/Main.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.*;
+
+/**
+ * Regression test for b/75971227 (code sinking with exceptions).
+ */
+public class Main {
+
+ public static class N {
+ int x;
+ }
+
+ private int f;
+
+ public int doit(N n1) throws FileNotFoundException {
+ int x = 1;
+ N n3 = new N();
+ try {
+ if (n1.x == 0) {
+ f = 11;
+ x = 3;
+ } else {
+ f = x;
+ }
+ throw new FileNotFoundException("n3" + n3.x);
+ } catch (NullPointerException e) {
+ }
+ return x;
+ }
+
+
+ public static void main(String[] args) {
+ N n = new N();
+ Main t = new Main();
+ int x = 0;
+
+ // Main 1, null pointer argument.
+ t.f = 0;
+ try {
+ x = t.doit(null);
+ } catch (FileNotFoundException e) {
+ x = -1;
+ }
+ if (x != 1 || t.f != 0) {
+ throw new Error("Main 1: x=" + x + " f=" + t.f);
+ }
+
+ // Main 2, n.x is 0.
+ n.x = 0;
+ try {
+ x = t.doit(n);
+ } catch (FileNotFoundException e) {
+ x = -1;
+ }
+ if (x != -1 || t.f != 11) {
+ throw new Error("Main 2: x=" + x + " f=" + t.f);
+ }
+
+ // Main 3, n.x is not 0.
+ n.x = 1;
+ try {
+ x = t.doit(n);
+ } catch (FileNotFoundException e) {
+ x = -1;
+ }
+ if (x != -1 || t.f != 1) {
+ throw new Error("Main 3: x=" + x + " f=" + t.f);
+ }
+
+ System.out.println("passed");
+ }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index cf781d7f2b..6633958140 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -24,7 +24,6 @@ TEST_ART_RUN_TEST_DEPENDENCIES := \
$(HOST_OUT_EXECUTABLES)/hiddenapi \
$(HOST_OUT_EXECUTABLES)/jasmin \
$(HOST_OUT_EXECUTABLES)/smali \
- $(HOST_OUT_EXECUTABLES)/dexmerger \
$(HOST_OUT_JAVA_LIBRARIES)/desugar.jar
# Add d8 dependency, if enabled.
@@ -103,7 +102,7 @@ endif
# Host executables.
host_prereq_rules := $(ART_TEST_HOST_RUN_TEST_DEPENDENCIES)
-# Required for dx, jasmin, smali, dexmerger.
+# Required for dx, jasmin, smali.
host_prereq_rules += $(TEST_ART_RUN_TEST_DEPENDENCIES)
# Sync test files to the target, depends upon all things that must be pushed
diff --git a/test/etc/default-build b/test/etc/default-build
index 3e6577cfda..9de7294a59 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -341,8 +341,26 @@ function make_dexmerge() {
shift
done
- # Should have at least 1 dex_files_to_merge here, otherwise dxmerger will print the help.
- ${DXMERGER} "$dst_file" "${dex_files_to_merge[@]}"
+ # Skip merge if we are not merging anything. IE: input = output.
+ if [[ "${#dex_files_to_merge[@]}" -eq "1" ]]; then
+ local single_input=${dex_files_to_merge[0]}
+ if [[ "$dst_file" != "$single_input" ]]; then
+ mv "$single_input" "$dst_file";
+ return
+ fi
+ fi
+
+ # We assume the dexer did all the API level checks and just merge away.
+ mkdir d8_merge_out
+ ${DXMERGER} --min-api 1000 --output ./d8_merge_out "${dex_files_to_merge[@]}"
+
+ if [[ -e "./d8_merge_out/classes2.dex" ]]; then
+ echo "Cannot merge all dex files into a single dex"
+ exit 1
+ fi
+
+ mv ./d8_merge_out/classes.dex "$dst_file";
+ rmdir d8_merge_out
}
function make_hiddenapi() {
diff --git a/test/knownfailures.json b/test/knownfailures.json
index a7e76d131e..22c370a61f 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -954,7 +954,8 @@
},
{
"tests": ["616-cha-unloading",
- "678-quickening"],
+ "678-quickening",
+ "679-locks"],
"variant": "jvm",
"description": ["Doesn't run on RI."]
},
diff --git a/test/run-test b/test/run-test
index 260a65a056..5b43b52b41 100755
--- a/test/run-test
+++ b/test/run-test
@@ -50,11 +50,18 @@ export USE_JACK="false"
export USE_DESUGAR="true"
export SMALI_ARGS=""
+# If d8 was not set by the environment variable, assume it is in the path.
+if [ -z "$D8" ]; then
+ export D8="d8"
+fi
+
# If dx was not set by the environment variable, assume it is in the path.
if [ -z "$DX" ]; then
export DX="dx"
fi
+export DXMERGER="$D8"
+
# If jasmin was not set by the environment variable, assume it is in the path.
if [ -z "$JASMIN" ]; then
export JASMIN="jasmin"
@@ -65,11 +72,6 @@ if [ -z "$SMALI" ]; then
export SMALI="smali"
fi
-# If dexmerger was not set by the environment variable, assume it is in the path.
-if [ -z "$DXMERGER" ]; then
- export DXMERGER="dexmerger"
-fi
-
# If jack was not set by the environment variable, assume it is in the path.
if [ -z "$JACK" ]; then
export JACK="jack"
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index 70efce51ee..539499173c 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -136,9 +136,8 @@ HOST_OUT_EXECUTABLES = os.path.join(ANDROID_BUILD_TOP,
_get_build_var("HOST_OUT_EXECUTABLES"))
# Set up default values for $JACK, $DX, $SMALI, etc to the $HOST_OUT_EXECUTABLES/$name path.
-for tool in ['jack', 'dx', 'smali', 'jasmin', 'dxmerger']:
- binary = tool if tool != 'dxmerger' else 'dexmerger'
- os.environ.setdefault(tool.upper(), HOST_OUT_EXECUTABLES + '/' + binary)
+for tool in ['jack', 'dx', 'smali', 'jasmin', 'd8']:
+ os.environ.setdefault(tool.upper(), HOST_OUT_EXECUTABLES + '/' + tool)
ANDROID_JAVA_TOOLCHAIN = os.path.join(ANDROID_BUILD_TOP,
_get_build_var('ANDROID_JAVA_TOOLCHAIN'))
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index a2215f9e9b..734a600c5e 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -114,6 +114,7 @@ ignore_skips = False
build = False
gdb = False
gdb_arg = ''
+runtime_option = ''
stop_testrunner = False
dex2oat_jobs = -1 # -1 corresponds to default threads for dex2oat
run_all_configs = False
@@ -346,6 +347,10 @@ def run_tests(tests):
if gdb_arg:
options_all += ' --gdb-arg ' + gdb_arg
+ if runtime_option:
+ for opt in runtime_option:
+ options_all += ' --runtime-option ' + opt
+
if dex2oat_jobs != -1:
options_all += ' --dex2oat-jobs ' + str(dex2oat_jobs)
@@ -921,6 +926,7 @@ def parse_option():
global build
global gdb
global gdb_arg
+ global runtime_option
global timeout
global dex2oat_jobs
global run_all_configs
@@ -933,9 +939,9 @@ def parse_option():
global_group.add_argument('--timeout', default=timeout, type=int, dest='timeout')
global_group.add_argument('--verbose', '-v', action='store_true', dest='verbose')
global_group.add_argument('--dry-run', action='store_true', dest='dry_run')
- global_group.add_argument("--skip", action="append", dest="skips", default=[],
+ global_group.add_argument("--skip", action='append', dest="skips", default=[],
help="Skip the given test in all circumstances.")
- global_group.add_argument("--no-skips", dest="ignore_skips", action="store_true", default=False,
+ global_group.add_argument("--no-skips", dest="ignore_skips", action='store_true', default=False,
help="""Don't skip any run-test configurations listed in
knownfailures.json.""")
global_group.add_argument('--no-build-dependencies',
@@ -950,6 +956,10 @@ def parse_option():
global_group.set_defaults(build = env.ART_TEST_RUN_TEST_BUILD)
global_group.add_argument('--gdb', action='store_true', dest='gdb')
global_group.add_argument('--gdb-arg', dest='gdb_arg')
+ global_group.add_argument('--runtime-option', action='append', dest='runtime_option',
+ help="""Pass an option to the runtime. Runtime options
+ starting with a '-' must be separated by a '=', for
+ example '--runtime-option=-Xjitthreshold:0'.""")
global_group.add_argument('--dex2oat-jobs', type=int, dest='dex2oat_jobs',
help='Number of dex2oat jobs')
global_group.add_argument('-a', '--all', action='store_true', dest='run_all',
@@ -993,6 +1003,7 @@ def parse_option():
gdb = True
if options['gdb_arg']:
gdb_arg = options['gdb_arg']
+ runtime_option = options['runtime_option'];
timeout = options['timeout']
if options['dex2oat_jobs']:
dex2oat_jobs = options['dex2oat_jobs']
diff --git a/tools/ahat/Android.bp b/tools/ahat/Android.bp
new file mode 100644
index 0000000000..dc9f098ff3
--- /dev/null
+++ b/tools/ahat/Android.bp
@@ -0,0 +1,25 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// 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.
+
+droiddoc_host {
+ name: "ahat-docs",
+ srcs: [
+ "src/main/**/*.java",
+ ],
+ custom_template: "droiddoc-templates-sdk",
+ args: "-stubpackages com.android.ahat:com.android.ahat.*",
+ api_tag_name: "AHAT",
+ api_filename: "ahat_api.txt",
+ removed_api_filename: "ahat_removed_api.txt",
+}
diff --git a/tools/ahat/Android.mk b/tools/ahat/Android.mk
index bf79751659..ad33233159 100644
--- a/tools/ahat/Android.mk
+++ b/tools/ahat/Android.mk
@@ -37,23 +37,10 @@ LOCAL_COMPATIBILITY_SUITE := general-tests
include $(BUILD_HOST_JAVA_LIBRARY)
AHAT_JAR := $(LOCAL_BUILT_MODULE)
-AHAT_API := $(intermediates.COMMON)/ahat_api.txt
-AHAT_REMOVED_API := $(intermediates.COMMON)/ahat_removed_api.txt
# --- api check for ahat.jar ----------
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-java-files-under, src/main)
-LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE := ahat
-LOCAL_DROIDDOC_OPTIONS := \
- -stubpackages com.android.ahat:com.android.ahat.* \
- -api $(AHAT_API) \
- -removedApi $(AHAT_REMOVED_API)
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := external/doclava/res/assets/templates-sdk
-include $(BUILD_DROIDDOC)
-$(AHAT_API): $(full_target)
+AHAT_API := $(INTERNAL_PLATFORM_AHAT_API_FILE)
+AHAT_REMOVED_API := $(INTERNAL_PLATFORM_AHAT_REMOVED_API_FILE)
$(eval $(call check-api, \
ahat-check-api, \
diff --git a/tools/veridex/Android.bp b/tools/veridex/Android.bp
new file mode 100644
index 0000000000..31ff682828
--- /dev/null
+++ b/tools/veridex/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+art_cc_binary {
+ name: "veridex",
+ host_supported: true,
+ srcs: [
+ "resolver.cc",
+ "veridex.cc",
+ ],
+ cflags: ["-Wall", "-Werror"],
+ shared_libs: ["libdexfile", "libbase"],
+ header_libs: [
+ "art_libartbase_headers",
+ ],
+}
diff --git a/tools/veridex/resolver.cc b/tools/veridex/resolver.cc
new file mode 100644
index 0000000000..c0705e5ea8
--- /dev/null
+++ b/tools/veridex/resolver.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "resolver.h"
+
+#include "dex/dex_file-inl.h"
+#include "dex/primitive.h"
+#include "veridex.h"
+
+namespace art {
+
+void VeridexResolver::Run() {
+ size_t class_def_count = dex_file_.NumClassDefs();
+ for (size_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
+ const DexFile::ClassDef& class_def = dex_file_.GetClassDef(class_def_index);
+ std::string name(dex_file_.StringByTypeIdx(class_def.class_idx_));
+ auto existing = type_map_.find(name);
+ if (existing != type_map_.end()) {
+ // Class already exists, cache it and move on.
+ type_infos_[class_def.class_idx_.index_] = *existing->second;
+ continue;
+ }
+ type_infos_[class_def.class_idx_.index_] = VeriClass(Primitive::Type::kPrimNot, 0, &class_def);
+ type_map_[name] = &(type_infos_[class_def.class_idx_.index_]);
+
+ const uint8_t* class_data = dex_file_.GetClassData(class_def);
+ if (class_data == nullptr) {
+ // Empty class.
+ continue;
+ }
+
+ ClassDataItemIterator it(dex_file_, class_data);
+ for (; it.HasNextStaticField(); it.Next()) {
+ field_infos_[it.GetMemberIndex()] = it.DataPointer();
+ }
+ for (; it.HasNextInstanceField(); it.Next()) {
+ field_infos_[it.GetMemberIndex()] = it.DataPointer();
+ }
+ for (; it.HasNextMethod(); it.Next()) {
+ method_infos_[it.GetMemberIndex()] = it.DataPointer();
+ }
+ }
+}
+
+} // namespace art
diff --git a/tools/veridex/resolver.h b/tools/veridex/resolver.h
new file mode 100644
index 0000000000..4e0c5b3732
--- /dev/null
+++ b/tools/veridex/resolver.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_TOOLS_VERIDEX_RESOLVER_H_
+#define ART_TOOLS_VERIDEX_RESOLVER_H_
+
+#include "dex/dex_file.h"
+#include "veridex.h"
+
+namespace art {
+
+class VeridexResolver {
+ public:
+ VeridexResolver(const DexFile& dex_file, TypeMap& type_map)
+ : dex_file_(dex_file),
+ type_map_(type_map),
+ type_infos_(dex_file.NumTypeIds(), VeriClass()),
+ method_infos_(dex_file.NumMethodIds(), nullptr),
+ field_infos_(dex_file.NumFieldIds(), nullptr) {}
+
+ void Run();
+
+ private:
+ const DexFile& dex_file_;
+ TypeMap& type_map_;
+ std::vector<VeriClass> type_infos_;
+ std::vector<VeriMethod> method_infos_;
+ std::vector<VeriField> field_infos_;
+};
+
+} // namespace art
+
+#endif // ART_TOOLS_VERIDEX_RESOLVER_H_
diff --git a/tools/veridex/veridex.cc b/tools/veridex/veridex.cc
new file mode 100644
index 0000000000..0370a0329c
--- /dev/null
+++ b/tools/veridex/veridex.cc
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "veridex.h"
+
+#include <android-base/file.h>
+
+#include "dex/dex_file.h"
+#include "dex/dex_file_loader.h"
+#include "resolver.h"
+
+#include <sstream>
+
+namespace art {
+
+struct VeridexOptions {
+ const char* dex_file = nullptr;
+ const char* core_stubs = nullptr;
+ const char* blacklist = nullptr;
+ const char* light_greylist = nullptr;
+ const char* dark_greylist = nullptr;
+};
+
+static const char* Substr(const char* str, int index) {
+ return str + index;
+}
+
+static bool StartsWith(const char* str, const char* val) {
+ return strlen(str) >= strlen(val) && memcmp(str, val, strlen(val)) == 0;
+}
+
+static void ParseArgs(VeridexOptions* options, int argc, char** argv) {
+ // Skip over the command name.
+ argv++;
+ argc--;
+
+ static const char* kDexFileOption = "--dex-file=";
+ static const char* kStubsOption = "--core-stubs=";
+ static const char* kBlacklistOption = "--blacklist=";
+ static const char* kDarkGreylistOption = "--dark-greylist=";
+ static const char* kLightGreylistOption = "--light-greylist=";
+
+ for (int i = 0; i < argc; ++i) {
+ if (StartsWith(argv[i], kDexFileOption)) {
+ options->dex_file = Substr(argv[i], strlen(kDexFileOption));
+ } else if (StartsWith(argv[i], kStubsOption)) {
+ options->core_stubs = Substr(argv[i], strlen(kStubsOption));
+ } else if (StartsWith(argv[i], kBlacklistOption)) {
+ options->blacklist = Substr(argv[i], strlen(kBlacklistOption));
+ } else if (StartsWith(argv[i], kDarkGreylistOption)) {
+ options->dark_greylist = Substr(argv[i], strlen(kDarkGreylistOption));
+ } else if (StartsWith(argv[i], kLightGreylistOption)) {
+ options->light_greylist = Substr(argv[i], strlen(kLightGreylistOption));
+ }
+ }
+}
+
+static std::vector<std::string> Split(const std::string& str, char sep) {
+ std::vector<std::string> tokens;
+ std::string tmp;
+ std::istringstream iss(str);
+ while (std::getline(iss, tmp, sep)) {
+ tokens.push_back(tmp);
+ }
+ return tokens;
+}
+
+class Veridex {
+ public:
+ static int Run(int argc, char** argv) {
+ VeridexOptions options;
+ ParseArgs(&options, argc, argv);
+
+ std::vector<std::string> boot_content;
+ std::vector<std::string> app_content;
+ std::vector<std::unique_ptr<const DexFile>> boot_dex_files;
+ std::vector<std::unique_ptr<const DexFile>> app_dex_files;
+ std::string error_msg;
+
+ // Read the boot classpath.
+ std::vector<std::string> boot_classpath = Split(options.core_stubs, ':');
+ boot_content.resize(boot_classpath.size());
+ uint32_t i = 0;
+ for (const std::string& str : boot_classpath) {
+ if (!Load(str, boot_content[i++], &boot_dex_files, &error_msg)) {
+ LOG(ERROR) << error_msg;
+ return 1;
+ }
+ }
+
+ // Read the apps dex files.
+ std::vector<std::string> app_files = Split(options.dex_file, ':');
+ app_content.resize(app_files.size());
+ i = 0;
+ for (const std::string& str : app_files) {
+ if (!Load(str, app_content[i++], &app_dex_files, &error_msg)) {
+ LOG(ERROR) << error_msg;
+ return 1;
+ }
+ }
+
+ // Resolve classes/methods/fields defined in each dex file.
+
+ // Cache of types we've seen. This is used in case of duplicate classes.
+ TypeMap type_map;
+
+ std::vector<VeridexResolver> boot_resolvers;
+ Resolve(boot_dex_files, type_map, &boot_resolvers);
+
+ std::vector<VeridexResolver> app_resolvers;
+ Resolve(app_dex_files, type_map, &app_resolvers);
+
+ return 0;
+ }
+
+ private:
+ static bool Load(const std::string& filename,
+ std::string& content,
+ std::vector<std::unique_ptr<const DexFile>>* dex_files,
+ std::string* error_msg) {
+ if (filename.empty()) {
+ *error_msg = "Missing file name";
+ return false;
+ }
+
+ // TODO: once added, use an api to android::base to read a std::vector<uint8_t>.
+ if (!android::base::ReadFileToString(filename.c_str(), &content)) {
+ *error_msg = "ReadFileToString failed for " + filename;
+ return false;
+ }
+
+ const DexFileLoader dex_file_loader;
+ static constexpr bool kVerifyChecksum = true;
+ static constexpr bool kRunDexFileVerifier = true;
+ if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()),
+ content.size(),
+ filename.c_str(),
+ kRunDexFileVerifier,
+ kVerifyChecksum,
+ error_msg,
+ dex_files)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ static void Resolve(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
+ TypeMap& type_map,
+ std::vector<VeridexResolver>* resolvers) {
+ for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+ resolvers->push_back(VeridexResolver(*dex_file.get(), type_map));
+ }
+
+ for (VeridexResolver& resolver : *resolvers) {
+ resolver.Run();
+ }
+ }
+};
+
+} // namespace art
+
+int main(int argc, char** argv) {
+ return art::Veridex::Run(argc, argv);
+}
+
diff --git a/tools/veridex/veridex.h b/tools/veridex/veridex.h
new file mode 100644
index 0000000000..bbff254f0a
--- /dev/null
+++ b/tools/veridex/veridex.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_TOOLS_VERIDEX_VERIDEX_H_
+#define ART_TOOLS_VERIDEX_VERIDEX_H_
+
+#include <map>
+
+#include "dex/dex_file.h"
+#include "dex/primitive.h"
+
+namespace art {
+
+/**
+ * Abstraction for classes defined, or implicitly defined (for arrays and primitives)
+ * in dex files.
+ */
+class VeriClass {
+ public:
+ VeriClass(const VeriClass& other) = default;
+ VeriClass() = default;
+ VeriClass(Primitive::Type k, uint8_t dims, const DexFile::ClassDef* cl)
+ : kind_(k), dimensions_(dims), class_def_(cl) {}
+
+ bool IsUninitialized() const {
+ return kind_ == Primitive::Type::kPrimNot && dimensions_ == 0 && class_def_ == nullptr;
+ }
+
+ bool IsPrimitive() const {
+ return kind_ != Primitive::Type::kPrimNot && dimensions_ == 0;
+ }
+
+ bool IsArray() const {
+ return dimensions_ != 0;
+ }
+
+ private:
+ Primitive::Type kind_;
+ uint8_t dimensions_;
+ const DexFile::ClassDef* class_def_;
+};
+
+/**
+ * Abstraction for fields defined in dex files. Currently, that's a pointer into their
+ * `encoded_field` description.
+ */
+using VeriField = const uint8_t*;
+
+/**
+ * Abstraction for methods defined in dex files. Currently, that's a pointer into their
+ * `encoded_method` description.
+ */
+using VeriMethod = const uint8_t*;
+
+using TypeMap = std::map<std::string, VeriClass*>;
+
+} // namespace art
+
+#endif // ART_TOOLS_VERIDEX_VERIDEX_H_