diff options
52 files changed, 2002 insertions, 1314 deletions
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk index 7fae7f6200..c508fe7e9e 100644 --- a/build/Android.common_test.mk +++ b/build/Android.common_test.mk @@ -20,14 +20,11 @@ ART_ANDROID_COMMON_TEST_MK = true include art/build/Android.common_path.mk # Directory used for temporary test files on the host. -ifneq ($(TMPDIR),) -ART_HOST_TEST_DIR := $(TMPDIR)/test-art-$(shell echo $$PPID) -else # Use a BSD checksum calculated from CWD and USER as one of the path # components for the test output. This should allow us to run tests from # multiple repositories at the same time. -ART_HOST_TEST_DIR := /tmp/test-art-$(shell echo $$CWD-${USER} | sum | cut -d ' ' -f1) -endif +ART_TMPDIR := $(if $(TMPDIR),$(TMPDIR),/tmp) +ART_HOST_TEST_DIR := $(ART_TMPDIR)/test-art-$(shell echo $$CWD-${USER} | sum | cut -d ' ' -f1) # List of known broken tests that we won't attempt to execute. The test name must be the full # rule name such as test-art-host-oat-optimizing-HelloWorld64. diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index 4a35ccfa13..388ff061a9 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -339,6 +339,7 @@ ART_TEST_MODULES := \ art_profman_tests \ art_runtime_tests \ art_runtime_compiler_tests \ + art_sigchain_tests \ ART_TARGET_GTEST_FILES := $(foreach m,$(ART_TEST_MODULES),\ $(ART_TEST_LIST_device_$(TARGET_ARCH)_$(m))) diff --git a/runtime/arch/arm64/instruction_set_features_arm64.cc b/runtime/arch/arm64/instruction_set_features_arm64.cc index 9e9cb16008..42c9a846d0 100644 --- a/runtime/arch/arm64/instruction_set_features_arm64.cc +++ b/runtime/arch/arm64/instruction_set_features_arm64.cc @@ -54,6 +54,7 @@ Arm64FeaturesUniquePtr Arm64InstructionSetFeatures::FromVariant( "cortex-a35", "exynos-m1", "exynos-m2", + "exynos-m3", "denver64", "kryo" }; diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 856e538ad6..f18e0b412c 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -267,7 +267,9 @@ static void WrapExceptionInInitializer(Handle<mirror::Class> klass) // cannot in general be guaranteed, but in all likelihood leads to breakage down the line. if (klass->GetClassLoader() == nullptr && !Runtime::Current()->IsAotCompiler()) { std::string tmp; - LOG(kIsDebugBuild ? FATAL : WARNING) << klass->GetDescriptor(&tmp) << " failed initialization"; + LOG(kIsDebugBuild ? FATAL : WARNING) << klass->GetDescriptor(&tmp) + << " failed initialization: " + << self->GetException()->Dump(); } env->ExceptionClear(); diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc index 0ae6dbfa88..b6055cb6c8 100644 --- a/runtime/instrumentation.cc +++ b/runtime/instrumentation.cc @@ -209,7 +209,9 @@ static void InstrumentationInstallStack(Thread* thread, void* arg) : StackVisitor(thread_in, context, kInstrumentationStackWalk), instrumentation_stack_(thread_in->GetInstrumentationStack()), instrumentation_exit_pc_(instrumentation_exit_pc), - reached_existing_instrumentation_frames_(false), instrumentation_stack_depth_(0), + reached_existing_instrumentation_frames_(false), + should_be_at_top_(false), + instrumentation_stack_depth_(0), last_return_pc_(0) { } @@ -233,6 +235,20 @@ static void InstrumentationInstallStack(Thread* thread, void* arg) return true; // Continue. } uintptr_t return_pc = GetReturnPc(); + if (UNLIKELY(should_be_at_top_)) { + std::string thread_name; + GetThread()->GetThreadName(thread_name); + uint32_t dex_pc = dex::kDexNoIndex; + if (last_return_pc_ != 0 && + GetCurrentOatQuickMethodHeader() != nullptr) { + dex_pc = GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_); + } + LOG(FATAL) << "While walking " << thread_name << " Reached unexpected frame above what " + << "should have been top. Method is " << GetMethod()->PrettyMethod() + << " return_pc: " << std::hex << return_pc + << " dex pc: " << dex_pc; + UNREACHABLE(); + } if (kVerboseInstrumentation) { LOG(INFO) << " Installing exit stub in " << DescribeLocation(); } @@ -267,22 +283,21 @@ static void InstrumentationInstallStack(Thread* thread, void* arg) if (kVerboseInstrumentation) { LOG(INFO) << "Ignoring already instrumented " << frame.Dump(); } + } else if (UNLIKELY(reached_existing_instrumentation_frames_)) { + // If tracing was enabled we might have had all methods have the instrumentation frame + // except the runtime transition method at the very top of the stack. This isn't really a + // problem since the transition method just goes back into the runtime and never leaves it + // so it can be ignored. + should_be_at_top_ = true; + DCHECK(m->IsRuntimeMethod()) << "Expected method to be runtime method at start of thread " + << "but was " << m->PrettyMethod(); + if (kVerboseInstrumentation) { + LOG(INFO) << "reached expected top frame " << m->PrettyMethod(); + } + // Don't bother continuing on the upcalls on non-debug builds. + return kIsDebugBuild ? true : false; } else { CHECK_NE(return_pc, 0U); - if (UNLIKELY(reached_existing_instrumentation_frames_)) { - std::string thread_name; - GetThread()->GetThreadName(thread_name); - uint32_t dex_pc = dex::kDexNoIndex; - if (last_return_pc_ != 0 && - GetCurrentOatQuickMethodHeader() != nullptr) { - dex_pc = GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_); - } - LOG(FATAL) << "While walking " << thread_name << " found existing instrumentation frames." - << " method is " << GetMethod()->PrettyMethod() - << " return_pc is " << std::hex << return_pc - << " dex pc: " << dex_pc; - UNREACHABLE(); - } InstrumentationStackFrame instrumentation_frame( m->IsRuntimeMethod() ? nullptr : GetThisObject(), m, @@ -320,6 +335,7 @@ static void InstrumentationInstallStack(Thread* thread, void* arg) std::vector<uint32_t> dex_pcs_; const uintptr_t instrumentation_exit_pc_; bool reached_existing_instrumentation_frames_; + bool should_be_at_top_; size_t instrumentation_stack_depth_; uintptr_t last_return_pc_; }; diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index a8ab626a62..380a981d09 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -1073,7 +1073,7 @@ static ObjPtr<mirror::CallSite> InvokeBootstrapMethod(Thread* self, Handle<mirror::Object> object(hs.NewHandle(result.GetL())); if (UNLIKELY(object.IsNull())) { // This will typically be for LambdaMetafactory which is not supported. - ThrowNullPointerException("Bootstrap method returned null"); + ThrowClassCastException("Bootstrap method returned null"); return nullptr; } @@ -1085,11 +1085,10 @@ static ObjPtr<mirror::CallSite> InvokeBootstrapMethod(Thread* self, Handle<mirror::CallSite> call_site = hs.NewHandle(ObjPtr<mirror::CallSite>::DownCast(ObjPtr<mirror::Object>(result.GetL()))); - // Check the call site target is not null as we're going to invoke it. Handle<mirror::MethodHandle> target = hs.NewHandle(call_site->GetTarget()); if (UNLIKELY(target.IsNull())) { - ThrowNullPointerException("Target for call-site is null"); + ThrowClassCastException("Bootstrap method did not return a callsite"); return nullptr; } diff --git a/sigchainlib/Android.bp b/sigchainlib/Android.bp index 7aab726be7..1f490cd3b9 100644 --- a/sigchainlib/Android.bp +++ b/sigchainlib/Android.bp @@ -16,15 +16,24 @@ cc_library { name: "libsigchain", + cpp_std: "gnu++17", + host_supported: true, defaults: ["art_defaults"], - shared: { - srcs: ["sigchain_dummy.cc"], - }, - static: { - srcs: ["sigchain.cc"], - }, target: { + linux: { + shared: { + srcs: ["sigchain_dummy.cc"], + }, + static: { + srcs: ["sigchain.cc"], + }, + }, + + darwin: { + srcs: ["sigchain_dummy.cc"], + }, + android: { shared_libs: ["liblog"], }, @@ -51,3 +60,12 @@ cc_library_static { }, }, } + +art_cc_test { + name: "art_sigchain_tests", + defaults: [ + "art_gtest_defaults", + ], + srcs: ["sigchain_test.cc"], + whole_static_libs: ["libsigchain"], +} diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc index b8ab51b629..61346b1487 100644 --- a/sigchainlib/sigchain.cc +++ b/sigchainlib/sigchain.cc @@ -29,8 +29,10 @@ #include <stdlib.h> #include <string.h> +#include <algorithm> #include <initializer_list> #include <mutex> +#include <type_traits> #include <utility> #include "sigchain.h" @@ -78,9 +80,28 @@ static void log(const char* format, ...) { #define fatal(...) log(__VA_ARGS__); abort() -static int sigorset(sigset_t* dest, sigset_t* left, sigset_t* right) { +#if defined(__BIONIC__) && !defined(__LP64__) +static int sigismember(const sigset64_t* sigset, int signum) { + return sigismember64(sigset, signum); +} + +static int sigemptyset(sigset64_t* sigset) { + return sigemptyset64(sigset); +} + +static int sigaddset(sigset64_t* sigset, int signum) { + return sigaddset64(sigset, signum); +} + +static int sigdelset(sigset64_t* sigset, int signum) { + return sigdelset64(sigset, signum); +} +#endif + +template<typename SigsetType> +static int sigorset(SigsetType* dest, SigsetType* left, SigsetType* right) { sigemptyset(dest); - for (size_t i = 0; i < sizeof(sigset_t) * CHAR_BIT; ++i) { + for (size_t i = 0; i < sizeof(SigsetType) * CHAR_BIT; ++i) { if (sigismember(left, i) == 1 || sigismember(right, i) == 1) { sigaddset(dest, i); } @@ -93,35 +114,36 @@ namespace art { static decltype(&sigaction) linked_sigaction; static decltype(&sigprocmask) linked_sigprocmask; +#if defined(__BIONIC__) +static decltype(&sigaction64) linked_sigaction64; +static decltype(&sigprocmask64) linked_sigprocmask64; +#endif + +template<typename T> +static void lookup_next_symbol(T* output, T wrapper, const char* name) { + void* sym = dlsym(RTLD_NEXT, name); + if (sym == nullptr) { + sym = dlsym(RTLD_DEFAULT, name); + if (sym == wrapper || sym == sigaction) { + fatal("Unable to find next %s in signal chain", name); + } + } + *output = reinterpret_cast<T>(sym); +} + __attribute__((constructor)) static void InitializeSignalChain() { static std::once_flag once; std::call_once(once, []() { - void* linked_sigaction_sym = dlsym(RTLD_NEXT, "sigaction"); - if (linked_sigaction_sym == nullptr) { - linked_sigaction_sym = dlsym(RTLD_DEFAULT, "sigaction"); - if (linked_sigaction_sym == nullptr || - linked_sigaction_sym == reinterpret_cast<void*>(sigaction)) { - fatal("Unable to find next sigaction in signal chain"); - } - } - - void* linked_sigprocmask_sym = dlsym(RTLD_NEXT, "sigprocmask"); - if (linked_sigprocmask_sym == nullptr) { - linked_sigprocmask_sym = dlsym(RTLD_DEFAULT, "sigprocmask"); - if (linked_sigprocmask_sym == nullptr || - linked_sigprocmask_sym == reinterpret_cast<void*>(sigprocmask)) { - fatal("Unable to find next sigprocmask in signal chain"); - } - } + lookup_next_symbol(&linked_sigaction, sigaction, "sigaction"); + lookup_next_symbol(&linked_sigprocmask, sigprocmask, "sigprocmask"); - linked_sigaction = - reinterpret_cast<decltype(linked_sigaction)>(linked_sigaction_sym); - linked_sigprocmask = - reinterpret_cast<decltype(linked_sigprocmask)>(linked_sigprocmask_sym); +#if defined(__BIONIC__) + lookup_next_symbol(&linked_sigaction64, sigaction64, "sigaction64"); + lookup_next_symbol(&linked_sigprocmask64, sigprocmask64, "sigprocmask64"); +#endif }); } - static pthread_key_t GetHandlingSignalKey() { static pthread_key_t key; static std::once_flag once; @@ -175,19 +197,51 @@ class SignalChain { // Register the signal chain with the kernel if needed. void Register(int signo) { +#if defined(__BIONIC__) + struct sigaction64 handler_action = {}; + sigfillset64(&handler_action.sa_mask); +#else struct sigaction handler_action = {}; + sigfillset(&handler_action.sa_mask); +#endif + handler_action.sa_sigaction = SignalChain::Handler; handler_action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; - sigfillset(&handler_action.sa_mask); + +#if defined(__BIONIC__) + linked_sigaction64(signo, &handler_action, &action_); +#else linked_sigaction(signo, &handler_action, &action_); +#endif } - void SetAction(const struct sigaction* action) { - action_ = *action; + template <typename SigactionType> + SigactionType GetAction() { + if constexpr (std::is_same_v<decltype(action_), SigactionType>) { + return action_; + } else { + SigactionType result; + result.sa_flags = action_.sa_flags; + result.sa_handler = action_.sa_handler; + result.sa_restorer = action_.sa_restorer; + memcpy(&result.sa_mask, &action_.sa_mask, + std::min(sizeof(action_.sa_mask), sizeof(result.sa_mask))); + return result; + } } - struct sigaction GetAction() { - return action_; + template <typename SigactionType> + void SetAction(const SigactionType* new_action) { + if constexpr (std::is_same_v<decltype(action_), SigactionType>) { + action_ = *new_action; + } else { + action_.sa_flags = new_action->sa_flags; + action_.sa_handler = new_action->sa_handler; + action_.sa_restorer = new_action->sa_restorer; + sigemptyset(&action_.sa_mask); + memcpy(&action_.sa_mask, &new_action->sa_mask, + std::min(sizeof(action_.sa_mask), sizeof(new_action->sa_mask))); + } } void AddSpecialHandler(SigchainAction* sa) { @@ -222,11 +276,17 @@ class SignalChain { private: bool claimed_; +#if defined(__BIONIC__) + struct sigaction64 action_; +#else struct sigaction action_; +#endif SigchainAction special_handlers_[2]; }; -static SignalChain chains[_NSIG]; +// _NSIG is 1 greater than the highest valued signal, but signals start from 1. +// Leave an empty element at index 0 for convenience. +static SignalChain chains[_NSIG + 1]; void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { // Try the special handlers first. @@ -260,12 +320,22 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { // Forward to the user's signal handler. int handler_flags = chains[signo].action_.sa_flags; ucontext_t* ucontext = static_cast<ucontext_t*>(ucontext_raw); +#if defined(__BIONIC__) + sigset64_t mask; + sigorset(&mask, &ucontext->uc_sigmask64, &chains[signo].action_.sa_mask); +#else sigset_t mask; sigorset(&mask, &ucontext->uc_sigmask, &chains[signo].action_.sa_mask); +#endif if (!(handler_flags & SA_NODEFER)) { sigaddset(&mask, signo); } + +#if defined(__BIONIC__) + linked_sigprocmask64(SIG_SETMASK, &mask, nullptr); +#else linked_sigprocmask(SIG_SETMASK, &mask, nullptr); +#endif if ((handler_flags & SA_SIGINFO)) { chains[signo].action_.sa_sigaction(signo, siginfo, ucontext_raw); @@ -281,20 +351,22 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { } } -extern "C" int sigaction(int signal, const struct sigaction* new_action, struct sigaction* old_action) { - InitializeSignalChain(); - +template <typename SigactionType> +static int __sigaction(int signal, const SigactionType* new_action, + SigactionType* old_action, + int (*linked)(int, const SigactionType*, + SigactionType*)) { // If this signal has been claimed as a signal chain, record the user's // action but don't pass it on to the kernel. // Note that we check that the signal number is in range here. An out of range signal // number should behave exactly as the libc sigaction. - if (signal < 0 || signal >= _NSIG) { + if (signal <= 0 || signal >= _NSIG) { errno = EINVAL; return -1; } if (chains[signal].IsClaimed()) { - struct sigaction saved_action = chains[signal].GetAction(); + SigactionType saved_action = chains[signal].GetAction<SigactionType>(); if (new_action != nullptr) { chains[signal].SetAction(new_action); } @@ -306,13 +378,27 @@ extern "C" int sigaction(int signal, const struct sigaction* new_action, struct // Will only get here if the signal chain has not been claimed. We want // to pass the sigaction on to the kernel via the real sigaction in libc. - return linked_sigaction(signal, new_action, old_action); + return linked(signal, new_action, old_action); +} + +extern "C" int sigaction(int signal, const struct sigaction* new_action, + struct sigaction* old_action) { + InitializeSignalChain(); + return __sigaction(signal, new_action, old_action, linked_sigaction); +} + +#if defined(__BIONIC__) +extern "C" int sigaction64(int signal, const struct sigaction64* new_action, + struct sigaction64* old_action) { + InitializeSignalChain(); + return __sigaction(signal, new_action, old_action, linked_sigaction64); } +#endif extern "C" sighandler_t signal(int signo, sighandler_t handler) { InitializeSignalChain(); - if (signo < 0 || signo > _NSIG) { + if (signo <= 0 || signo >= _NSIG) { errno = EINVAL; return SIG_ERR; } @@ -326,7 +412,8 @@ extern "C" sighandler_t signal(int signo, sighandler_t handler) { // If this signal has been claimed as a signal chain, record the user's // action but don't pass it on to the kernel. if (chains[signo].IsClaimed()) { - oldhandler = reinterpret_cast<sighandler_t>(chains[signo].GetAction().sa_handler); + oldhandler = reinterpret_cast<sighandler_t>( + chains[signo].GetAction<struct sigaction>().sa_handler); chains[signo].SetAction(&sa); return oldhandler; } @@ -348,23 +435,23 @@ extern "C" sighandler_t bsd_signal(int signo, sighandler_t handler) { } #endif -extern "C" int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) { - InitializeSignalChain(); - +template <typename SigsetType> +int __sigprocmask(int how, const SigsetType* new_set, SigsetType* old_set, + int (*linked)(int, const SigsetType*, SigsetType*)) { // When inside a signal handler, forward directly to the actual sigprocmask. if (GetHandlingSignal()) { - return linked_sigprocmask(how, bionic_new_set, bionic_old_set); + return linked(how, new_set, old_set); } - const sigset_t* new_set_ptr = bionic_new_set; - sigset_t tmpset; - if (bionic_new_set != nullptr) { - tmpset = *bionic_new_set; + const SigsetType* new_set_ptr = new_set; + SigsetType tmpset; + if (new_set != nullptr) { + tmpset = *new_set; - if (how == SIG_BLOCK) { + if (how == SIG_BLOCK || how == SIG_SETMASK) { // Don't allow claimed signals in the mask. If a signal chain has been claimed // we can't allow the user to block that signal. - for (int i = 0 ; i < _NSIG; ++i) { + for (int i = 1; i < _NSIG; ++i) { if (chains[i].IsClaimed() && sigismember(&tmpset, i)) { sigdelset(&tmpset, i); } @@ -373,9 +460,23 @@ extern "C" int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bi new_set_ptr = &tmpset; } - return linked_sigprocmask(how, new_set_ptr, bionic_old_set); + return linked(how, new_set_ptr, old_set); } +extern "C" int sigprocmask(int how, const sigset_t* new_set, + sigset_t* old_set) { + InitializeSignalChain(); + return __sigprocmask(how, new_set, old_set, linked_sigprocmask); +} + +#if defined(__BIONIC__) +extern "C" int sigprocmask64(int how, const sigset64_t* new_set, + sigset64_t* old_set) { + InitializeSignalChain(); + return __sigprocmask(how, new_set, old_set, linked_sigprocmask64); +} +#endif + extern "C" void AddSpecialSignalHandlerFn(int signal, SigchainAction* sa) { InitializeSignalChain(); diff --git a/sigchainlib/sigchain_test.cc b/sigchainlib/sigchain_test.cc new file mode 100644 index 0000000000..9f338ad3a2 --- /dev/null +++ b/sigchainlib/sigchain_test.cc @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include <signal.h> +#include <sys/syscall.h> + +#include <functional> + +#include <gtest/gtest.h> + +#include "sigchain.h" + +#if !defined(__BIONIC__) +typedef sigset_t sigset64_t; + +static int sigemptyset64(sigset64_t* set) { + return sigemptyset(set); +} + +static int sigismember64(sigset64_t* set, int member) { + return sigismember(set, member); +} +#endif + +static int RealSigprocmask(int how, const sigset64_t* new_sigset, sigset64_t* old_sigset) { + // glibc's sigset_t is overly large, so sizeof(*new_sigset) doesn't work. + return syscall(__NR_rt_sigprocmask, how, new_sigset, old_sigset, 8); +} + +class SigchainTest : public ::testing::Test { + void SetUp() final { + art::AddSpecialSignalHandlerFn(SIGSEGV, &action); + } + + void TearDown() final { + art::RemoveSpecialSignalHandlerFn(SIGSEGV, action.sc_sigaction); + } + + art::SigchainAction action = { + .sc_sigaction = [](int, siginfo_t*, void*) { return true; }, + .sc_mask = {}, + .sc_flags = 0, + }; +}; + + +static void TestSignalBlocking(std::function<void()> fn) { + // Unblock SIGSEGV, make sure it stays unblocked. + sigset64_t mask; + sigemptyset64(&mask); + ASSERT_EQ(0, RealSigprocmask(SIG_SETMASK, &mask, nullptr)) << strerror(errno); + + fn(); + + if (testing::Test::HasFatalFailure()) return; + ASSERT_EQ(0, RealSigprocmask(SIG_SETMASK, nullptr, &mask)); + ASSERT_FALSE(sigismember64(&mask, SIGSEGV)); +} + +TEST_F(SigchainTest, sigprocmask_setmask) { + TestSignalBlocking([]() { + sigset_t mask; + sigfillset(&mask); + ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, sigprocmask_block) { + TestSignalBlocking([]() { + sigset_t mask; + sigfillset(&mask); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &mask, nullptr)); + }); +} + +// bionic-only wide variants for LP32. +#if defined(__BIONIC__) +TEST_F(SigchainTest, sigprocmask64_setmask) { + TestSignalBlocking([]() { + sigset64_t mask; + sigfillset64(&mask); + ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, sigprocmask64_block) { + TestSignalBlocking([]() { + sigset64_t mask; + sigfillset64(&mask); + ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, pthread_sigmask64_setmask) { + TestSignalBlocking([]() { + sigset64_t mask; + sigfillset64(&mask); + ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, pthread_sigmask64_block) { + TestSignalBlocking([]() { + sigset64_t mask; + sigfillset64(&mask); + ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &mask, nullptr)); + }); +} +#endif + +// glibc doesn't implement most of these in terms of sigprocmask, which we rely on. +#if defined(__BIONIC__) +TEST_F(SigchainTest, pthread_sigmask_setmask) { + TestSignalBlocking([]() { + sigset_t mask; + sigfillset(&mask); + ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, pthread_sigmask_block) { + TestSignalBlocking([]() { + sigset_t mask; + sigfillset(&mask); + ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &mask, nullptr)); + }); +} + +TEST_F(SigchainTest, sigset_mask) { + TestSignalBlocking([]() { + sigset(SIGSEGV, SIG_HOLD); + }); +} + +TEST_F(SigchainTest, sighold) { + TestSignalBlocking([]() { + sighold(SIGSEGV); + }); +} + +#if defined(__BIONIC__) +// Not exposed via headers, but the symbols are available if you declare them yourself. +extern "C" int sigblock(int); +extern "C" int sigsetmask(int); +#endif + +TEST_F(SigchainTest, sigblock) { + TestSignalBlocking([]() { + int mask = ~0U; + ASSERT_EQ(0, sigblock(mask)); + }); +} + +TEST_F(SigchainTest, sigsetmask) { + TestSignalBlocking([]() { + int mask = ~0U; + ASSERT_EQ(0, sigsetmask(mask)); + }); +} + +#endif diff --git a/sigchainlib/version-script32.txt b/sigchainlib/version-script32.txt index 2340785c42..e8a18e772c 100644 --- a/sigchainlib/version-script32.txt +++ b/sigchainlib/version-script32.txt @@ -5,8 +5,10 @@ global: RemoveSpecialSignalHandlerFn; bsd_signal; sigaction; + sigaction64; signal; sigprocmask; + sigprocmask64; local: *; }; diff --git a/sigchainlib/version-script64.txt b/sigchainlib/version-script64.txt index acf36309ea..72c86a1ba8 100644 --- a/sigchainlib/version-script64.txt +++ b/sigchainlib/version-script64.txt @@ -4,8 +4,10 @@ global: AddSpecialSignalHandlerFn; RemoveSpecialSignalHandlerFn; sigaction; + sigaction64; signal; sigprocmask; + sigprocmask64; local: *; }; diff --git a/test/004-SignalTest/signaltest.cc b/test/004-SignalTest/signaltest.cc index a58a0752c9..67118d5e63 100644 --- a/test/004-SignalTest/signaltest.cc +++ b/test/004-SignalTest/signaltest.cc @@ -99,6 +99,15 @@ static void signalhandler(int sig ATTRIBUTE_UNUSED, siginfo_t* info ATTRIBUTE_UN static struct sigaction oldaction; +bool compare_sigaction(const struct sigaction* lhs, const struct sigaction* rhs) { + // bionic's definition of `struct sigaction` has internal padding bytes, so we can't just do a + // naive memcmp of the entire struct. + return memcmp(&lhs->sa_mask, &rhs->sa_mask, sizeof(lhs->sa_mask)) == 0 && + lhs->sa_sigaction == rhs->sa_sigaction && + lhs->sa_flags == rhs->sa_flags && + lhs->sa_restorer == rhs->sa_restorer; +} + extern "C" JNIEXPORT void JNICALL Java_Main_initSignalTest(JNIEnv*, jclass) { struct sigaction action; action.sa_sigaction = signalhandler; @@ -112,8 +121,15 @@ extern "C" JNIEXPORT void JNICALL Java_Main_initSignalTest(JNIEnv*, jclass) { sigaction(SIGSEGV, &action, &oldaction); struct sigaction check; sigaction(SIGSEGV, nullptr, &check); - if (memcmp(&action, &check, sizeof(action)) != 0) { + if (!compare_sigaction(&check, &action)) { printf("sigaction returned different value\n"); + printf("action.sa_mask = %p, check.sa_mask = %p\n", + *reinterpret_cast<void**>(&action.sa_mask), + *reinterpret_cast<void**>(&check.sa_mask)); + printf("action.sa_sigaction = %p, check.sa_sigaction = %p\n", + action.sa_sigaction, check.sa_sigaction); + printf("action.sa_flags = %x, check.sa_flags = %x\n", + action.sa_flags, check.sa_flags); } signal(BLOCKED_SIGNAL, blocked_signal); signal(UNBLOCKED_SIGNAL, unblocked_signal); diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt index 343a76247e..06f5979f3e 100644 --- a/test/115-native-bridge/expected.txt +++ b/test/115-native-bridge/expected.txt @@ -63,6 +63,8 @@ trampoline_Java_Main_testNewStringObject called! Getting trampoline for Java_Main_testSignal with shorty I. NB signal handler with signal 11. NB signal handler with signal 4. +NB signal handler with signal 11. +NB signal handler with signal 4. Loading invalid library 'libinvalid.so' from Java, which will fail. Checking for support. Was to load 'libinvalid.so', force fail. diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc index a049b97adc..3b352096df 100644 --- a/test/115-native-bridge/nativebridge.cc +++ b/test/115-native-bridge/nativebridge.cc @@ -224,6 +224,22 @@ static jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) { sigaction(SIGILL, &tmp, nullptr); kill(getpid(), SIGILL); +#if defined(__BIONIC__) + // Do the same again, but with sigaction64. + struct sigaction64 tmp2; + sigemptyset64(&tmp2.sa_mask); + tmp2.sa_sigaction = test_sigaction_handler; + tmp2.sa_restorer = nullptr; + + sigaction64(SIGSEGV, &tmp2, nullptr); + sigaction64(SIGILL, &tmp2, nullptr); +#endif + + // Reraise SIGSEGV/SIGILL even on non-bionic, so that the expected output is + // the same. + raise_sigsegv(); + kill(getpid(), SIGILL); + return 1234; } diff --git a/test/1926-missed-frame-pop/src/art/Test1926.java b/test/1926-missed-frame-pop/src/art/Test1926.java index cb210729a9..1c6c33a9e6 100644 --- a/test/1926-missed-frame-pop/src/art/Test1926.java +++ b/test/1926-missed-frame-pop/src/art/Test1926.java @@ -166,17 +166,22 @@ public class Test1926 { public static void doRecurTestWith(final int times, int watch_frame) throws Exception { final String target_method_name_start = "recurTimes"; final ThreadPauser safepoint = new ThreadPauser(); - Thread target = new Thread(() -> { - recurTimesA(times, () -> { - safepoint.run(); - disableFramePop(null); - }); - System.out.println("Ran recurTimes(" + times + ") without errors after disabling " + - "frame pop event!"); - System.out.println("renabling frame pop event with similar stack."); - recurTimesB(times, () -> { reenableFramePop(null); }); - System.out.println("Ran recurTimes(" + times + ") without errors!"); - }); + // We need to make the stack bigger since ASAN causes SOE if we don't. + Thread target = new Thread( + /*thread Group*/ null, + () -> { + recurTimesA(times, () -> { + safepoint.run(); + disableFramePop(null); + }); + System.out.println("Ran recurTimes(" + times + ") without errors after disabling " + + "frame pop event!"); + System.out.println("renabling frame pop event with similar stack."); + recurTimesB(times, () -> { reenableFramePop(null); }); + System.out.println("Ran recurTimes(" + times + ") without errors!"); + }, + "Test1926-Thread", + /*10 mb stack*/10 * 1024 * 1024); target.start(); safepoint.waitForOtherThreadToPause(); Suspension.suspend(target); diff --git a/test/714-invoke-custom-lambda-metafactory/expected.txt b/test/714-invoke-custom-lambda-metafactory/expected.txt index 54b6c24798..c98a4c244d 100644 --- a/test/714-invoke-custom-lambda-metafactory/expected.txt +++ b/test/714-invoke-custom-lambda-metafactory/expected.txt @@ -1,5 +1,5 @@ Exception in thread "main" java.lang.BootstrapMethodError: Exception from call site #0 bootstrap method at Main.main(Main.java:25) -Caused by: java.lang.NullPointerException: Bootstrap method returned null +Caused by: java.lang.ClassCastException: Bootstrap method returned null ... 1 more exit status: 1 diff --git a/test/952-invoke-custom-lookup/build b/test/952-invoke-custom-lookup/build deleted file mode 100644 index f3fe95c135..0000000000 --- a/test/952-invoke-custom-lookup/build +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# -# Copyright 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. - -# make us exit on a failure -set -e - -# This test uses previously prepared dex and jar files. They need to -# be re-packaged to match the files that the run-test-jar script -# expects. -if [[ $@ != *"--jvm"* ]]; then - zip ${TEST_NAME}.jar classes.dex -else - unzip -d classes classes.jar -fi diff --git a/test/952-invoke-custom-lookup/classes.dex b/test/952-invoke-custom-lookup/classes.dex Binary files differdeleted file mode 100644 index 670d93dedf..0000000000 --- a/test/952-invoke-custom-lookup/classes.dex +++ /dev/null diff --git a/test/952-invoke-custom-lookup/classes.jar b/test/952-invoke-custom-lookup/classes.jar Binary files differdeleted file mode 100644 index aa6a1f65fa..0000000000 --- a/test/952-invoke-custom-lookup/classes.jar +++ /dev/null diff --git a/test/952-invoke-custom-lookup/expected.txt b/test/952-invoke-custom-lookup/expected.txt deleted file mode 100644 index 0da2b866d2..0000000000 --- a/test/952-invoke-custom-lookup/expected.txt +++ /dev/null @@ -1,10 +0,0 @@ -NAME: 1 -CALLER: Main -CALLER CLASS: class Main -THIS CLASS: class com.android.tools.r8.maindexlist.desugar.BootstrapHolder -invokedynamic target on Main -NAME: 2 -CALLER: Main -CALLER CLASS: class Main -THIS CLASS: class com.android.tools.r8.maindexlist.desugar.BootstrapHolder -invokedynamic target on BootstrapHolder diff --git a/test/952-invoke-custom-lookup/info.txt b/test/952-invoke-custom-lookup/info.txt deleted file mode 100644 index 3bfe87dfd3..0000000000 --- a/test/952-invoke-custom-lookup/info.txt +++ /dev/null @@ -1 +0,0 @@ -A temporary test for the lookup class used for invoke-custom (see b/73056094). diff --git a/test/952-invoke-custom/build b/test/952-invoke-custom/build index 2b0b2c1274..2caca94d7f 100644..100755 --- a/test/952-invoke-custom/build +++ b/test/952-invoke-custom/build @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright 2016 The Android Open Source Project +# Copyright 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. @@ -17,4 +17,36 @@ # make us exit on a failure set -e -./default-build "$@" --experimental method-handles +ASM_JAR="${ANDROID_BUILD_TOP}/prebuilts/misc/common/asm/asm-6.0.jar" +INTERMEDIATE_CLASSES=classes-intermediate +CLASSES=classes + +DEXER="${DX:-dx}" +if [ "${USE_D8=false}" = "true" ]; then + DEXER="${ANDROID_HOST_OUT}/bin/d8-compat-dx" +fi + +# Create directory for intermediate classes +rm -rf "${INTERMEDIATE_CLASSES}" +mkdir "${INTERMEDIATE_CLASSES}" + +# Generate intermediate classes that will allow transform to be applied to test classes +JAVAC_ARGS="${JAVAC_ARGS} -source 1.8 -target 1.8 -cp ${ASM_JAR}" +${JAVAC:-javac} ${JAVAC_ARGS} -d ${INTERMEDIATE_CLASSES} $(find src -name '*.java') + +# Create directory for transformed classes +rm -rf "${CLASSES}" +mkdir "${CLASSES}" + +# Run transform +for class in ${INTERMEDIATE_CLASSES}/*.class ; do + transformed_class=${CLASSES}/$(basename ${class}) + ${JAVA:-java} -cp "${ASM_JAR}:${INTERMEDIATE_CLASSES}" transformer.IndyTransformer ${class} ${transformed_class} +done + +# Create DEX +DX_FLAGS="${DX_FLAGS} --min-sdk-version=26 --debug --dump-width=1000" +${DEXER} -JXmx256m --dex ${DX_FLAGS} --dump-to=${CLASSES}.lst --output=classes.dex ${CLASSES} + +# Zip DEX to file name expected by test runner +zip ${TEST_NAME:-classes-dex}.jar classes.dex diff --git a/test/952-invoke-custom/expected.txt b/test/952-invoke-custom/expected.txt index bb87296e60..be01c453fb 100644 --- a/test/952-invoke-custom/expected.txt +++ b/test/952-invoke-custom/expected.txt @@ -1,14 +1,15 @@ Caught exception from uninitialized call site Caught exception from uninitialized call site linkerMethod failure type 1 -Returning null instead of CallSite for add (int,int)int +Returning null instead of CallSite for _add (int,int)int linkerMethod failure type 2 Throwing InstantiationException in linkerMethod() linkerMethod failure type 3 Throwing ArithmeticException in add() Failure Type + 0 (1013) -Linking add (int,int)int +Linking _add (int,int)int 100 -9000 9000 +TestLinkerUnrelatedBSM Winners 1 Votes 16 diff --git a/test/952-invoke-custom/generator/TestInvokeCustomWithConcurrentThreads.java b/test/952-invoke-custom/generator/TestInvokeCustomWithConcurrentThreads.java deleted file mode 100644 index 9c0645b5af..0000000000 --- a/test/952-invoke-custom/generator/TestInvokeCustomWithConcurrentThreads.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import com.android.jack.annotations.CalledByInvokeCustom; -import com.android.jack.annotations.Constant; -import com.android.jack.annotations.LinkerMethodHandle; -import com.android.jack.annotations.MethodHandleKind; - -import java.lang.invoke.CallSite; -import java.lang.invoke.ConstantCallSite; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import java.lang.Thread; -import java.lang.ThreadLocal; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.CyclicBarrier; - -public class TestInvokeCustomWithConcurrentThreads extends Thread { - private static final int NUMBER_OF_THREADS = 16; - - private static final AtomicInteger nextIndex = new AtomicInteger(0); - - private static final ThreadLocal<Integer> threadIndex = - new ThreadLocal<Integer>() { - @Override - protected Integer initialValue() { - return nextIndex.getAndIncrement(); - } - }; - - // Array of call sites instantiated, one per thread - private static final CallSite[] instantiated = new CallSite[NUMBER_OF_THREADS]; - - // Array of counters for how many times each instantiated call site is called - private static final AtomicInteger[] called = new AtomicInteger[NUMBER_OF_THREADS]; - - // Array of call site indicies of which call site a thread invoked - private static final AtomicInteger[] targetted = new AtomicInteger[NUMBER_OF_THREADS]; - - // Synchronization barrier all threads will wait on in the bootstrap method. - private static final CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_THREADS); - - private TestInvokeCustomWithConcurrentThreads() {} - - private static int getThreadIndex() { - return threadIndex.get().intValue(); - } - - public static int notUsed(int x) { - return x; - } - - @Override - public void run() { - int x = setCalled(-1 /* argument dropped */); - notUsed(x); - } - - @CalledByInvokeCustom( - invokeMethodHandle = @LinkerMethodHandle(kind = MethodHandleKind.INVOKE_STATIC, - enclosingType = TestInvokeCustomWithConcurrentThreads.class, - name = "linkerMethod", - argumentTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}), - name = "setCalled", - returnType = int.class, - argumentTypes = {int.class}) - private static int setCalled(int index) { - called[index].getAndIncrement(); - targetted[getThreadIndex()].set(index); - return 0; - } - - @SuppressWarnings("unused") - private static CallSite linkerMethod(MethodHandles.Lookup caller, - String name, - MethodType methodType) throws Throwable { - int threadIndex = getThreadIndex(); - MethodHandle mh = - caller.findStatic(TestInvokeCustomWithConcurrentThreads.class, name, methodType); - assertEquals(methodType, mh.type()); - assertEquals(mh.type().parameterCount(), 1); - mh = MethodHandles.insertArguments(mh, 0, threadIndex); - mh = MethodHandles.dropArguments(mh, 0, int.class); - assertEquals(mh.type().parameterCount(), 1); - assertEquals(methodType, mh.type()); - - // Wait for all threads to be in this method. - // Multiple call sites should be created, but only one - // invoked. - barrier.await(); - - instantiated[getThreadIndex()] = new ConstantCallSite(mh); - return instantiated[getThreadIndex()]; - } - - public static void test() throws Throwable { - // Initialize counters for which call site gets invoked - for (int i = 0; i < NUMBER_OF_THREADS; ++i) { - called[i] = new AtomicInteger(0); - targetted[i] = new AtomicInteger(0); - } - - // Run threads that each invoke-custom the call site - Thread [] threads = new Thread[NUMBER_OF_THREADS]; - for (int i = 0; i < NUMBER_OF_THREADS; ++i) { - threads[i] = new TestInvokeCustomWithConcurrentThreads(); - threads[i].start(); - } - - // Wait for all threads to complete - for (int i = 0; i < NUMBER_OF_THREADS; ++i) { - threads[i].join(); - } - - // Check one call site instance won - int winners = 0; - int votes = 0; - for (int i = 0; i < NUMBER_OF_THREADS; ++i) { - assertNotEquals(instantiated[i], null); - if (called[i].get() != 0) { - winners++; - votes += called[i].get(); - } - } - - System.out.println("Winners " + winners + " Votes " + votes); - - // We assert this below but output details when there's an error as - // it's non-deterministic. - if (winners != 1) { - System.out.println("Threads did not the same call-sites:"); - for (int i = 0; i < NUMBER_OF_THREADS; ++i) { - System.out.format(" Thread % 2d invoked call site instance #%02d\n", - i, targetted[i].get()); - } - } - - // We assert this below but output details when there's an error as - // it's non-deterministic. - if (votes != NUMBER_OF_THREADS) { - System.out.println("Call-sites invocations :"); - for (int i = 0; i < NUMBER_OF_THREADS; ++i) { - System.out.format(" Call site instance #%02d was invoked % 2d times\n", - i, called[i].get()); - } - } - - assertEquals(winners, 1); - assertEquals(votes, NUMBER_OF_THREADS); - } - - public static void assertTrue(boolean value) { - if (!value) { - throw new AssertionError("assertTrue value: " + value); - } - } - - public static void assertEquals(byte b1, byte b2) { - if (b1 == b2) { return; } - throw new AssertionError("assertEquals b1: " + b1 + ", b2: " + b2); - } - - public static void assertEquals(char c1, char c2) { - if (c1 == c2) { return; } - throw new AssertionError("assertEquals c1: " + c1 + ", c2: " + c2); - } - - public static void assertEquals(short s1, short s2) { - if (s1 == s2) { return; } - throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); - } - - public static void assertEquals(int i1, int i2) { - if (i1 == i2) { return; } - throw new AssertionError("assertEquals i1: " + i1 + ", i2: " + i2); - } - - public static void assertEquals(long l1, long l2) { - if (l1 == l2) { return; } - throw new AssertionError("assertEquals l1: " + l1 + ", l2: " + l2); - } - - public static void assertEquals(float f1, float f2) { - if (f1 == f2) { return; } - throw new AssertionError("assertEquals f1: " + f1 + ", f2: " + f2); - } - - public static void assertEquals(double d1, double d2) { - if (d1 == d2) { return; } - throw new AssertionError("assertEquals d1: " + d1 + ", d2: " + d2); - } - - public static void assertEquals(Object o, Object p) { - if (o == p) { return; } - if (o != null && p != null && o.equals(p)) { return; } - throw new AssertionError("assertEquals: o1: " + o + ", o2: " + p); - } - - public static void assertNotEquals(Object o, Object p) { - if (o != p) { return; } - if (o != null && p != null && !o.equals(p)) { return; } - throw new AssertionError("assertNotEquals: o1: " + o + ", o2: " + p); - } - - public static void assertEquals(String s1, String s2) { - if (s1 == s2) { - return; - } - - if (s1 != null && s2 != null && s1.equals(s2)) { - return; - } - - throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); - } -} diff --git a/test/952-invoke-custom/generator/TestLinkerMethodMinimalArguments.java b/test/952-invoke-custom/generator/TestLinkerMethodMinimalArguments.java deleted file mode 100644 index 93d96a9a7b..0000000000 --- a/test/952-invoke-custom/generator/TestLinkerMethodMinimalArguments.java +++ /dev/null @@ -1,137 +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 com.android.jack.annotations.CalledByInvokeCustom; -import com.android.jack.annotations.Constant; -import com.android.jack.annotations.LinkerMethodHandle; -import com.android.jack.annotations.MethodHandleKind; - -import java.lang.invoke.CallSite; -import java.lang.invoke.ConstantCallSite; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -public class TestLinkerMethodMinimalArguments { - - private static int forceFailureType = 0; - - private static int FAILURE_TYPE_NONE = 0; - private static int FAILURE_TYPE_LINKER_METHOD_RETURNS_NULL = 1; - private static int FAILURE_TYPE_LINKER_METHOD_THROWS = 2; - private static int FAILURE_TYPE_TARGET_METHOD_THROWS = 3; - - @CalledByInvokeCustom( - invokeMethodHandle = @LinkerMethodHandle( - kind = MethodHandleKind.INVOKE_STATIC, - enclosingType = TestLinkerMethodMinimalArguments.class, - argumentTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}, - name = "linkerMethod"), - name = "add", - returnType = int.class, - argumentTypes = {int.class, int.class}) - private static int add(int a, int b) { - if (forceFailureType == FAILURE_TYPE_TARGET_METHOD_THROWS) { - System.out.println("Throwing ArithmeticException in add()"); - throw new ArithmeticException("add"); - } - return a + b; - } - - @SuppressWarnings("unused") - private static CallSite linkerMethod(MethodHandles.Lookup caller, String name, - MethodType methodType) throws Throwable { - System.out.println("linkerMethod failure type " + forceFailureType); - MethodHandle mh_add = - caller.findStatic(TestLinkerMethodMinimalArguments.class, name, methodType); - if (forceFailureType == FAILURE_TYPE_LINKER_METHOD_RETURNS_NULL) { - System.out.println("Returning null instead of CallSite for " + name + " " + methodType); - return null; - } else if (forceFailureType == FAILURE_TYPE_LINKER_METHOD_THROWS) { - System.out.println("Throwing InstantiationException in linkerMethod()"); - throw new InstantiationException("linkerMethod"); - } else { - return new ConstantCallSite(mh_add); - } - } - - public static void test(int failureType, int x, int y) throws Throwable { - assertTrue(failureType >= FAILURE_TYPE_NONE); - assertTrue(failureType <= FAILURE_TYPE_TARGET_METHOD_THROWS); - forceFailureType = failureType; - assertEquals(x + y, add(x, y)); - System.out.println("Failure Type + " + failureType + " (" + x + y+ ")"); - } - - public static void assertTrue(boolean value) { - if (!value) { - throw new AssertionError("assertTrue value: " + value); - } - } - - public static void assertEquals(byte b1, byte b2) { - if (b1 == b2) { return; } - throw new AssertionError("assertEquals b1: " + b1 + ", b2: " + b2); - } - - public static void assertEquals(char c1, char c2) { - if (c1 == c2) { return; } - throw new AssertionError("assertEquals c1: " + c1 + ", c2: " + c2); - } - - public static void assertEquals(short s1, short s2) { - if (s1 == s2) { return; } - throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); - } - - public static void assertEquals(int i1, int i2) { - if (i1 == i2) { return; } - throw new AssertionError("assertEquals i1: " + i1 + ", i2: " + i2); - } - - public static void assertEquals(long l1, long l2) { - if (l1 == l2) { return; } - throw new AssertionError("assertEquals l1: " + l1 + ", l2: " + l2); - } - - public static void assertEquals(float f1, float f2) { - if (f1 == f2) { return; } - throw new AssertionError("assertEquals f1: " + f1 + ", f2: " + f2); - } - - public static void assertEquals(double d1, double d2) { - if (d1 == d2) { return; } - throw new AssertionError("assertEquals d1: " + d1 + ", d2: " + d2); - } - - public static void assertEquals(Object o, Object p) { - if (o == p) { return; } - if (o != null && p != null && o.equals(p)) { return; } - throw new AssertionError("assertEquals: o1: " + o + ", o2: " + p); - } - - public static void assertEquals(String s1, String s2) { - if (s1 == s2) { - return; - } - - if (s1 != null && s2 != null && s1.equals(s2)) { - return; - } - - throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); - } -} diff --git a/test/952-invoke-custom/generator/TestLinkerMethodMultipleArgumentTypes.java b/test/952-invoke-custom/generator/TestLinkerMethodMultipleArgumentTypes.java deleted file mode 100644 index 4e4d97e15e..0000000000 --- a/test/952-invoke-custom/generator/TestLinkerMethodMultipleArgumentTypes.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import com.android.jack.annotations.CalledByInvokeCustom; -import com.android.jack.annotations.Constant; -import com.android.jack.annotations.LinkerMethodHandle; -import com.android.jack.annotations.MethodHandleKind; - -import java.lang.invoke.CallSite; -import java.lang.invoke.ConstantCallSite; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -public class TestLinkerMethodMultipleArgumentTypes { - - private static int bootstrapRunCount = 0; - - @CalledByInvokeCustom( - invokeMethodHandle = @LinkerMethodHandle(kind = MethodHandleKind.INVOKE_STATIC, - enclosingType = TestLinkerMethodMultipleArgumentTypes.class, - name = "linkerMethod", - argumentTypes = {MethodHandles.Lookup.class, String.class, MethodType.class, - boolean.class, byte.class, char.class, short.class, int.class, - float.class, double.class, String.class, Class.class, long.class}), - methodHandleExtraArgs = {@Constant(booleanValue = true), @Constant(byteValue = 1), - @Constant(charValue = 'a'), @Constant(shortValue = 1024), - @Constant(intValue = 1), @Constant(floatValue = 11.1f), - @Constant(doubleValue = 2.2), @Constant(stringValue = "Hello"), - @Constant(classValue = TestLinkerMethodMultipleArgumentTypes.class), - @Constant(longValue = 123456789L)}, - name = "add", - returnType = int.class, - argumentTypes = {int.class, int.class}) - private static int add(int a, int b) { - return a + b; - } - - @SuppressWarnings("unused") - private static CallSite linkerMethod(MethodHandles.Lookup caller, String name, - MethodType methodType, boolean v1, byte v2, char v3, - short v4, int v5, float v6, double v7, - String v8, Class<?> v9, long v10) throws Throwable { - System.out.println("Linking " + name + " " + methodType); - assertTrue(v1); - assertEquals(1, v2); - assertEquals('a', v3); - assertEquals(1024, v4); - assertEquals(1, v5); - assertEquals(11.1f, v6); - assertEquals(2.2, v7); - assertEquals("Hello", v8); - assertEquals(TestLinkerMethodMultipleArgumentTypes.class, v9); - assertEquals(123456789L, v10); - MethodHandle mh_add = - caller.findStatic(TestLinkerMethodMultipleArgumentTypes.class, name, methodType); - return new ConstantCallSite(mh_add); - } - - public int GetBootstrapRunCount() { - return bootstrapRunCount; - } - - public static void test(int x, int y) throws Throwable { - assertEquals(x + y, add(x, y)); - System.out.println(x + y); - } - - public static void assertTrue(boolean value) { - if (!value) { - throw new AssertionError("assertTrue value: " + value); - } - } - - public static void assertEquals(byte b1, byte b2) { - if (b1 == b2) { return; } - throw new AssertionError("assertEquals b1: " + b1 + ", b2: " + b2); - } - - public static void assertEquals(char c1, char c2) { - if (c1 == c2) { return; } - throw new AssertionError("assertEquals c1: " + c1 + ", c2: " + c2); - } - - public static void assertEquals(short s1, short s2) { - if (s1 == s2) { return; } - throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); - } - - public static void assertEquals(int i1, int i2) { - if (i1 == i2) { return; } - throw new AssertionError("assertEquals i1: " + i1 + ", i2: " + i2); - } - - public static void assertEquals(long l1, long l2) { - if (l1 == l2) { return; } - throw new AssertionError("assertEquals l1: " + l1 + ", l2: " + l2); - } - - public static void assertEquals(float f1, float f2) { - if (f1 == f2) { return; } - throw new AssertionError("assertEquals f1: " + f1 + ", f2: " + f2); - } - - public static void assertEquals(double d1, double d2) { - if (d1 == d2) { return; } - throw new AssertionError("assertEquals d1: " + d1 + ", d2: " + d2); - } - - public static void assertEquals(Object o, Object p) { - if (o == p) { return; } - if (o != null && p != null && o.equals(p)) { return; } - throw new AssertionError("assertEquals: o1: " + o + ", o2: " + p); - } - - public static void assertEquals(String s1, String s2) { - if (s1 == s2) { - return; - } - - if (s1 != null && s2 != null && s1.equals(s2)) { - return; - } - - throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); - } -} diff --git a/test/952-invoke-custom/generator/build-test.sh b/test/952-invoke-custom/generator/build-test.sh deleted file mode 100755 index d1d8221261..0000000000 --- a/test/952-invoke-custom/generator/build-test.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Set up prog to be the path of this script, including following symlinks, -# and set up progdir to be the fully-qualified pathname of its directory. -prog="$0" -args="$@" -while [ -h "${prog}" ]; do - newProg=`/bin/ls -ld "${prog}"` - newProg=`expr "${newProg}" : ".* -> \(.*\)$"` - if expr "x${newProg}" : 'x/' >/dev/null; then - prog="${newProg}" - else - progdir=`dirname "${prog}"` - prog="${progdir}/${newProg}" - fi -done -oldwd=`pwd` -progdir=`dirname "${prog}"` -cd "${progdir}" -progdir=`pwd` -prog="${progdir}"/`basename "${prog}"` -test_dir="test-$$" -if [ -z "$TMPDIR" ]; then - tmp_dir="/tmp/$USER/${test_dir}" -else - tmp_dir="${TMPDIR}/${test_dir}" -fi - -if [ "x$ANDROID_BUILD_TOP" = "x" ]; then - echo Build environment is not set-up. - exit -1 -fi - -# This only works internally for now (sorry folks!) -jack_annotations_lib=/google/data/rw/teams/android-runtime/jack/jack-test-annotations-lib.jack -if [ ! -f $jack_annotations_lib ]; then - echo Try 'prodaccess' to access android-runtime directory. - exit -1 -fi - -# Compile test into a base64 string that can be instantiated via -# reflection on hosts without the jack-test-annotations-lib.jack file. -mkdir $tmp_dir -for input_file in $progdir/*.java; do - i=${input_file##*/Test} - i=${i%%.java} - src_file=$progdir/Test$i.java - jack_file=./src.jack - dex_file=./classes.dex - base_64_file=$tmp_dir/TestData$i.base64 - output_file=$progdir/../src/TestData$i.java - # Compile source file to jack file. - jack -g -cp $ANDROID_BUILD_TOP/out/host/linux-x86/../common/obj/JAVA_LIBRARIES/core-libart-hostdex_intermediates/classes.jack:$ANDROID_BUILD_TOP/out/host/linux-x86/../common/obj/JAVA_LIBRARIES/core-oj-hostdex_intermediates/classes.jack:$jack_annotations_lib -D sched.runner=multi-threaded -D sched.runner.thread.kind=fixed -D sched.runner.thread.fixed.count=4 -D jack.java.source.version=1.7 -D jack.android.min-api-level=o-b2 --output-jack $jack_file $src_file - # Compile jack file to classes.dex. - jack -g -cp $ANDROID_BUILD_TOP/out/host/linux-x86/../common/obj/JAVA_LIBRARIES/core-libart-hostdex_intermediates/classes.jack:$ANDROID_BUILD_TOP/out/host/linux-x86/../common/obj/JAVA_LIBRARIES/core-oj-hostdex_intermediates/classes.jack -D sched.runner=multi-threaded -D sched.runner.thread.kind=fixed -D sched.runner.thread.fixed.count=4 -D jack.java.source.version=1.7 -D jack.android.min-api-level=o-b2 --import $jack_file --output-dex . - # Pack the classes.dex file into a base64 string. - base64 -w 72 $dex_file > $base_64_file - # Emit a managed source file containing the base64 string. The test can be - # run by loading this string as a dex file and invoking it via reflection. -cat > $output_file <<HEADER -/* Generated by ${prog##*/} from ${src_file##*/} */ -public class TestData$i { - public static final String BASE64_DEX_FILE = -HEADER -sed -e 's/^\(.*\)$/ "\1" +/' -e '$s/ +/;/' $base_64_file >> $output_file -cat >> $output_file <<FOOTER -} -FOOTER - rm $dex_file $jack_file -done - -rm -rf $tmp_dir diff --git a/test/952-invoke-custom/info.txt b/test/952-invoke-custom/info.txt index 2954e55137..1dce686812 100644 --- a/test/952-invoke-custom/info.txt +++ b/test/952-invoke-custom/info.txt @@ -1,9 +1 @@ -A test that is only available as a DEX binary. - -This tests execution of invoke-custom. There is no bytecode to emit -invoke-custom directly. This test is generated using an internal only jack file. - -Internal developers MUST regenerate the test data files after editing -the tests under generator/ using: - -$ generator/build-tests.sh +Tests the invoke-custom bytecode. diff --git a/test/952-invoke-custom/src-art/Main.java b/test/952-invoke-custom/src-art/Main.java deleted file mode 100644 index 2abc3122fa..0000000000 --- a/test/952-invoke-custom/src-art/Main.java +++ /dev/null @@ -1,159 +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 dalvik.system.InMemoryDexClassLoader; - -import java.lang.invoke.CallSite; -import java.lang.invoke.MethodType; -import java.lang.invoke.MutableCallSite; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.ByteBuffer; -import java.util.Base64; - -// This test is a stop-gap until we have support for generating invoke-custom -// in the Android tree. - -public class Main { - - private static void TestUninitializedCallSite() throws Throwable { - CallSite callSite = new MutableCallSite(MethodType.methodType(int.class)); - try { - callSite.getTarget().invoke(); - fail(); - } catch (IllegalStateException e) { - System.out.println("Caught exception from uninitialized call site"); - } - - callSite = new MutableCallSite(MethodType.methodType(String.class, int.class, char.class)); - try { - callSite.getTarget().invoke(1535, 'd'); - fail(); - } catch (IllegalStateException e) { - System.out.println("Caught exception from uninitialized call site"); - } - } - - private static void TestLinkerMethodMultipleArgumentTypes() throws Throwable { - // This is a more comprehensive test of invoke-custom, the linker - // method takes additional arguments of types boolean, byte, char, - // short, int, float, double, String, Class, and long (in this order) - // The test asserts the values passed to the linker method match their - // expected values. - byte[] base64Data = TestDataLinkerMethodMultipleArgumentTypes.BASE64_DEX_FILE.getBytes(); - Base64.Decoder decoder = Base64.getDecoder(); - ByteBuffer dexBuffer = ByteBuffer.wrap(decoder.decode(base64Data)); - - InMemoryDexClassLoader classLoader = - new InMemoryDexClassLoader(dexBuffer, - ClassLoader.getSystemClassLoader()); - Class<?> testClass = - classLoader.loadClass("TestLinkerMethodMultipleArgumentTypes"); - Method testMethod = testClass.getDeclaredMethod("test", int.class, int.class); - // First invocation should link via the bootstrap method (outputs "Linking add" ...). - testMethod.invoke(null, 33, 67); - // Subsequent invocations use the cached value of the CallSite and do not require linking. - testMethod.invoke(null, -10000, +1000); - testMethod.invoke(null, -1000, +10000); - } - - private static void TestLinkerMethodMinimalArguments() throws Throwable { - // This test checks various failures when running the linker - // method and during invocation of the method handle. - byte[] base64Data = TestDataLinkerMethodMinimalArguments.BASE64_DEX_FILE.getBytes(); - Base64.Decoder decoder = Base64.getDecoder(); - ByteBuffer dexBuffer = ByteBuffer.wrap(decoder.decode(base64Data)); - - InMemoryDexClassLoader classLoader = - new InMemoryDexClassLoader(dexBuffer, - ClassLoader.getSystemClassLoader()); - Class<?> testClass = - classLoader.loadClass("TestLinkerMethodMinimalArguments"); - Method testMethod = testClass.getDeclaredMethod("test", int.class, int.class, int.class); - - try { - testMethod.invoke(null, 1 /* linker method return null */, 10, 10); - } catch (InvocationTargetException e) { - assertEquals(e.getCause().getClass().getName(), "java.lang.BootstrapMethodError"); - assertEquals( - e.getCause().getCause().getClass().getName(), "java.lang.NullPointerException"); - } - - try { - testMethod.invoke(null, 2 /* linker method throw InstantiationException */, 10, 11); - } catch (InvocationTargetException e) { - assertEquals(e.getCause().getClass().getName(), "java.lang.BootstrapMethodError"); - assertEquals( - e.getCause().getCause().getClass().getName(), "java.lang.InstantiationException"); - } - try { - // Creating the CallSite works here, but fail invoking the method. - testMethod.invoke(null, 3 /* target throw NPE */, 10, 12); - } catch (InvocationTargetException e) { - assertEquals(e.getCause().getClass().getName(), "java.lang.ArithmeticException"); - } - - // This should succeed using already resolved CallSite. - testMethod.invoke(null, 0 /* no error */, 10, 13); - } - - private static void TestInvokeCustomWithConcurrentThreads() throws Throwable { - // This is a concurrency test that attempts to run invoke-custom on the same - // call site. - byte[] base64Data = TestDataInvokeCustomWithConcurrentThreads.BASE64_DEX_FILE.getBytes(); - Base64.Decoder decoder = Base64.getDecoder(); - ByteBuffer dexBuffer = ByteBuffer.wrap(decoder.decode(base64Data)); - - InMemoryDexClassLoader classLoader = - new InMemoryDexClassLoader(dexBuffer, - ClassLoader.getSystemClassLoader()); - Class<?> testClass = - classLoader.loadClass("TestInvokeCustomWithConcurrentThreads"); - Method testMethod = testClass.getDeclaredMethod("test"); - testMethod.invoke(null); - } - - public static void assertEquals(Object o, Object p) { - if (o == p) { return; } - if (o != null && p != null && o.equals(p)) { return; } - throw new AssertionError("assertEquals: o1: " + o + ", o2: " + p); - } - - public static void assertEquals(String s1, String s2) { - if (s1 == s2) { - return; - } - - if (s1 != null && s2 != null && s1.equals(s2)) { - return; - } - - throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); - } - - private static void fail() { - System.out.println("fail"); - Thread.dumpStack(); - } - - public static void main(String[] args) throws Throwable { - TestUninitializedCallSite(); - TestLinkerMethodMinimalArguments(); - TestLinkerMethodMultipleArgumentTypes(); - TestInvokeCustomWithConcurrentThreads(); - } -}
\ No newline at end of file diff --git a/test/952-invoke-custom/src-art/TestDataInvokeCustomWithConcurrentThreads.java b/test/952-invoke-custom/src-art/TestDataInvokeCustomWithConcurrentThreads.java deleted file mode 100644 index 076acd71d2..0000000000 --- a/test/952-invoke-custom/src-art/TestDataInvokeCustomWithConcurrentThreads.java +++ /dev/null @@ -1,147 +0,0 @@ -/* Generated by build-test.sh from TestInvokeCustomWithConcurrentThreads.java */ -public class TestDataInvokeCustomWithConcurrentThreads { - public static final String BASE64_DEX_FILE = - "ZGV4CjAzOABWCyocbwmvY62Y5O92LHrb3B/jTa9jHG0IHgAAcAAAAHhWNBIAAAAAAAAAACAd" + - "AACrAAAAcAAAACsAAAAcAwAAJQAAAMgDAAAKAAAAhAUAADkAAADUBQAAAgAAAKAHAAAgFgAA" + - "6AcAAMARAADzEQAAIxIAACwSAAA0EgAAPBIAAEQSAABMEgAAVBIAAFwSAABkEgAAbBIAAHMS" + - "AAB2EgAAgBIAAIgSAACMEgAAjxIAAJISAACsEgAArxIAALISAAC1EgAAuRIAAMgSAADLEgAA" + - "zhIAANISAADWEgAA2hIAAN4SAADiEgAA5hIAAOwSAADxEgAA9xIAACITAABLEwAATxMAAIQT" + - "AAC3EwAA6BMAAAwUAAAsFAAATxQAAG4UAACKFAAAoRQAAL0UAADQFAAA5RQAAPkUAAANFQAA" + - "KBUAADwVAABQFQAAaBUAAIEVAACYFQAAtRUAANoVAAD7FQAAJBYAAEYWAABlFgAAixYAALgW" + - "AADLFgAAzhYAANQWAAAAFwAAJhcAACkXAAAuFwAAMxcAADgXAAA9FwAAQRcAAEYXAABLFwAA" + - "TxcAAFQXAABZFwAAXRcAAGcXAABqFwAAbhcAAIIXAACXFwAArBcAAMoXAAD4FwAABRgAAA0Y" + - "AAAcGAAAKhgAAD0YAABQGAAAYxgAAHYYAACJGAAAnBgAAK8YAADDGAAA1BgAAOsYAAD3GAAA" + - "CxkAABIZAAAWGQAAGhkAACMZAAAnGQAAKxkAADMZAAA7GQAAPxkAAEMZAABSGQAAZhkAAHUZ" + - "AAB9GQAAgRkAAIUZAACRGQAAmRkAAJ4ZAACvGQAAvxkAAMIZAADGGQAAyhkAANEZAADfGQAA" + - "8BkAAP4ZAAAIGgAAHBoAACIaAAAoGgAALBoAADAaAAA+GgAAShoAAE4aAABUGgAAXxoAAGga" + - "AABrGgAAcBoAAHMaAACDGgAAjBoAAJgaAACdGgAAoRoAAKUaAACqGgAAtRoAALwaAADHGgAA" + - "zRoAANMaAADgGgAA6RoAAPMaAAD5GgAAABsAAAkbAAAQGwAAGRsAABAAAAARAAAAEwAAABQA" + - "AAAVAAAAGAAAACMAAAAkAAAAJgAAACcAAAAoAAAAKQAAACoAAAArAAAALAAAAC0AAAAuAAAA" + - "LwAAADAAAAAxAAAAMgAAADMAAAA0AAAANQAAADYAAAA4AAAAOQAAADoAAAA7AAAAPAAAAD0A" + - "AAA+AAAAPwAAAEAAAABBAAAAQwAAAEcAAABUAAAAVgAAAFcAAABYAAAAWQAAAFoAAAAVAAAA" + - "BAAAAAAAAAAWAAAABAAAAPgQAAAhAAAAEAAAAAARAAAZAAAAEwAAAAAAAAAdAAAAEwAAAPgQ" + - "AAAZAAAAFAAAAAAAAAAZAAAAFQAAAAAAAAAaAAAAFgAAAAgRAAAbAAAAFgAAABARAAAcAAAA" + - "FgAAABgRAAAdAAAAFgAAAPgQAAAeAAAAFgAAACARAAAfAAAAFgAAACgRAAAfAAAAFgAAADAR" + - "AAAlAAAAFgAAADgRAAAiAAAAGwAAAEARAAAiAAAAHQAAAEwRAAAgAAAAHQAAAFgRAAAgAAAA" + - "HQAAAGQRAAAZAAAAIAAAAAAAAAAZAAAAIgAAAAAAAABHAAAAJAAAAAAAAABIAAAAJAAAAHAR" + - "AABJAAAAJAAAAHgRAABKAAAAJAAAAIARAABLAAAAJAAAAIgRAABMAAAAJAAAAPgQAABNAAAA" + - "JAAAAJARAABOAAAAJAAAAJgRAABPAAAAJAAAACgRAABQAAAAJAAAAKARAABPAAAAJAAAADAR" + - "AABQAAAAJAAAAKgRAABPAAAAJAAAALARAABRAAAAJAAAALgRAABSAAAAJAAAADgRAABVAAAA" + - "JQAAACgRAAAHAAQAQgAAAAcAIQBuAAAABwAqAHEAAAAHACkAhgAAAAcAIgCRAAAABwAqAJ8A" + - "AAAHABkAogAAAAoACgAXAAAAEwASAEQAAAAXABAAlAAAAAYAFQAOAAAABgADAIQAAAAGAAUA" + - "hAAAAAcAFAALAAAABwAVAA0AAAAHABUADgAAAAcAFgBeAAAABwAXAF4AAAAHABgAXgAAAAcA" + - "GQBeAAAABwAbAF4AAAAHABwAXgAAAAcAHgBeAAAABwAgAF4AAAAHACIAXgAAAAcAHgBnAAAA" + - "BwAjAGkAAAAHAAAAfwAAAAcADwCNAAAABwABAJIAAAAHABUAmQAAAAcAAQCdAAAABwAVAKAA" + - "AAAQAAIAfAAAABAAHwCXAAAAEQAdAA4AAAATAAAAhwAAABMABACnAAAAFAAkAHgAAAAVACQA" + - "eAAAABYAFQAOAAAAFgAHAFwAAAAWAAgAXAAAABYACQBcAAAAFgAKAFwAAAAWAAsAXAAAABYA" + - "DABcAAAAFgANAFwAAAAWAA4AXAAAABYABgCkAAAAGAAVAA4AAAAYABUAiQAAABgAFQCeAAAA" + - "GQAVAA4AAAAZAAUAfQAAABwAIQAOAAAAHQATAKUAAAAeABAAewAAAB8AEQB1AAAAHwASAIUA" + - "AAAgAAAAlgAAACEAGgAOAAAAIQAAAGsAAAAiABoADgAAACIAAAB9AAAAIgAAAH4AAAAiABoA" + - "nAAAAJwcAAAGAAAAEAAAABkAAAAAAAAARQAAALgQAACjHAAAAAAAAAcAAAABAAAAGAAAAAAA" + - "AABFAAAAyBAAALYcAACZHAAABAAAABIAAAADAAAAPRwAAEQcAABNHAAAAQAAAFwcAAABAAAA" + - "TRwAAAEAAABlHAAAAQAAAG4cAAABAAEAAQAAABwbAAAEAAAAcBArAAAADgACAAEAAQAAACQb" + - "AAANAAAAcQADAAAADABuEDcAAAAKAHEQGwAAAAwAEQAAAAIAAQABAAAAKRsAAAUAAABuEAEA" + - "AQAMABEAAAABAAAAAAAAAAAAAAADAAAAYgAEABEAAAADAAAAAgAAAC4bAAAlAAAAEwIQACIA" + - "IgASAXAgNQAQAGkABAAiAAYAcBAAAAAAaQAGACMgKQBpAAMAIyAqAGkAAgAjICoAaQAFACIA" + - "IQBwIDMAIABpAAEADgAAAAEAAQABAAAAPBsAAAQAAABwECgAAAAOAAUAAgACAAAAQRsAACgA" + - "AAAzQwMADgAiABEAIgEWAHAQHgABABsCXwAAAG4gJQAhAAwBbiAiADEADAEbAgMAAABuICUA" + - "IQAMAW4gIgBBAAwBbhAnAAEADAFwIBkAEAAnAAUAAgACAAAAShsAACgAAAAzQwMADgAiABEA" + - "IgEWAHAQHgABABsCYAAAAG4gJQAhAAwBbiAfADEADAEbAgQAAABuICUAIQAMAW4gHwBBAAwB" + - "bhAnAAEADAFwIBkAEAAnAAgABAADAAAAUxsAACoAAAAvAAQGOQADAA4AIgARACIBFgBwEB4A" + - "AQAbAmEAAABuICUAIQAMAW4wIABBBQwBGwIFAAAAbiAlACEADAFuMCAAYQcMAW4QJwABAAwB" + - "cCAZABAAJwAFAAIAAgAAAFwbAAAqAAAALQADBDkAAwAOACIAEQAiARYAcBAeAAEAGwJiAAAA" + - "biAlACEADAFuICEAMQAMARsCBgAAAG4gJQAhAAwBbiAhAEEADAFuECcAAQAMAXAgGQAQACcA" + - "BQACAAIAAABlGwAAKAAAADNDAwAOACIAEQAiARYAcBAeAAEAGwJjAAAAbiAlACEADAFuICIA" + - "MQAMARsCBwAAAG4gJQAhAAwBbiAiAEEADAFuECcAAQAMAXAgGQAQACcACAAEAAMAAABwGwAA" + - "KgAAADEABAY5AAMADgAiABEAIgEWAHAQHgABABsCZAAAAG4gJQAhAAwBbjAjAEEFDAEbAggA" + - "AABuICUAIQAMAW4wIwBhBwwBbhAnAAEADAFwIBkAEAAnAAUAAgACAAAAexsAADMAAAAzQwMA" + - "DgA4AwsAOAQJAG4gHABDAAoAOAADAA4AIgARACIBFgBwEB4AAQAbAmYAAABuICUAIQAMAW4g" + - "JAAxAAwBGwIJAAAAbiAlACEADAFuICQAQQAMAW4QJwABAAwBcCAZABAAJwAAAAUAAgACAAAA" + - "hxsAADMAAAAzQwMADgA4AwsAOAQJAG4gHQBDAAoAOAADAA4AIgARACIBFgBwEB4AAQAbAmUA" + - "AABuICUAIQAMAW4gJQAxAAwBGwIKAAAAbiAlACEADAFuICUAQQAMAW4QJwABAAwBcCAZABAA" + - "JwAAAAUAAgACAAAAlRsAACgAAAAzQwMADgAiABEAIgEWAHAQHgABABsCZQAAAG4gJQAhAAwB" + - "biAiADEADAEbAgoAAABuICUAIQAMAW4gIgBBAAwBbhAnAAEADAFwIBkAEAAnAAUAAgACAAAA" + - "oBsAADUAAAAyQwMADgA4Aw0AOAQLAG4gHABDAAoA3wAAATgAAwAOACIAEQAiARYAcBAeAAEA" + - "GwJoAAAAbiAlACEADAFuICQAMQAMARsCCQAAAG4gJQAhAAwBbiAkAEEADAFuECcAAQAMAXAg" + - "GQAQACcAAAAEAAEAAgAAAKwbAAAdAAAAOQMcACIAEQAiARYAcBAeAAEAGwJqAAAAbiAlACEA" + - "DAFuICYAMQAMAW4QJwABAAwBcCAZABAAJwAOAAAAAQAAAAEAAAC4GwAADQAAAGIABgBuECwA" + - "AAAMAB8AEwBuEBoAAAAKAA8AAAAJAAMABAAAAL0bAABhAAAAEhUSBHEAEQAAAAoBHAIHAG5A" + - "LwAmhwwAbhAuAAAADAJxIAwAKABuEC4AAAAMAm4QMgACAAoCcSAKAFIAI1InAHEQGwABAAwD" + - "TQMCBHEwMQBAAgwAI1ImAGIDCABNAwIEcTAwAEACDABuEC4AAAAMAm4QMgACAAoCcSAKAFIA" + - "bhAuAAAADAJxIAwAKABiAgEAbhA0AAIAYgIDAHEAEQAAAAoDIgQcAHAgLQAEAE0EAgNiAgMA" + - "cQARAAAACgNGAgIDEQIAAAEAAQAAAAAA2xsAAAEAAAAPAAAAAwABAAIAAADiGwAAFAAAAGIA" + - "AgBGAAACbhA3AAAAYgAFAHEAEQAAAAoBRgAAAW4gOAAgABIADwAMAAAAAwAAAOsbAADoAAAA" + - "EisSGhIJEwgQABIANYAXAGIEAgAiBSIAcCA1AJUATQUEAGIEBQAiBSIAcCA1AJUATQUEANgA" + - "AAEo6iOBKAASADWAEQAiBAcAcBAFAAQATQQBAEYEAQBuECoABADYAAABKPASADWACgBGBAEA" + - "bhApAAQA2AAAASj3EgMSAhIANYAiAGIEAwBGBAQAEgVxIA8AVABiBAIARgQEAG4QNgAEAAoE" + - "OAQNANgDAwFiBAIARgQEAG4QNgAEAAoEsELYAAABKN9iBAkAIgUWAHAQHgAFABsGUwAAAG4g" + - "JQBlAAwFbiAiADUADAUbBgIAAABuICUAZQAMBW4gIgAlAAwFbhAnAAUADAVuIBgAVAAyoy4A" + - "YgQJABsFRgAAAG4gGABUABIANYAjAGIECQAbBQEAAAAjticAcRAbAAAADAdNBwYJYgcFAEYH" + - "BwBuEDYABwAKB3EQGwAHAAwHTQcGCm4wFwBUBtgAAAEo3jKCLgBiBAkAGwUSAAAAbiAYAFQA" + - "EgA1gCMAYgQJABsFAAAAACO2JwBxEBsAAAAMB00HBgliBwIARgcHAG4QNgAHAAoHcRAbAAcA" + - "DAdNBwYKbjAXAFQG2AAAASjecSAKAKMAcSAKAIIADgADAAEAAQAAADEcAAAJAAAAEvH8EAAA" + - "AQAKAHEQEwAAAA4AAADoBwAAAAAAAAAAAAAAAAAA+AcAAAEAAAADAAAAAAAAAAYAAAAACAAA" + - "EgAAAAgIAAAVAAAAEAgAABYAAAAICAAAAQAAAAQAAAACAAAAFQAnAAEAAAABAAAAAQAAAAIA" + - "AAABAAAAAwAAAAEAAAAFAAAAAQAAABQAAAABAAAAFQAAAAEAAAAlAAAAAwAAAB4AFQAgAAAA" + - "AwAAABIAFQAgAAAAAwAAAB0ABAAmAAAAAwAAAB0ABAAnAAAAAgAAAAAAAAACAAAAAQABAAIA" + - "AAACAAIAAgAAAAMAAwACAAAABAAEAAIAAAAFAAUAAgAAABQAFAACAAAAFQAVAAEAAAAdAAAA" + - "AgAAACMAIwAxIENhbGwgc2l0ZSBpbnN0YW5jZSAjJTAyZCB3YXMgaW52b2tlZCAlIDJkIHRp" + - "bWVzCgAuIFRocmVhZCAlIDJkIGludm9rZWQgY2FsbCBzaXRlIGluc3RhbmNlICMlMDJkCgAH" + - "IFZvdGVzIAAGLCBiMjogAAYsIGMyOiAABiwgZDI6IAAGLCBmMjogAAYsIGkyOiAABiwgbDI6" + - "IAAGLCBvMjogAAYsIHMyOiAABS1nZXQwAAE8AAg8Y2xpbml0PgAGPGluaXQ+AAI+OwABQgAB" + - "QwAYQ2FsbC1zaXRlcyBpbnZvY2F0aW9ucyA6AAFEAAFGAAFJAAJJSQANSU5WT0tFX1NUQVRJ" + - "QwABSgABTAACTEMAAkxEAAJMRgACTEkAAkxKAAJMTAAETExJTAADTExMAARMTExMAClMVGVz" + - "dEludm9rZUN1c3RvbVdpdGhDb25jdXJyZW50VGhyZWFkcyQxOwAnTFRlc3RJbnZva2VDdXN0" + - "b21XaXRoQ29uY3VycmVudFRocmVhZHM7AAJMWgAzTGNvbS9hbmRyb2lkL2phY2svYW5ub3Rh" + - "dGlvbnMvQ2FsbGVkQnlJbnZva2VDdXN0b207ADFMY29tL2FuZHJvaWQvamFjay9hbm5vdGF0" + - "aW9ucy9MaW5rZXJNZXRob2RIYW5kbGU7AC9MY29tL2FuZHJvaWQvamFjay9hbm5vdGF0aW9u" + - "cy9NZXRob2RIYW5kbGVLaW5kOwAiTGRhbHZpay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNz" + - "OwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ACFMZGFsdmlrL2Fubm90YXRpb24v" + - "TWVtYmVyQ2xhc3NlczsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWduYXR1cmU7ABpMZGFsdmlr" + - "L2Fubm90YXRpb24vVGhyb3dzOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABpMamF2YS9sYW5n" + - "L0Fzc2VydGlvbkVycm9yOwARTGphdmEvbGFuZy9DbGFzczsAE0xqYXZhL2xhbmcvSW50ZWdl" + - "cjsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABlMamF2YS9sYW5n" + - "L1N0cmluZ0J1aWxkZXI7ABJMamF2YS9sYW5nL1N5c3RlbTsAEkxqYXZhL2xhbmcvVGhyZWFk" + - "OwAWTGphdmEvbGFuZy9UaHJlYWRMb2NhbAAXTGphdmEvbGFuZy9UaHJlYWRMb2NhbDsAFUxq" + - "YXZhL2xhbmcvVGhyb3dhYmxlOwAbTGphdmEvbGFuZy9pbnZva2UvQ2FsbFNpdGU7ACNMamF2" + - "YS9sYW5nL2ludm9rZS9Db25zdGFudENhbGxTaXRlOwAfTGphdmEvbGFuZy9pbnZva2UvTWV0" + - "aG9kSGFuZGxlOwAnTGphdmEvbGFuZy9pbnZva2UvTWV0aG9kSGFuZGxlcyRMb29rdXA7ACBM" + - "amF2YS9sYW5nL2ludm9rZS9NZXRob2RIYW5kbGVzOwAdTGphdmEvbGFuZy9pbnZva2UvTWV0" + - "aG9kVHlwZTsAJExqYXZhL3V0aWwvY29uY3VycmVudC9DeWNsaWNCYXJyaWVyOwArTGphdmEv" + - "dXRpbC9jb25jdXJyZW50L2F0b21pYy9BdG9taWNJbnRlZ2VyOwARTlVNQkVSX09GX1RIUkVB" + - "RFMAAVMABFRZUEUAKlRlc3RJbnZva2VDdXN0b21XaXRoQ29uY3VycmVudFRocmVhZHMuamF2" + - "YQAkVGhyZWFkcyBkaWQgbm90IHRoZSBzYW1lIGNhbGwtc2l0ZXM6AAFWAANWQkIAA1ZDQwAD" + - "VkREAANWRkYAAlZJAANWSUkAA1ZKSgACVkwAA1ZMTAADVlNTAAJWWgAIV2lubmVycyAAAVoA" + - "AlpMABJbTGphdmEvbGFuZy9DbGFzczsAE1tMamF2YS9sYW5nL09iamVjdDsAE1tMamF2YS9s" + - "YW5nL1RocmVhZDsAHFtMamF2YS9sYW5nL2ludm9rZS9DYWxsU2l0ZTsALFtMamF2YS91dGls" + - "L2NvbmN1cnJlbnQvYXRvbWljL0F0b21pY0ludGVnZXI7AAthY2Nlc3NGbGFncwAGYXBwZW5k" + - "AA1hcmd1bWVudFR5cGVzAAxhc3NlcnRFcXVhbHMAEWFzc2VydEVxdWFscyBiMTogABFhc3Nl" + - "cnRFcXVhbHMgYzE6IAARYXNzZXJ0RXF1YWxzIGQxOiAAEWFzc2VydEVxdWFscyBmMTogABFh" + - "c3NlcnRFcXVhbHMgaTE6IAARYXNzZXJ0RXF1YWxzIGwxOiAAEWFzc2VydEVxdWFscyBzMTog" + - "ABJhc3NlcnRFcXVhbHM6IG8xOiAAD2Fzc2VydE5vdEVxdWFscwAVYXNzZXJ0Tm90RXF1YWxz" + - "OiBvMTogAAphc3NlcnRUcnVlABJhc3NlcnRUcnVlIHZhbHVlOiAABWF3YWl0AAJiMQACYjIA" + - "B2JhcnJpZXIAAmMxAAJjMgAGY2FsbGVkAAZjYWxsZXIAAmQxAAJkMgANZHJvcEFyZ3VtZW50" + - "cwASZW1pdHRlcjogamFjay00LjI1AA1lbmNsb3NpbmdUeXBlAAZlcXVhbHMAAmYxAAJmMgAK" + - "ZmluZFN0YXRpYwAGZm9ybWF0AANnZXQAD2dldEFuZEluY3JlbWVudAAOZ2V0VGhyZWFkSW5k" + - "ZXgAAWkAAmkxAAJpMgAFaW5kZXgADGluaXRpYWxWYWx1ZQAPaW5zZXJ0QXJndW1lbnRzAAxp" + - "bnN0YW50aWF0ZWQACGludFZhbHVlABJpbnZva2VNZXRob2RIYW5kbGUABGpvaW4ABGtpbmQA" + - "AmwxAAJsMgAMbGlua2VyTWV0aG9kAAptZXRob2RUeXBlAAJtaAAEbmFtZQAJbmV4dEluZGV4" + - "AAdub3RVc2VkAAFvAANvdXQAAXAADnBhcmFtZXRlckNvdW50AAdwcmludGxuAApyZXR1cm5U" + - "eXBlAANydW4AAnMxAAJzMgADc2V0AAlzZXRDYWxsZWQABXN0YXJ0AAl0YXJnZXR0ZWQABHRl" + - "c3QABHRoaXMAC3RocmVhZEluZGV4AAd0aHJlYWRzAAh0b1N0cmluZwAEdHlwZQAFdmFsdWUA" + - "B3ZhbHVlT2YABXZvdGVzAAd3aW5uZXJzAAF4ACcABw4CWjsAKgAHDgAoAAcOACQAByyJWDVN" + - "TU0CaXcAOgAHDgCuAQJtbgcOPACzAQJwcQcOPADMAQJ0dQcOWgDHAQJ6ewcOWgC9AQKCAYMB" + - "Bw48AMIBAowBjQEHDloA0QEClAGWAQcOPLQA3QECmwGcAQcOLSClIAC4AQKbAZwBBw48ANcB" + - "ApQBlgEHDjzSAKgBAacBBw4tARoQAD0ABw4AXANzkQGPAQcsTAMBowEFaQMAkAEeeLTDpbR8" + - "W9IAQQGrAQcOAFMBhAEHDni0AHEAB1kBAQMAgQEFLZaTQS0DAaQBKTx4V0E8WEAeAwOqAQUe" + - "AwKpAQU8h6UtkUMBJBIthzx4ARQNOkMthzx4ARQNOkE8PABGAAcOWgMAqwEFPAACCwGmARgH" + - "AgwCWwQIkAEeAg4BpgEcBBc3FwwXMRcPAg0BpgEcARgGAg8BpgEcARgaAAgEXRwBGASIARwB" + - "HQkEXRwDGB4YFRggdxgHigEbB5ABF42QARedmAEYBAEEEAMWABedFQEAAAECAICABJgQAQSw" + - "EAHEINwQBwATAQAaARoBGgEaARoBGgEaA4gg+BABiIAEkBEBgoAE7BEBCYQSAQnkEgEJxBMB" + - "CagUAQmMFQEJ7BUBCdAWAQnIFwEJwBgBCaAZAQmcGgEK6BoBCpQbAQnoHAIK/BwBCbQdFAGU" + - "IQAAABMAAAAAAAAAAQAAAAAAAAABAAAAqwAAAHAAAAACAAAAKwAAABwDAAADAAAAJQAAAMgD" + - "AAAEAAAACgAAAIQFAAAFAAAAOQAAANQFAAAHAAAAAQAAAJwHAAAGAAAAAgAAAKAHAAAIAAAA" + - "AQAAAOAHAAADEAAABQAAAOgHAAABIAAAFwAAABgIAAAGIAAAAgAAALgQAAABEAAAFwAAAPgQ" + - "AAACIAAAqwAAAMARAAADIAAAFgAAABwbAAAEIAAABgAAAD0cAAAFIAAAAgAAAJkcAAAAIAAA" + - "AgAAAKMcAAAAEAAAAQAAACAdAAA="; -} diff --git a/test/952-invoke-custom/src-art/TestDataLinkerMethodMinimalArguments.java b/test/952-invoke-custom/src-art/TestDataLinkerMethodMinimalArguments.java deleted file mode 100644 index 443a7af187..0000000000 --- a/test/952-invoke-custom/src-art/TestDataLinkerMethodMinimalArguments.java +++ /dev/null @@ -1,106 +0,0 @@ -/* Generated by build-test.sh from TestLinkerMethodMinimalArguments.java */ -public class TestDataLinkerMethodMinimalArguments { - public static final String BASE64_DEX_FILE = - "ZGV4CjAzOADnZpVEc25JsNXLCW+vh64OuLf8RymAuINwFQAAcAAAAHhWNBIAAAAAAAAAAIgU" + - "AACBAAAAcAAAAB0AAAB0AgAAHAAAAOgCAAAHAAAAOAQAACIAAABwBAAAAQAAAIQFAADEDwAA" + - "rAUAAKAMAACjDAAApwwAAKoMAACyDAAAugwAAMIMAADKDAAA0gwAANoMAADiDAAA6gwAAPQM" + - "AAD8DAAA/wwAAAINAAAFDQAACA0AADENAABUDQAAZw0AAIoNAACbDQAAng0AAKMNAACyDQAA" + - "tQ0AALgNAAC8DQAAwA0AAMQNAADIDQAAzA0AANANAADWDQAA+g0AAP4NAAAzDgAAZg4AAJcO" + - "AACzDgAAyg4AAOsOAAAHDwAAGg8AAD4PAABSDwAAZg8AAIEPAACVDwAArA8AAMkPAADuDwAA" + - "DxAAADgQAABXEAAAgBAAAIMQAACqEAAA0RAAAAQRAAAHEQAADBEAABERAAAWEQAAGxEAACAR" + - "AAAmEQAAKxEAAC8RAAA0EQAAOREAAD0RAABAEQAARBEAAEcRAABMEQAAVBEAAGMRAABxEQAA" + - "hBEAAJcRAACqEQAAvREAANARAADjEQAA9hEAAAoSAAAWEgAAKhIAAC0SAAAxEgAANRIAADkS" + - "AAA9EgAARRIAAEkSAABNEgAAYRIAAHASAAB4EgAAfBIAAIASAACNEgAAmRIAAKsSAACvEgAA" + - "sxIAAMcSAADNEgAA0RIAANUSAADjEgAA/xIAAAsTAAATEwAAGRMAABwTAAAhEwAAJBMAAC0T" + - "AAA5EwAAPRMAAEETAABHEwAATRMAAFcTAABeEwAAYRMAAA0AAAAOAAAADwAAABAAAAAWAAAA" + - "GQAAACIAAAAkAAAAJQAAACYAAAAnAAAAKAAAACkAAAAqAAAAKwAAACwAAAAtAAAALgAAAC8A" + - "AAAwAAAAMQAAADIAAAAzAAAANAAAADUAAAA2AAAAOAAAADwAAABIAAAAFwAAAAQAAADsCwAA" + - "GgAAABEAAAAAAAAAGwAAABIAAAD0CwAAHAAAABIAAAD8CwAAHQAAABIAAAAEDAAAHgAAABIA" + - "AAAMDAAAHwAAABIAAAAUDAAAIAAAABIAAAAcDAAAIAAAABIAAAAkDAAAIwAAABIAAAAsDAAA" + - "IQAAABUAAAA0DAAAIQAAABcAAABADAAAPAAAABsAAAAAAAAAPQAAABsAAABMDAAAPgAAABsA" + - "AABUDAAAPwAAABsAAABcDAAAQAAAABsAAABkDAAAQQAAABsAAADsCwAAQgAAABsAAABsDAAA" + - "QwAAABsAAAB4DAAARAAAABsAAAAcDAAARQAAABsAAACADAAARAAAABsAAAAkDAAARQAAABsA" + - "AACIDAAARAAAABsAAACQDAAARgAAABsAAACYDAAARwAAABsAAAAsDAAASQAAABwAAAAcDAAA" + - "BgAEABEAAAAGAAQAEgAAAAYABAATAAAABgAEABQAAAAGAAQAaAAAAAkACQAYAAAAEwALAHUA" + - "AAAGAAwACwAAAAYADAAMAAAABgAAAEsAAAAGAA0ATgAAAAYADgBOAAAABgAPAE4AAAAGABAA" + - "TgAAAAYAEQBOAAAABgATAE4AAAAGABUATgAAAAYAFwBOAAAABgAZAE4AAAAGABoAVwAAAAYA" + - "CgBvAAAABgASAHsAAAALABYAdwAAAAwAFgAMAAAADQAUAAwAAAAPABYADAAAABAADAAMAAAA" + - "EAAbAGMAAAARABsAYwAAABIADAAMAAAAEgACAEwAAAASAAMATAAAABIABABMAAAAEgAFAEwA" + - "AAASAAYATAAAABIABwBMAAAAEgAIAEwAAAASAAkATAAAABIAAQB9AAAAFgAYAAwAAAAYAAsA" + - "ZwAAADIUAAAGAAAAAQAAABAAAAAAAAAAOQAAAMQLAAA5FAAAAAAAAAQAAAANAAAAAQAAAAIU" + - "AAABAAAAKhQAAAEAAAAAAAAAZBMAAA8AAAASAGcABABnAAIAEhBnAAAAEiBnAAEAEjBnAAMA" + - "DgAAAAEAAQABAAAAcBMAAAQAAABwEBMAAAAOAAQAAgACAAAAdRMAABoAAABgAAQAYAEDADMQ" + - "EwBiAAYAGwE6AAAAbiAPABAAIgAMABsBSwAAAHAgEAAQACcAkAACAw8ABQACAAIAAAB/EwAA" + - "KAAAADNDAwAOACIADQAiARIAcBAWAAEAGwJPAAAAbiAdACEADAFuIBoAMQAMARsCAwAAAG4g" + - "HQAhAAwBbiAaAEEADAFuEB8AAQAMAXAgEQAQACcABQACAAIAAACHEwAAKAAAADNDAwAOACIA" + - "DQAiARIAcBAWAAEAGwJQAAAAbiAdACEADAFuIBcAMQAMARsCBAAAAG4gHQAhAAwBbiAXAEEA" + - "DAFuEB8AAQAMAXAgEQAQACcACAAEAAMAAACPEwAAKgAAAC8ABAY5AAMADgAiAA0AIgESAHAQ" + - "FgABABsCUQAAAG4gHQAhAAwBbjAYAEEFDAEbAgUAAABuIB0AIQAMAW4wGABhBwwBbhAfAAEA" + - "DAFwIBEAEAAnAAUAAgACAAAAlxMAACoAAAAtAAMEOQADAA4AIgANACIBEgBwEBYAAQAbAlIA" + - "AABuIB0AIQAMAW4gGQAxAAwBGwIGAAAAbiAdACEADAFuIBkAQQAMAW4QHwABAAwBcCARABAA" + - "JwAFAAIAAgAAAJ8TAAAoAAAAM0MDAA4AIgANACIBEgBwEBYAAQAbAlMAAABuIB0AIQAMAW4g" + - "GgAxAAwBGwIHAAAAbiAdACEADAFuIBoAQQAMAW4QHwABAAwBcCARABAAJwAIAAQAAwAAAKcT" + - "AAAqAAAAMQAEBjkAAwAOACIADQAiARIAcBAWAAEAGwJUAAAAbiAdACEADAFuMBsAQQUMARsC" + - "CAAAAG4gHQAhAAwBbjAbAGEHDAFuEB8AAQAMAXAgEQAQACcABQACAAIAAACvEwAAMwAAADND" + - "AwAOADgDCwA4BAkAbiAUAEMACgA4AAMADgAiAA0AIgESAHAQFgABABsCVgAAAG4gHQAhAAwB" + - "biAcADEADAEbAgkAAABuIB0AIQAMAW4gHABBAAwBbhAfAAEADAFwIBEAEAAnAAAABQACAAIA" + - "AAC4EwAAMwAAADNDAwAOADgDCwA4BAkAbiAVAEMACgA4AAMADgAiAA0AIgESAHAQFgABABsC" + - "VQAAAG4gHQAhAAwBbiAdADEADAEbAgoAAABuIB0AIQAMAW4gHQBBAAwBbhAfAAEADAFwIBEA" + - "EAAnAAAABQACAAIAAADDEwAAKAAAADNDAwAOACIADQAiARIAcBAWAAEAGwJVAAAAbiAdACEA" + - "DAFuIBoAMQAMARsCCgAAAG4gHQAhAAwBbiAaAEEADAFuEB8AAQAMAXAgEQAQACcABAABAAIA" + - "AADLEwAAHQAAADkDHAAiAA0AIgESAHAQFgABABsCWAAAAG4gHQAhAAwBbiAeADEADAFuEB8A" + - "AQAMAXAgEQAQACcADgAAAAcAAwAEAAAA1RMAAGoAAABiAQYAIgISAHAQFgACABsDcAAAAG4g" + - "HQAyAAwCYAMEAG4gGgAyAAwCbhAfAAIADAJuIA8AIQAcAQYAbkAhABRlDABgAQQAYAIAADMh" + - "KABiAQYAIgISAHAQFgACABsDNwAAAG4gHQAyAAwCbiAdAFIADAIbAwAAAABuIB0AMgAMAm4g" + - "HABiAAwCbhAfAAIADAJuIA8AIQASAREBYAEEAGACAQAzIRMAYgEGABsCOwAAAG4gDwAhACIB" + - "DwAbAm8AAABwIBIAIQAnASIBFgBwICAAAQARAQYAAwACAAAA7RMAAFAAAAASERICYAACADQD" + - "SAABEHEQDAAAAGAAAwA2A0IAcRAMAAEAZwMEAJAABAX8IAAAVAAKAXEgBwAQAGIABgAiARIA" + - "cBAWAAEAGwIVAAAAbiAdACEADAFuIBoAMQAMARsCAQAAAG4gHQAhAAwBbiAaAEEADAFuIBoA" + - "UQAMARsCAgAAAG4gHQAhAAwBbhAfAAEADAFuIA8AEAAOAAEgKLoBISi/AAAAAAAAAAADAAAA" + - "AAAAAAIAAACsBQAADQAAALQFAAAOAAAAtAUAAAIAAAAEAAQAAQAAAAEAAAABAAAAAgAAAAEA" + - "AAADAAAAAQAAAAQAAAABAAAABQAAAAEAAAAQAAAAAQAAABEAAAABAAAAHAAAAAMAAAAYABEA" + - "GQAAAAMAAAAOABEAGQAAAAIAAAAAAAAAAgAAAAEAAQACAAAAAgACAAIAAAADAAMAAwAAAAQA" + - "BAAEAAAAAgAAAAUABQACAAAAEAAQAAIAAAARABEAAQAAABcAAAACAAAAGgAaAAEgAAIgKAAB" + - "KQAGLCBiMjogAAYsIGMyOiAABiwgZDI6IAAGLCBmMjogAAYsIGkyOiAABiwgbDI6IAAGLCBv" + - "MjogAAYsIHMyOiAACDxjbGluaXQ+AAY8aW5pdD4AAUIAAUMAAUQAAUYAJ0ZBSUxVUkVfVFlQ" + - "RV9MSU5LRVJfTUVUSE9EX1JFVFVSTlNfTlVMTAAhRkFJTFVSRV9UWVBFX0xJTktFUl9NRVRI" + - "T0RfVEhST1dTABFGQUlMVVJFX1RZUEVfTk9ORQAhRkFJTFVSRV9UWVBFX1RBUkdFVF9NRVRI" + - "T0RfVEhST1dTAA9GYWlsdXJlIFR5cGUgKyAAAUkAA0lJSQANSU5WT0tFX1NUQVRJQwABSgAB" + - "TAACTEMAAkxEAAJMRgACTEkAAkxKAAJMTAAETExMTAAiTFRlc3RMaW5rZXJNZXRob2RNaW5p" + - "bWFsQXJndW1lbnRzOwACTFoAM0xjb20vYW5kcm9pZC9qYWNrL2Fubm90YXRpb25zL0NhbGxl" + - "ZEJ5SW52b2tlQ3VzdG9tOwAxTGNvbS9hbmRyb2lkL2phY2svYW5ub3RhdGlvbnMvTGlua2Vy" + - "TWV0aG9kSGFuZGxlOwAvTGNvbS9hbmRyb2lkL2phY2svYW5ub3RhdGlvbnMvTWV0aG9kSGFu" + - "ZGxlS2luZDsAGkxkYWx2aWsvYW5ub3RhdGlvbi9UaHJvd3M7ABVMamF2YS9pby9QcmludFN0" + - "cmVhbTsAH0xqYXZhL2xhbmcvQXJpdGhtZXRpY0V4Y2VwdGlvbjsAGkxqYXZhL2xhbmcvQXNz" + - "ZXJ0aW9uRXJyb3I7ABFMamF2YS9sYW5nL0NsYXNzOwAiTGphdmEvbGFuZy9JbnN0YW50aWF0" + - "aW9uRXhjZXB0aW9uOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsA" + - "GUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsAEkxqYXZhL2xhbmcvU3lzdGVtOwAVTGphdmEv" + - "bGFuZy9UaHJvd2FibGU7ABtMamF2YS9sYW5nL2ludm9rZS9DYWxsU2l0ZTsAI0xqYXZhL2xh" + - "bmcvaW52b2tlL0NvbnN0YW50Q2FsbFNpdGU7AB9MamF2YS9sYW5nL2ludm9rZS9NZXRob2RI" + - "YW5kbGU7ACdMamF2YS9sYW5nL2ludm9rZS9NZXRob2RIYW5kbGVzJExvb2t1cDsAHUxqYXZh" + - "L2xhbmcvaW52b2tlL01ldGhvZFR5cGU7ACdSZXR1cm5pbmcgbnVsbCBpbnN0ZWFkIG9mIENh" + - "bGxTaXRlIGZvciAAAVMAJVRlc3RMaW5rZXJNZXRob2RNaW5pbWFsQXJndW1lbnRzLmphdmEA" + - "JVRocm93aW5nIEFyaXRobWV0aWNFeGNlcHRpb24gaW4gYWRkKCkAMVRocm93aW5nIEluc3Rh" + - "bnRpYXRpb25FeGNlcHRpb24gaW4gbGlua2VyTWV0aG9kKCkAAVYAA1ZCQgADVkNDAANWREQA" + - "A1ZGRgADVklJAARWSUlJAANWSkoAAlZMAANWTEwAA1ZTUwACVloAAVoAAlpMAAFhAANhZGQA" + - "BmFwcGVuZAANYXJndW1lbnRUeXBlcwAMYXNzZXJ0RXF1YWxzABFhc3NlcnRFcXVhbHMgYjE6" + - "IAARYXNzZXJ0RXF1YWxzIGMxOiAAEWFzc2VydEVxdWFscyBkMTogABFhc3NlcnRFcXVhbHMg" + - "ZjE6IAARYXNzZXJ0RXF1YWxzIGkxOiAAEWFzc2VydEVxdWFscyBsMTogABFhc3NlcnRFcXVh" + - "bHMgczE6IAASYXNzZXJ0RXF1YWxzOiBvMTogAAphc3NlcnRUcnVlABJhc3NlcnRUcnVlIHZh" + - "bHVlOiAAAWIAAmIxAAJiMgACYzEAAmMyAAZjYWxsZXIAAmQxAAJkMgASZW1pdHRlcjogamFj" + - "ay00LjI1AA1lbmNsb3NpbmdUeXBlAAZlcXVhbHMAAmYxAAJmMgALZmFpbHVyZVR5cGUACmZp" + - "bmRTdGF0aWMAEGZvcmNlRmFpbHVyZVR5cGUAAmkxAAJpMgASaW52b2tlTWV0aG9kSGFuZGxl" + - "AARraW5kAAJsMQACbDIADGxpbmtlck1ldGhvZAAabGlua2VyTWV0aG9kIGZhaWx1cmUgdHlw" + - "ZSAACm1ldGhvZFR5cGUABm1oX2FkZAAEbmFtZQABbwADb3V0AAFwAAdwcmludGxuAApyZXR1" + - "cm5UeXBlAAJzMQACczIABHRlc3QABHRoaXMACHRvU3RyaW5nAAV2YWx1ZQABeAABeQAeAAcd" + - "Li08PAJ5OwAcAAcOAC8CS1oHDmmHlwBWAltcBw48AFsCXV4HDjwAdAJgYQcOWgBvAmVmBw5a" + - "AGUCamsHDjwAagJubwcOWgB5AnV3Bw48tAB/Anp7Bw4tIKUgAGACensHDjwAUAF/Bw4tARoQ" + - "ADkDX3RyBw4BGxBpAwBzGGkBJA8taYeXAEgDZ4ABgQEHLId4LZYBLw8CeywtAAAHBE0cAhgE" + - "GARrHAEdCARNHAMYGBgRGBliGAZsGwVzF29zF0t4GAQCCgF+HAEYFAMWABdLFQAFAA8AAAoB" + - "CgEKAQoBCgCIgAS8CwGBgATsCwEKhAwBCcgMAQmoDQEJiA4BCewOAQnQDwEJsBABCZQRAQmM" + - "EgEJhBMBCeQTAQqwFAEJlBYAEwAAAAAAAAABAAAAAAAAAAEAAACBAAAAcAAAAAIAAAAdAAAA" + - "dAIAAAMAAAAcAAAA6AIAAAQAAAAHAAAAOAQAAAUAAAAiAAAAcAQAAAcAAAABAAAAgAUAAAYA" + - "AAABAAAAhAUAAAgAAAABAAAApAUAAAMQAAACAAAArAUAAAEgAAAPAAAAvAUAAAYgAAABAAAA" + - "xAsAAAEQAAAVAAAA7AsAAAIgAACBAAAAoAwAAAMgAAAPAAAAZBMAAAQgAAACAAAAAhQAAAUg" + - "AAABAAAAMhQAAAAgAAABAAAAORQAAAAQAAABAAAAiBQAAA=="; -} diff --git a/test/952-invoke-custom/src-art/TestDataLinkerMethodMultipleArgumentTypes.java b/test/952-invoke-custom/src-art/TestDataLinkerMethodMultipleArgumentTypes.java deleted file mode 100644 index b96e18486f..0000000000 --- a/test/952-invoke-custom/src-art/TestDataLinkerMethodMultipleArgumentTypes.java +++ /dev/null @@ -1,108 +0,0 @@ -/* Generated by build-test.sh from TestLinkerMethodMultipleArgumentTypes.java */ -public class TestDataLinkerMethodMultipleArgumentTypes { - public static final String BASE64_DEX_FILE = - "ZGV4CjAzOADmj8ccx56N3pWZ9IunuZvI0eWD+wmFmSnEFQAAcAAAAHhWNBIAAAAAAAAAANwU" + - "AACTAAAAcAAAAB0AAAC8AgAAHQAAADADAAADAAAAjAQAACIAAACkBAAAAQAAALgFAADkDwAA" + - "4AUAAEQMAABHDAAASgwAAFIMAABaDAAAYgwAAGoMAAByDAAAegwAAIIMAACKDAAAkgwAAJwM" + - "AACkDAAApwwAAKoMAACtDAAAsAwAAMYMAADNDAAA0AwAANUMAADkDAAA5wwAAOoMAADuDAAA" + - "8gwAAPYMAAD6DAAA/gwAAAINAAAIDQAAGA0AAEENAABFDQAAeg0AAKMNAADWDQAABw4AACYO" + - "AABCDgAATA4AAGMOAAB/DgAAkQ4AAKQOAAC6DgAAzg4AAOIOAAD9DgAAEQ8AACgPAABFDwAA" + - "ag8AAIsPAAC0DwAA0w8AANYPAAACEAAABRAAAAoQAAAPEAAAFBAAABkQAAAdEAAAIhAAACcQ" + - "AAArEAAAMBAAADUQAAA5EAAAPBAAAEUQAABJEAAATBAAAFEQAABZEAAAaBAAAHYQAACJEAAA" + - "nBAAAK8QAADCEAAA1RAAAOgQAAD7EAAADxEAABsRAAAvEQAAMhEAADYRAAA6EQAASBEAAFsR" + - "AABmEQAAahEAAG4RAAB2EQAAgREAAI0RAACREQAAlREAAKIRAAC2EQAAxREAAM0RAADREQAA" + - "1REAAOERAADtEQAA8REAAPURAAD/EQAAExIAABkSAAAdEgAAIRIAAC8SAAA6EgAAURIAAF0S" + - "AABlEgAAaxIAAG4SAABzEgAAdhIAAH8SAACLEgAAjxIAAJMSAACfEgAArBIAALISAAC4EgAA" + - "whIAAMYSAADLEgAAzxIAANMSAADXEgAA2xIAAN8SAADjEgAA5xIAAOsSAADyEgAA9RIAAA0A" + - "AAAOAAAADwAAABAAAAATAAAAFgAAACAAAAAiAAAAIwAAACQAAAAlAAAAJgAAACcAAAApAAAA" + - "KgAAACwAAAAuAAAALwAAADAAAAAxAAAAMgAAADMAAAA0AAAANQAAADYAAAA3AAAAOAAAADoA" + - "AABGAAAAEwAAAAQAAAAAAAAAFAAAAAQAAACICwAAFwAAABEAAAAAAAAAGAAAABIAAACQCwAA" + - "GQAAABIAAACYCwAAGgAAABIAAACgCwAAGwAAABIAAACoCwAAHAAAABIAAACwCwAAHQAAABIA" + - "AAC4CwAAHQAAABIAAADACwAAIQAAABIAAADICwAAHwAAABUAAADQCwAAHgAAABcAAADwCwAA" + - "OgAAABsAAAAAAAAAOwAAABsAAAD8CwAAPAAAABsAAAAEDAAAPQAAABsAAAAMDAAAPgAAABsA" + - "AAAUDAAAPwAAABsAAACoCwAAQAAAABsAAACICwAAQQAAABsAAAAcDAAAQgAAABsAAAC4CwAA" + - "QwAAABsAAAAkDAAAQgAAABsAAADACwAAQwAAABsAAAAsDAAAQgAAABsAAAA0DAAARAAAABsA" + - "AAA8DAAARQAAABsAAADICwAASAAAABwAAAC4CwAABgAEAFwAAAAKAAoAFQAAABMADQB7AAAA" + - "BgANAAsAAAAGAA0ADAAAAAYAAAARAAAABgABAEoAAAAGAA4ATQAAAAYADwBNAAAABgAQAE0A" + - "AAAGABEATQAAAAYAEwBNAAAABgAUAE0AAAAGABYATQAAAAYAGABNAAAABgAaAE0AAAAGABsA" + - "VgAAAAYACwB0AAAABgATAIMAAAANABIAfQAAAA0AFwB9AAAADgAVAAwAAAAQAA0ADAAAABAA" + - "HABoAAAAEQAcAGgAAAASAA0ADAAAABIAAwBLAAAAEgAEAEsAAAASAAUASwAAABIABgBLAAAA" + - "EgAHAEsAAAASAAgASwAAABIACQBLAAAAEgAKAEsAAAASAAIAhQAAABYAGQAMAAAAGAAMAGsA" + - "AABpFAAABgAAAAEAAAAQAAAAAAAAADkAAABgCwAAkhQAAAAAAAAEAAAADgAAAAEAAACpEwAA" + - "AgAAAEcUAABgFAAAAQAAAGAUAAABAAAAAAAAAPgSAAAEAAAAEgBnAAAADgABAAEAAQAAAP4S" + - "AAAEAAAAcBATAAAADgADAAIAAAAAAAMTAAADAAAAkAABAg8AAAAFAAIAAgAAAAoTAAAoAAAA" + - "M0MDAA4AIgAOACIBEgBwEBYAAQAbAk4AAABuIB0AIQAMAW4gGgAxAAwBGwICAAAAbiAdACEA" + - "DAFuIBoAQQAMAW4QHwABAAwBcCASABAAJwAFAAIAAgAAABITAAAoAAAAM0MDAA4AIgAOACIB" + - "EgBwEBYAAQAbAk8AAABuIB0AIQAMAW4gFwAxAAwBGwIDAAAAbiAdACEADAFuIBcAQQAMAW4Q" + - "HwABAAwBcCASABAAJwAIAAQAAwAAABoTAAAqAAAALwAEBjkAAwAOACIADgAiARIAcBAWAAEA" + - "GwJQAAAAbiAdACEADAFuMBgAQQUMARsCBAAAAG4gHQAhAAwBbjAYAGEHDAFuEB8AAQAMAXAg" + - "EgAQACcABQACAAIAAAAiEwAAKgAAAC0AAwQ5AAMADgAiAA4AIgESAHAQFgABABsCUQAAAG4g" + - "HQAhAAwBbiAZADEADAEbAgUAAABuIB0AIQAMAW4gGQBBAAwBbhAfAAEADAFwIBIAEAAnAAUA" + - "AgACAAAAKhMAACgAAAAzQwMADgAiAA4AIgESAHAQFgABABsCUgAAAG4gHQAhAAwBbiAaADEA" + - "DAEbAgYAAABuIB0AIQAMAW4gGgBBAAwBbhAfAAEADAFwIBIAEAAnAAgABAADAAAAMhMAACoA" + - "AAAxAAQGOQADAA4AIgAOACIBEgBwEBYAAQAbAlMAAABuIB0AIQAMAW4wGwBBBQwBGwIHAAAA" + - "biAdACEADAFuMBsAYQcMAW4QHwABAAwBcCASABAAJwAFAAIAAgAAADoTAAAzAAAAM0MDAA4A" + - "OAMLADgECQBuIBQAQwAKADgAAwAOACIADgAiARIAcBAWAAEAGwJVAAAAbiAdACEADAFuIBwA" + - "MQAMARsCCAAAAG4gHQAhAAwBbiAcAEEADAFuEB8AAQAMAXAgEgAQACcAAAAFAAIAAgAAAEMT" + - "AAAzAAAAM0MDAA4AOAMLADgECQBuIBUAQwAKADgAAwAOACIADgAiARIAcBAWAAEAGwJUAAAA" + - "biAdACEADAFuIB0AMQAMARsCCQAAAG4gHQAhAAwBbiAdAEEADAFuEB8AAQAMAXAgEgAQACcA" + - "AAAFAAIAAgAAAFETAAAoAAAAM0MDAA4AIgAOACIBEgBwEBYAAQAbAlQAAABuIB0AIQAMAW4g" + - "GgAxAAwBGwIJAAAAbiAdACEADAFuIBoAQQAMAW4QHwABAAwBcCASABAAJwAEAAEAAgAAAFsT" + - "AAAdAAAAOQMcACIADgAiARIAcBAWAAEAGwJXAAAAbiAdACEADAFuIB4AMQAMAW4QHwABAAwB" + - "cCASABAAJwAOAAAAFgAPAAQAAABmEwAAbAAAAGIDAgAiBBIAcBAWAAQAGwUoAAAAbiAdAFQA" + - "DARuIB0AhAAMBBsFAAAAAG4gHQBUAAwEbiAcAJQADARuEB8ABAAMBG4gEQBDAHEQDQAKABIT" + - "cSAIALMAEwNhAHEgBQDDABMDAARxIAgA0wASE3EgCADjABQDmpkxQXEgBwDzABgEmpmZmZmZ" + - "AUAFABAAcUAGAFQQGwMSAAAACAASAHEgCwADABwDBgAIABMAcSAKAAMAFwQVzVsHBQAUAHFA" + - "CQBUEBwDBgBuQCEAN5gMAiIDFgBwICAAIwARAwQAAgACAAAAmRMAABEAAACQAAID/CAAADIA" + - "CgFxIAgAEABiAAIAkAECA24gEAAQAA4AAAACAAEAAAAAAKQTAAADAAAAYAAAAA8AAAAAAAAA" + - "AAAAAAMAAAAAAAAAAwAAAOAFAAAOAAAA6AUAAA8AAAD0BQAAAgAAAAQABAABAAAAAQAAAAEA" + - "AAACAAAAAQAAAAMAAAABAAAABAAAAAEAAAAFAAAAAQAAABAAAAABAAAAEQAAAAEAAAAcAAAA" + - "DQAAABgAEQAZABwAAAABABoABAADAAIAEQAPAAUAAAADAAAADwARABkAAAACAAAAAAAAAAIA" + - "AAABAAEAAgAAAAIAAgACAAAAAwADAAIAAAAFAAUAAgAAABAAEAACAAAAEQARAAEAAAAXAAAA" + - "AgAAABoAGgABIAABKAAGLCBiMjogAAYsIGMyOiAABiwgZDI6IAAGLCBmMjogAAYsIGkyOiAA" + - "BiwgbDI6IAAGLCBvMjogAAYsIHMyOiAABjwqPjtKKQAIPGNsaW5pdD4ABjxpbml0PgABQgAB" + - "QwABRAABRgAUR2V0Qm9vdHN0cmFwUnVuQ291bnQABUhlbGxvAAFJAANJSUkADUlOVk9LRV9T" + - "VEFUSUMAAUoAAUwAAkxDAAJMRAACTEYAAkxJAAJMSgACTEwABExMTEwADkxMTExaQkNTSUZE" + - "TExKACdMVGVzdExpbmtlck1ldGhvZE11bHRpcGxlQXJndW1lbnRUeXBlczsAAkxaADNMY29t" + - "L2FuZHJvaWQvamFjay9hbm5vdGF0aW9ucy9DYWxsZWRCeUludm9rZUN1c3RvbTsAJ0xjb20v" + - "YW5kcm9pZC9qYWNrL2Fubm90YXRpb25zL0NvbnN0YW50OwAxTGNvbS9hbmRyb2lkL2phY2sv" + - "YW5ub3RhdGlvbnMvTGlua2VyTWV0aG9kSGFuZGxlOwAvTGNvbS9hbmRyb2lkL2phY2svYW5u" + - "b3RhdGlvbnMvTWV0aG9kSGFuZGxlS2luZDsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWduYXR1" + - "cmU7ABpMZGFsdmlrL2Fubm90YXRpb24vVGhyb3dzOwAITGlua2luZyAAFUxqYXZhL2lvL1By" + - "aW50U3RyZWFtOwAaTGphdmEvbGFuZy9Bc3NlcnRpb25FcnJvcjsAEExqYXZhL2xhbmcvQ2xh" + - "c3MAEUxqYXZhL2xhbmcvQ2xhc3M7ABRMamF2YS9sYW5nL0NsYXNzPCo+OwASTGphdmEvbGFu" + - "Zy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAGUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRl" + - "cjsAEkxqYXZhL2xhbmcvU3lzdGVtOwAVTGphdmEvbGFuZy9UaHJvd2FibGU7ABtMamF2YS9s" + - "YW5nL2ludm9rZS9DYWxsU2l0ZTsAI0xqYXZhL2xhbmcvaW52b2tlL0NvbnN0YW50Q2FsbFNp" + - "dGU7AB9MamF2YS9sYW5nL2ludm9rZS9NZXRob2RIYW5kbGU7ACdMamF2YS9sYW5nL2ludm9r" + - "ZS9NZXRob2RIYW5kbGVzJExvb2t1cDsAHUxqYXZhL2xhbmcvaW52b2tlL01ldGhvZFR5cGU7" + - "AAFTACpUZXN0TGlua2VyTWV0aG9kTXVsdGlwbGVBcmd1bWVudFR5cGVzLmphdmEAAVYAA1ZC" + - "QgADVkNDAANWREQAA1ZGRgACVkkAA1ZJSQADVkpKAAJWTAADVkxMAANWU1MAAlZaAAFaAAda" + - "QkNTSUZEAAJaTAABYQADYWRkAAZhcHBlbmQADWFyZ3VtZW50VHlwZXMADGFzc2VydEVxdWFs" + - "cwARYXNzZXJ0RXF1YWxzIGIxOiAAEWFzc2VydEVxdWFscyBjMTogABFhc3NlcnRFcXVhbHMg" + - "ZDE6IAARYXNzZXJ0RXF1YWxzIGYxOiAAEWFzc2VydEVxdWFscyBpMTogABFhc3NlcnRFcXVh" + - "bHMgbDE6IAARYXNzZXJ0RXF1YWxzIHMxOiAAEmFzc2VydEVxdWFsczogbzE6IAAKYXNzZXJ0" + - "VHJ1ZQASYXNzZXJ0VHJ1ZSB2YWx1ZTogAAFiAAJiMQACYjIADGJvb2xlYW5WYWx1ZQARYm9v" + - "dHN0cmFwUnVuQ291bnQACWJ5dGVWYWx1ZQACYzEAAmMyAAZjYWxsZXIACWNoYXJWYWx1ZQAK" + - "Y2xhc3NWYWx1ZQACZDEAAmQyAAtkb3VibGVWYWx1ZQASZW1pdHRlcjogamFjay00LjI1AA1l" + - "bmNsb3NpbmdUeXBlAAZlcXVhbHMAAmYxAAJmMgAKZmluZFN0YXRpYwAKZmxvYXRWYWx1ZQAC" + - "aTEAAmkyAAhpbnRWYWx1ZQASaW52b2tlTWV0aG9kSGFuZGxlAARraW5kAAJsMQACbDIADGxp" + - "bmtlck1ldGhvZAAJbG9uZ1ZhbHVlABVtZXRob2RIYW5kbGVFeHRyYUFyZ3MACm1ldGhvZFR5" + - "cGUABm1oX2FkZAAEbmFtZQABbwADb3V0AAFwAAdwcmludGxuAApyZXR1cm5UeXBlAAJzMQAC" + - "czIACnNob3J0VmFsdWUAC3N0cmluZ1ZhbHVlAAR0ZXN0AAR0aGlzAAh0b1N0cmluZwACdjEA" + - "A3YxMAACdjIAAnYzAAJ2NAACdjUAAnY2AAJ2NwACdjgAAnY5AAV2YWx1ZQABeAABeQAeAAcO" + - "OQAcAAcOADECSlkHDgBZAlpbBw48AF4CX2AHDjwAdwJkZQcOWgByAmprBw5aAGgCbm8HDjwA" + - "bQJzdAcOWgB8Ant9Bw48tACCAQKAAYEBBw4tIKUgAGMCgAGBAQcOPABTAZEBBw4tARoQADkN" + - "YXp4hwGJAYoBiwGMAY0BjgGPAQCIAQQTkAEQLgcOASQPPEtaWktppYd4iGkDAnkYAE4CkgGT" + - "AQcOlngASgAHDgAABwVMHAIYBBgEcBwBHQkETBwNGBgYERgZGBwYABgBGBoYBBgDGAIYERgP" + - "GAVnGAZxGwF5F3R2HAodCAFbHAE/HQgBXRwBAAEdCAFhHAEDYR0IAYEBHAEiAAQdCAFvHAEE" + - "AR0IAWwcAXCamTFBHQgBZRwB8ZqZmZmZmQFAHQgBggEcARcSHQgBYhwBGAYdCAF1HAFmFc1b" + - "B3kXSn4YBAILAZABHAkXARc2Fy8XNxdHFy8XKxcKFzMCDAGQARwBGBQNFgAXShUBBAEEAQRh" + - "JAAEBAFwmpkxQfGamZmZmZkBQBcSGAZmFc1bBwEADwEACgCIgAT8CwGBgASUDAIKrAwBCcQM" + - "AQmkDQEJhA4BCegOAQnMDwEJrBABCZARAQmIEgEJgBMBCeATAQqsFAEJlBYCAcgWEwAAAAAA" + - "AAABAAAAAAAAAAEAAACTAAAAcAAAAAIAAAAdAAAAvAIAAAMAAAAdAAAAMAMAAAQAAAADAAAA" + - "jAQAAAUAAAAiAAAApAQAAAcAAAABAAAAtAUAAAYAAAABAAAAuAUAAAgAAAABAAAA2AUAAAMQ" + - "AAADAAAA4AUAAAEgAAAQAAAA/AUAAAYgAAABAAAAYAsAAAEQAAAUAAAAiAsAAAIgAACTAAAA" + - "RAwAAAMgAAAQAAAA+BIAAAQgAAADAAAAqRMAAAUgAAABAAAAaRQAAAAgAAABAAAAkhQAAAAQ" + - "AAABAAAA3BQAAA=="; -} diff --git a/test/952-invoke-custom/src/Main.java b/test/952-invoke-custom/src/Main.java new file mode 100644 index 0000000000..2e1db8200f --- /dev/null +++ b/test/952-invoke-custom/src/Main.java @@ -0,0 +1,90 @@ +/* + * 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.invoke.CallSite; +import java.lang.invoke.MethodType; +import java.lang.invoke.MutableCallSite; + +public class Main extends TestBase { + + private static void TestUninitializedCallSite() throws Throwable { + CallSite callSite = new MutableCallSite(MethodType.methodType(int.class)); + try { + callSite.getTarget().invoke(); + fail(); + } catch (IllegalStateException e) { + System.out.println("Caught exception from uninitialized call site"); + } + + callSite = new MutableCallSite(MethodType.methodType(String.class, int.class, char.class)); + try { + callSite.getTarget().invoke(1535, 'd'); + fail(); + } catch (IllegalStateException e) { + System.out.println("Caught exception from uninitialized call site"); + } + } + + private static void TestLinkerMethodMultipleArgumentTypes() throws Throwable { + TestLinkerMethodMultipleArgumentTypes.test(33, 67); + TestLinkerMethodMultipleArgumentTypes.test(-10000, 1000); + TestLinkerMethodMultipleArgumentTypes.test(-1000, 10000); + } + + private static void TestLinkerMethodMinimalArguments() throws Throwable { + try { + TestLinkerMethodMinimalArguments.test( + TestLinkerMethodMinimalArguments.FAILURE_TYPE_LINKER_METHOD_RETURNS_NULL, + 10, + 10); + assertNotReached(); + } catch (BootstrapMethodError e) { + assertEquals(e.getCause().getClass(), ClassCastException.class); + } + + try { + TestLinkerMethodMinimalArguments.test( + TestLinkerMethodMinimalArguments.FAILURE_TYPE_LINKER_METHOD_THROWS, 10, 11); + assertNotReached(); + } catch (BootstrapMethodError e) { + assertEquals(e.getCause().getClass(), InstantiationException.class); + } + + try { + TestLinkerMethodMinimalArguments.test( + TestLinkerMethodMinimalArguments.FAILURE_TYPE_TARGET_METHOD_THROWS, 10, 12); + assertNotReached(); + } catch (ArithmeticException e) { + } + + TestLinkerMethodMinimalArguments.test( + TestLinkerMethodMinimalArguments.FAILURE_TYPE_NONE, 10, 13); + } + + private static void TestInvokeCustomWithConcurrentThreads() throws Throwable { + // This is a concurrency test that attempts to run invoke-custom on the same + // call site. + TestInvokeCustomWithConcurrentThreads.test(); + } + + public static void main(String[] args) throws Throwable { + TestUninitializedCallSite(); + TestLinkerMethodMinimalArguments(); + TestLinkerMethodMultipleArgumentTypes(); + TestLinkerUnrelatedBSM.test(); + TestInvokeCustomWithConcurrentThreads(); + } +} diff --git a/test/952-invoke-custom/src/TestBase.java b/test/952-invoke-custom/src/TestBase.java new file mode 100644 index 0000000000..25ec9b609b --- /dev/null +++ b/test/952-invoke-custom/src/TestBase.java @@ -0,0 +1,95 @@ +/* + * 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.util.Objects; + +abstract class TestBase { + static void assertTrue(boolean value) { + if (!value) { + throw new AssertionError("assertTrue value: " + value); + } + } + + static void assertEquals(byte b1, byte b2) { + if (b1 == b2) { + return; + } + throw new AssertionError("assertEquals b1: " + b1 + ", b2: " + b2); + } + + static void assertEquals(char c1, char c2) { + if (c1 == c2) { + return; + } + throw new AssertionError("assertEquals c1: " + c1 + ", c2: " + c2); + } + + static void assertEquals(short s1, short s2) { + if (s1 == s2) { + return; + } + throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2); + } + + static void assertEquals(int i1, int i2) { + if (i1 == i2) { + return; + } + throw new AssertionError("assertEquals i1: " + i1 + ", i2: " + i2); + } + + static void assertEquals(long l1, long l2) { + if (l1 == l2) { + return; + } + throw new AssertionError("assertEquals l1: " + l1 + ", l2: " + l2); + } + + static void assertEquals(float f1, float f2) { + if (f1 == f2) { + return; + } + throw new AssertionError("assertEquals f1: " + f1 + ", f2: " + f2); + } + + static void assertEquals(double d1, double d2) { + if (d1 == d2) { + return; + } + throw new AssertionError("assertEquals d1: " + d1 + ", d2: " + d2); + } + + static void assertEquals(Object o, Object p) { + if (!Objects.equals(o, p)) { + throw new AssertionError("assertEquals: o1: " + o + ", o2: " + p); + } + } + + static void assertNotEquals(Object o, Object p) { + if (Objects.equals(o, p)) { + throw new AssertionError("assertNotEquals: o1: " + o + ", o2: " + p); + } + } + + static void assertNotReached() { + throw new AssertionError("Unreachable"); + } + + static void fail() { + System.out.println("fail"); + Thread.dumpStack(); + } +} diff --git a/test/952-invoke-custom/src/TestInvokeCustomWithConcurrentThreads.java b/test/952-invoke-custom/src/TestInvokeCustomWithConcurrentThreads.java new file mode 100644 index 0000000000..761d1820db --- /dev/null +++ b/test/952-invoke-custom/src/TestInvokeCustomWithConcurrentThreads.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import annotations.CalledByIndy; +import annotations.LinkerMethodHandle; +import annotations.MethodHandleKind; +import java.lang.invoke.CallSite; +import java.lang.invoke.ConstantCallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicInteger; + +public class TestInvokeCustomWithConcurrentThreads extends TestBase implements Runnable { + private static final int NUMBER_OF_THREADS = 16; + + private static final AtomicInteger nextIndex = new AtomicInteger(0); + + private static final ThreadLocal<Integer> threadIndex = + new ThreadLocal<Integer>() { + @Override + protected Integer initialValue() { + return nextIndex.getAndIncrement(); + } + }; + + // Array of call sites instantiated, one per thread + private static final CallSite[] instantiated = new CallSite[NUMBER_OF_THREADS]; + + // Array of counters for how many times each instantiated call site is called + private static final AtomicInteger[] called = new AtomicInteger[NUMBER_OF_THREADS]; + + // Array of call site indicies of which call site a thread invoked + private static final AtomicInteger[] targetted = new AtomicInteger[NUMBER_OF_THREADS]; + + // Synchronization barrier all threads will wait on in the bootstrap method. + private static final CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_THREADS); + + private TestInvokeCustomWithConcurrentThreads() {} + + private static int getThreadIndex() { + return threadIndex.get().intValue(); + } + + public static int notUsed(int x) { + return x; + } + + public void run() { + int x = setCalled(-1 /* argument dropped */); + notUsed(x); + } + + @CalledByIndy( + invokeMethodHandle = + @LinkerMethodHandle( + kind = MethodHandleKind.INVOKE_STATIC, + enclosingType = TestInvokeCustomWithConcurrentThreads.class, + name = "linkerMethod", + argumentTypes = {MethodHandles.Lookup.class, String.class, MethodType.class} + ), + name = "setCalled", + returnType = int.class, + argumentTypes = {int.class} + ) + private static int setCalled(int index) { + called[index].getAndIncrement(); + targetted[getThreadIndex()].set(index); + return 0; + } + + @SuppressWarnings("unused") + private static CallSite linkerMethod( + MethodHandles.Lookup caller, String name, MethodType methodType) throws Throwable { + MethodHandle mh = + caller.findStatic(TestInvokeCustomWithConcurrentThreads.class, name, methodType); + assertEquals(methodType, mh.type()); + assertEquals(mh.type().parameterCount(), 1); + mh = MethodHandles.insertArguments(mh, 0, getThreadIndex()); + mh = MethodHandles.dropArguments(mh, 0, int.class); + assertEquals(mh.type().parameterCount(), 1); + assertEquals(methodType, mh.type()); + + // Wait for all threads to be in this method. + // Multiple call sites should be created, but only one + // invoked. + barrier.await(); + + instantiated[getThreadIndex()] = new ConstantCallSite(mh); + return instantiated[getThreadIndex()]; + } + + public static void test() throws Throwable { + // Initialize counters for which call site gets invoked + for (int i = 0; i < NUMBER_OF_THREADS; ++i) { + called[i] = new AtomicInteger(0); + targetted[i] = new AtomicInteger(0); + } + + // Run threads that each invoke-custom the call site + Thread[] threads = new Thread[NUMBER_OF_THREADS]; + for (int i = 0; i < NUMBER_OF_THREADS; ++i) { + threads[i] = new Thread(new TestInvokeCustomWithConcurrentThreads()); + threads[i].start(); + } + + // Wait for all threads to complete + for (int i = 0; i < NUMBER_OF_THREADS; ++i) { + threads[i].join(); + } + + // Check one call site instance won + int winners = 0; + int votes = 0; + for (int i = 0; i < NUMBER_OF_THREADS; ++i) { + assertNotEquals(instantiated[i], null); + if (called[i].get() != 0) { + winners++; + votes += called[i].get(); + } + } + + System.out.println("Winners " + winners + " Votes " + votes); + + // We assert this below but output details when there's an error as + // it's non-deterministic. + if (winners != 1) { + System.out.println("Threads did not the same call-sites:"); + for (int i = 0; i < NUMBER_OF_THREADS; ++i) { + System.out.format( + " Thread % 2d invoked call site instance #%02d\n", i, targetted[i].get()); + } + } + + // We assert this below but output details when there's an error as + // it's non-deterministic. + if (votes != NUMBER_OF_THREADS) { + System.out.println("Call-sites invocations :"); + for (int i = 0; i < NUMBER_OF_THREADS; ++i) { + System.out.format( + " Call site instance #%02d was invoked % 2d times\n", i, called[i].get()); + } + } + + assertEquals(winners, 1); + assertEquals(votes, NUMBER_OF_THREADS); + } +} diff --git a/test/952-invoke-custom/src/TestLinkerMethodMinimalArguments.java b/test/952-invoke-custom/src/TestLinkerMethodMinimalArguments.java new file mode 100644 index 0000000000..74ac3cd15e --- /dev/null +++ b/test/952-invoke-custom/src/TestLinkerMethodMinimalArguments.java @@ -0,0 +1,86 @@ +/* + * 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 annotations.CalledByIndy; +import annotations.LinkerMethodHandle; +import annotations.MethodHandleKind; +import java.lang.invoke.CallSite; +import java.lang.invoke.ConstantCallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class TestLinkerMethodMinimalArguments extends TestBase { + private static int forceFailureType = 0; + + static final int FAILURE_TYPE_NONE = 0; + static final int FAILURE_TYPE_LINKER_METHOD_RETURNS_NULL = 1; + static final int FAILURE_TYPE_LINKER_METHOD_THROWS = 2; + static final int FAILURE_TYPE_TARGET_METHOD_THROWS = 3; + + @CalledByIndy( + invokeMethodHandle = + @LinkerMethodHandle( + kind = MethodHandleKind.INVOKE_STATIC, + enclosingType = TestLinkerMethodMinimalArguments.class, + argumentTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}, + name = "linkerMethod" + ), + name = "_add", + returnType = int.class, + argumentTypes = {int.class, int.class} + ) + private static int add(int a, int b) { + assertNotReached(); + return -1; + } + + @SuppressWarnings("unused") + static int _add(int a, int b) { + if (forceFailureType == FAILURE_TYPE_TARGET_METHOD_THROWS) { + System.out.println("Throwing ArithmeticException in add()"); + throw new ArithmeticException("add"); + } + return a + b; + } + + @SuppressWarnings("unused") + private static CallSite linkerMethod( + MethodHandles.Lookup caller, String name, MethodType methodType) throws Throwable { + System.out.println("linkerMethod failure type " + forceFailureType); + MethodHandle mh_add = + caller.findStatic(TestLinkerMethodMinimalArguments.class, name, methodType); + switch (forceFailureType) { + case FAILURE_TYPE_LINKER_METHOD_RETURNS_NULL: + System.out.println( + "Returning null instead of CallSite for " + name + " " + methodType); + return null; + case FAILURE_TYPE_LINKER_METHOD_THROWS: + System.out.println("Throwing InstantiationException in linkerMethod()"); + throw new InstantiationException("linkerMethod"); + default: + return new ConstantCallSite(mh_add); + } + } + + public static void test(int failureType, int x, int y) throws Throwable { + assertTrue(failureType >= FAILURE_TYPE_NONE); + assertTrue(failureType <= FAILURE_TYPE_TARGET_METHOD_THROWS); + forceFailureType = failureType; + assertEquals(x + y, add(x, y)); + System.out.println("Failure Type + " + failureType + " (" + x + y + ")"); + } +} diff --git a/test/952-invoke-custom/src/TestLinkerMethodMultipleArgumentTypes.java b/test/952-invoke-custom/src/TestLinkerMethodMultipleArgumentTypes.java new file mode 100644 index 0000000000..acb698675f --- /dev/null +++ b/test/952-invoke-custom/src/TestLinkerMethodMultipleArgumentTypes.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import annotations.CalledByIndy; +import annotations.Constant; +import annotations.LinkerMethodHandle; +import annotations.MethodHandleKind; +import java.lang.invoke.CallSite; +import java.lang.invoke.ConstantCallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class TestLinkerMethodMultipleArgumentTypes extends TestBase { + + private static int bootstrapRunCount = 0; + + @CalledByIndy( + invokeMethodHandle = + @LinkerMethodHandle( + kind = MethodHandleKind.INVOKE_STATIC, + enclosingType = TestLinkerMethodMultipleArgumentTypes.class, + name = "linkerMethod", + argumentTypes = { + MethodHandles.Lookup.class, + String.class, + MethodType.class, + int.class, + int.class, + int.class, + int.class, + int.class, + float.class, + double.class, + String.class, + Class.class, + long.class + } + ), + methodHandleExtraArgs = { + @Constant(intValue = -1), + @Constant(intValue = 1), + @Constant(intValue = (int) 'a'), + @Constant(intValue = 1024), + @Constant(intValue = 1), + @Constant(floatValue = 11.1f), + @Constant(doubleValue = 2.2), + @Constant(stringValue = "Hello"), + @Constant(classValue = TestLinkerMethodMultipleArgumentTypes.class), + @Constant(longValue = 123456789L) + }, + name = "_add", + returnType = int.class, + argumentTypes = {int.class, int.class} + ) + private static int add(int a, int b) { + assertNotReached(); + return -1; + } + + @SuppressWarnings("unused") + private static int _add(int a, int b) { + return a + b; + } + + @SuppressWarnings("unused") + private static CallSite linkerMethod( + MethodHandles.Lookup caller, + String name, + MethodType methodType, + int v1, + int v2, + int v3, + int v4, + int v5, + float v6, + double v7, + String v8, + Class<?> v9, + long v10) + throws Throwable { + System.out.println("Linking " + name + " " + methodType); + assertEquals(-1, v1); + assertEquals(1, v2); + assertEquals('a', v3); + assertEquals(1024, v4); + assertEquals(1, v5); + assertEquals(11.1f, v6); + assertEquals(2.2, v7); + assertEquals("Hello", v8); + assertEquals(TestLinkerMethodMultipleArgumentTypes.class, v9); + assertEquals(123456789L, v10); + MethodHandle mh_add = + caller.findStatic(TestLinkerMethodMultipleArgumentTypes.class, name, methodType); + return new ConstantCallSite(mh_add); + } + + public int GetBootstrapRunCount() { + return bootstrapRunCount; + } + + public static void test(int x, int y) throws Throwable { + assertEquals(x + y, add(x, y)); + System.out.println(x + y); + } +} diff --git a/test/952-invoke-custom/src/TestLinkerUnrelatedBSM.java b/test/952-invoke-custom/src/TestLinkerUnrelatedBSM.java new file mode 100644 index 0000000000..3a63b332b6 --- /dev/null +++ b/test/952-invoke-custom/src/TestLinkerUnrelatedBSM.java @@ -0,0 +1,84 @@ +/* + * 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 annotations.CalledByIndy; +import annotations.Constant; +import annotations.LinkerMethodHandle; +import annotations.MethodHandleKind; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +class TestLinkerUnrelatedBSM extends TestBase { + @CalledByIndy( + invokeMethodHandle = + @LinkerMethodHandle( + kind = MethodHandleKind.INVOKE_STATIC, + enclosingType = UnrelatedBSM.class, + argumentTypes = { + MethodHandles.Lookup.class, + String.class, + MethodType.class, + Class.class + }, + name = "bsm" + ), + methodHandleExtraArgs = {@Constant(classValue = TestLinkerUnrelatedBSM.class)}, + name = "_addf", + returnType = float.class, + argumentTypes = {float.class, float.class} + ) + private static float addf(float a, float b) { + assertNotReached(); + return Float.MIN_VALUE; + } + + public static float _addf(float a, float b) { + return a + b; + } + + @CalledByIndy( + invokeMethodHandle = + @LinkerMethodHandle( + kind = MethodHandleKind.INVOKE_STATIC, + enclosingType = UnrelatedBSM.class, + argumentTypes = { + MethodHandles.Lookup.class, + String.class, + MethodType.class, + Class.class + }, + name = "bsm" + ), + methodHandleExtraArgs = {@Constant(classValue = TestLinkerUnrelatedBSM.class)}, + name = "_subf", + returnType = float.class, + argumentTypes = {float.class, float.class} + ) + private static float subf(float a, float b) { + assertNotReached(); + return Float.MIN_VALUE; + } + + private static float _subf(float a, float b) { + return a - b; + } + + public static void test() { + System.out.println(TestLinkerUnrelatedBSM.class.getName()); + assertEquals(2.5f, addf(2.0f, 0.5f)); + assertEquals(1.5f, subf(2.0f, 0.5f)); + } +} diff --git a/test/952-invoke-custom/src/UnrelatedBSM.java b/test/952-invoke-custom/src/UnrelatedBSM.java new file mode 100644 index 0000000000..1611a81f64 --- /dev/null +++ b/test/952-invoke-custom/src/UnrelatedBSM.java @@ -0,0 +1,30 @@ +/* + * 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.lang.invoke.CallSite; +import java.lang.invoke.ConstantCallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +class UnrelatedBSM { + static CallSite bsm( + MethodHandles.Lookup lookup, String name, MethodType methodType, Class<?> target) + throws Throwable { + MethodHandle mh = lookup.findStatic(target, name, methodType); + return new ConstantCallSite(mh); + } +} diff --git a/test/952-invoke-custom/src/annotations/CalledByIndy.java b/test/952-invoke-custom/src/annotations/CalledByIndy.java new file mode 100644 index 0000000000..17b8259af4 --- /dev/null +++ b/test/952-invoke-custom/src/annotations/CalledByIndy.java @@ -0,0 +1,42 @@ +/* + * 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. + */ + +package annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation can be set on method to specify that if this method is called then it must be + * called by an invokedynamic instruction. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface CalledByIndy { + LinkerMethodHandle[] invokeMethodHandle() default {}; + + LinkerFieldHandle[] fieldMethodHandle() default {}; + + String name(); + + Class<?> returnType() default void.class; + + Class<?>[] argumentTypes() default {}; + + Constant[] methodHandleExtraArgs() default {}; +} diff --git a/test/952-invoke-custom/src/annotations/Constant.java b/test/952-invoke-custom/src/annotations/Constant.java new file mode 100644 index 0000000000..7966a524ba --- /dev/null +++ b/test/952-invoke-custom/src/annotations/Constant.java @@ -0,0 +1,47 @@ +/* + * 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. + */ + +package annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Describes an annotation that allows passing a constant extra argument to a linker method. */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface Constant { + boolean[] booleanValue() default {}; + + byte[] byteValue() default {}; + + char[] charValue() default {}; + + short[] shortValue() default {}; + + int[] intValue() default {}; + + float[] floatValue() default {}; + + double[] doubleValue() default {}; + + long[] longValue() default {}; + + Class<?>[] classValue() default {}; + + String[] stringValue() default {}; +} diff --git a/test/952-invoke-custom/src/annotations/LinkerFieldHandle.java b/test/952-invoke-custom/src/annotations/LinkerFieldHandle.java new file mode 100644 index 0000000000..a3efe24107 --- /dev/null +++ b/test/952-invoke-custom/src/annotations/LinkerFieldHandle.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.invoke.CallSite; + +/** Describe a linker method to a field. */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface LinkerFieldHandle { + MethodHandleKind kind(); + + Class<?> enclosingType(); + + String name(); + + Class<?> type() default CallSite.class; +} diff --git a/test/952-invoke-custom/src/annotations/LinkerMethodHandle.java b/test/952-invoke-custom/src/annotations/LinkerMethodHandle.java new file mode 100644 index 0000000000..e0e56c578d --- /dev/null +++ b/test/952-invoke-custom/src/annotations/LinkerMethodHandle.java @@ -0,0 +1,38 @@ +/* + * 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. + */ + +package annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.invoke.CallSite; + +/** Describe a linker method to a method. */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.ANNOTATION_TYPE) +public @interface LinkerMethodHandle { + MethodHandleKind kind(); + + Class<?> enclosingType(); + + String name(); + + Class<?> returnType() default CallSite.class; + + Class<?>[] argumentTypes() default {}; +} diff --git a/test/952-invoke-custom/src/annotations/MethodHandleKind.java b/test/952-invoke-custom/src/annotations/MethodHandleKind.java new file mode 100644 index 0000000000..5847e2f39f --- /dev/null +++ b/test/952-invoke-custom/src/annotations/MethodHandleKind.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package annotations; + +/** MethodHandle invocations kinds supported by invokedynamic */ +public enum MethodHandleKind { + GET_FIELD, + GET_STATIC, + PUT_FIELD, + PUT_STATIC, + INVOKE_VIRTUAL, + INVOKE_STATIC, + INVOKE_SPECIAL, + INVOKE_CONSTRUCTOR, + INVOKE_INTERFACE +} diff --git a/test/952-invoke-custom/src/transformer/IndyTransformer.java b/test/952-invoke-custom/src/transformer/IndyTransformer.java new file mode 100644 index 0000000000..286c09859d --- /dev/null +++ b/test/952-invoke-custom/src/transformer/IndyTransformer.java @@ -0,0 +1,263 @@ +/* + * 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. + */ +package transformer; + +import annotations.CalledByIndy; +import annotations.Constant; +import annotations.LinkerFieldHandle; +import annotations.LinkerMethodHandle; +import annotations.MethodHandleKind; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Handle; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * Class for inserting invoke-dynamic instructions in annotated Java class files. + * + * This class replaces static method invocations of annotated methods + * with invoke-dynamic instructions. Suppose a method is annotated as: + * + * @CalledByIndy( + * invokeMethodHandle = + * @LinkerMethodHandle( + * kind = MethodHandleKind.INVOKE_STATIC, + * enclosingType = TestLinkerMethodMinimalArguments.class, + * argumentTypes = {MethodHandles.Lookup.class, String.class, MethodType.class}, + * name = "linkerMethod" + * ), + * name = "magicAdd", + * returnType = int.class, + * argumentTypes = {int.class, int.class} + * ) + * private int add(int x, int y) { + * throw new UnsupportedOperationException(e); + * } + * + * private int magicAdd(int x, int y) { + * return x + y; + * } + * + * Then invokestatic bytecodes targeting the add() method will be + * replaced invokedynamic instructions targetting the CallSite that is + * construction by the bootstrap method described by the @CalledByIndy + * annotation. + * + * In the example above, this results in add() being replaced by + * invocations of magicAdd(). + */ +class IndyTransformer { + + static class BootstrapBuilder extends ClassVisitor { + + private final Map<String, CalledByIndy> callsiteMap; + private final Map<String, Handle> bsmMap = new HashMap<>(); + + public BootstrapBuilder(int api, Map<String, CalledByIndy> callsiteMap) { + this(api, null, callsiteMap); + } + + public BootstrapBuilder(int api, ClassVisitor cv, Map<String, CalledByIndy> callsiteMap) { + super(api, cv); + this.callsiteMap = callsiteMap; + } + + @Override + public MethodVisitor visitMethod( + int access, String name, String desc, String signature, String[] exceptions) { + MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); + return new MethodVisitor(this.api, mv) { + @Override + public void visitMethodInsn( + int opcode, String owner, String name, String desc, boolean itf) { + if (opcode == org.objectweb.asm.Opcodes.INVOKESTATIC) { + CalledByIndy callsite = callsiteMap.get(name); + if (callsite != null) { + insertIndy(callsite.name(), desc, callsite); + return; + } + } + mv.visitMethodInsn(opcode, owner, name, desc, itf); + } + + private void insertIndy(String name, String desc, CalledByIndy callsite) { + Handle bsm = buildBootstrapMethodHandle(callsite); + Object[] bsmArgs = buildBootstrapArguments(callsite); + mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); + } + + private Handle buildBootstrapMethodHandle(CalledByIndy callsite) { + MethodHandleKind kind; + if (callsite.fieldMethodHandle().length != 0) { + return buildBootstrapMethodHandleForField(callsite.fieldMethodHandle()[0]); + } else if (callsite.invokeMethodHandle().length != 0) { + return buildBootstrapMethodHandleForMethod( + callsite.invokeMethodHandle()[0]); + } else { + throw new Error("Missing linker method handle in CalledByIndy annotation"); + } + } + + private Handle buildBootstrapMethodHandleForField(LinkerFieldHandle fieldHandle) { + int handleKind; + switch (fieldHandle.kind()) { + case GET_FIELD: + handleKind = Opcodes.H_GETFIELD; + break; + case GET_STATIC: + handleKind = Opcodes.H_GETSTATIC; + break; + case PUT_FIELD: + handleKind = Opcodes.H_PUTFIELD; + break; + case PUT_STATIC: + handleKind = Opcodes.H_PUTSTATIC; + break; + default: + throw new Error("Unknown field invocation kind: " + fieldHandle.kind()); + } + Class<?> resolverClass = fieldHandle.enclosingType(); + String resolverMethod = fieldHandle.name(); + Class<?> resolverReturnType = fieldHandle.type(); + + // TODO: arguments types to invoke resolver with (default + extra args). + throw new Error("WIP"); + } + + private Handle buildBootstrapMethodHandleForMethod( + LinkerMethodHandle methodHandle) { + int handleKind; + switch (methodHandle.kind()) { + case INVOKE_CONSTRUCTOR: + handleKind = Opcodes.H_NEWINVOKESPECIAL; + break; + case INVOKE_INTERFACE: + handleKind = Opcodes.H_INVOKEINTERFACE; + break; + case INVOKE_SPECIAL: + handleKind = Opcodes.H_INVOKESPECIAL; + break; + case INVOKE_STATIC: + handleKind = Opcodes.H_INVOKESTATIC; + break; + case INVOKE_VIRTUAL: + handleKind = Opcodes.H_INVOKEVIRTUAL; + break; + default: + throw new Error( + "Unknown method invocation kind: " + methodHandle.kind()); + } + String className = Type.getInternalName(methodHandle.enclosingType()); + String methodName = methodHandle.name(); + String methodType = + MethodType.methodType( + methodHandle.returnType(), methodHandle.argumentTypes()) + .toMethodDescriptorString(); + return new Handle( + handleKind, className, methodName, methodType, false /* itf */); + } + + private Object decodeConstant(int index, Constant constant) { + if (constant.booleanValue().length == 1) { + return constant.booleanValue()[0]; + } else if (constant.byteValue().length == 1) { + return constant.byteValue()[0]; + } else if (constant.charValue().length == 1) { + return constant.charValue()[0]; + } else if (constant.shortValue().length == 1) { + return constant.shortValue()[0]; + } else if (constant.intValue().length == 1) { + return constant.intValue()[0]; + } else if (constant.longValue().length == 1) { + return constant.longValue()[0]; + } else if (constant.floatValue().length == 1) { + return constant.floatValue()[0]; + } else if (constant.doubleValue().length == 1) { + return constant.doubleValue()[0]; + } else if (constant.stringValue().length == 1) { + return constant.stringValue()[0]; + } else if (constant.classValue().length == 1) { + return Type.getType(constant.classValue()[0]); + } else { + throw new Error("Bad constant at index " + index); + } + } + + private Object[] buildBootstrapArguments(CalledByIndy callsite) { + Constant[] rawArgs = callsite.methodHandleExtraArgs(); + Object[] args = new Object[rawArgs.length]; + for (int i = 0; i < rawArgs.length; ++i) { + args[i] = decodeConstant(i, rawArgs[i]); + } + return args; + } + }; + } + } + + private static void transform(Path inputClassPath, Path outputClassPath) throws Throwable { + URLClassLoader classLoader = + new URLClassLoader( + new URL[] {inputClassPath.toUri().toURL()}, + ClassLoader.getSystemClassLoader()); + String inputClassName = inputClassPath.getFileName().toString().replace(".class", ""); + Class<?> inputClass = classLoader.loadClass(inputClassName); + Map<String, CalledByIndy> callsiteMap = new HashMap<>(); + + for (Method m : inputClass.getDeclaredMethods()) { + CalledByIndy calledByIndy = m.getAnnotation(CalledByIndy.class); + if (calledByIndy == null) { + continue; + } + if (calledByIndy.name() == null) { + throw new Error("CallByIndy annotation does not specify name"); + } + final int PRIVATE_STATIC = Modifier.STATIC | Modifier.PRIVATE; + if ((m.getModifiers() & PRIVATE_STATIC) != PRIVATE_STATIC) { + throw new Error( + "Method whose invocations should be replaced should be private and static"); + } + callsiteMap.put(m.getName(), calledByIndy); + } + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + try (InputStream is = Files.newInputStream(inputClassPath)) { + ClassReader cr = new ClassReader(is); + cr.accept(new BootstrapBuilder(Opcodes.ASM6, cw, callsiteMap), 0); + } + try (OutputStream os = Files.newOutputStream(outputClassPath)) { + os.write(cw.toByteArray()); + } + } + + public static void main(String[] args) throws Throwable { + transform(Paths.get(args[0]), Paths.get(args[1])); + } +} diff --git a/test/983-source-transform-verify/source_transform_slicer.cc b/test/983-source-transform-verify/source_transform_slicer.cc index abf32e752e..34de625ed3 100644 --- a/test/983-source-transform-verify/source_transform_slicer.cc +++ b/test/983-source-transform-verify/source_transform_slicer.cc @@ -17,15 +17,10 @@ #include "source_transform.h" #pragma clang diagnostic push -// slicer defines its own CHECK. b/65422458 -#pragma push_macro("CHECK") -#undef CHECK - // Slicer's headers have code that triggers these warnings. b/65298177 #pragma clang diagnostic ignored "-Wsign-compare" -#include "reader.h" +#include "slicer/reader.h" -#pragma pop_macro("CHECK") #pragma clang diagnostic pop namespace art { diff --git a/test/knownfailures.json b/test/knownfailures.json index fe1e31e759..cc3d200ed1 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -1,17 +1,17 @@ [ { - "tests": "1934-jvmti-signal-thread", - "description": ["Disables 1934-jvmti-signal-thread in tracing configurations"], - "variant": "trace | stream", - "bug": "http://b/67384421" - }, - { "tests": "153-reference-stress", "description": ["Disable 153-reference-stress temporarily until a fix", "arrives."], "bug": "http://b/33389022" }, { + "tests": "579-inline-infinite", + "description": ["This test seems to fail often on redefine-stress for unknown reasons"], + "variant": "redefine-stress", + "bug": "http://b/73871735" + }, + { "tests": "080-oom-fragmentation", "description": "Disable 080-oom-fragmentation due to flakes.", "bug": "http://b/33795328" @@ -673,5 +673,304 @@ "env_vars": {"SANITIZE_HOST": "address"}, "bug": "b/73060923", "description": ["ASAN issue"] + }, + { + "tests": ["1941-dispose-stress", "522-checker-regression-monitor-exit"], + "variant": "jvm", + "bug": "b/73888836", + "description": ["Hangs forever, times out."] + }, + { + "tests": [ + "004-JniTest", + "004-NativeAllocations", + "004-ReferenceMap", + "004-SignalTest", + "004-StackWalk", + "004-ThreadStress", + "004-UnsafeTest", + "005-annotations", + "008-exceptions", + "020-string", + "021-string2", + "030-bad-finalizer", + "031-class-attributes", + "034-call-null", + "038-inner-null", + "044-proxy", + "046-reflect", + "064-field-access", + "068-classloader", + "070-nio-buffer", + "071-dexfile", + "071-dexfile-get-static-size", + "071-dexfile-map-clean", + "082-inline-execute", + "086-null-super", + "087-gc-after-link", + "088-monitor-verification", + "091-override-package-private-method", + "097-duplicate-method", + "098-ddmc", + "099-vmdebug", + "100-reflect2", + "104-growth-limit", + "111-unresolvable-exception", + "115-native-bridge", + "116-nodex2oat", + "117-nopatchoat", + "118-noimage-dex2oat", + "119-noimage-patchoat", + "127-checker-secondarydex", + "129-ThreadGetId", + "130-hprof", + "1337-gc-coverage", + "1338-gc-no-los", + "134-nodex2oat-nofallback", + "134-reg-promotion", + "135-MirandaDispatch", + "136-daemon-jni-shutdown", + "137-cfi", + "138-duplicate-classes-check", + "138-duplicate-classes-check2", + "140-field-packing", + "141-class-unload", + "142-classloader2", + "143-string-value", + "144-static-field-sigquit", + "145-alloc-tracking-stress", + "146-bad-interface", + "147-stripped-dex-fallback", + "148-multithread-gc-annotations", + "150-loadlibrary", + "154-gc-loop", + "156-register-dex-file-multi-loader", + "157-void-class", + "158-app-image-class-table", + "159-app-image-fields", + "161-final-abstract-class", + "162-method-resolution", + "163-app-image-methods", + "164-resolution-trampoline-dex-cache", + "167-visit-locks", + "168-vmstack-annotated", + "201-built-in-except-detail-messages", + "203-multi-checkpoint", + "304-method-tracing", + "305-other-fault-handler", + "412-new-array", + "416-optimizing-arith-not", + "425-invoke-super", + "431-type-propagation", + "432-optimizing-cmp", + "434-invoke-direct", + "435-new-instance", + "441-checker-inliner", + "442-checker-constant-folding", + "448-multiple-returns", + "449-checker-bce", + "452-multiple-returns2", + "453-not-byte", + "454-get-vreg", + "455-checker-gvn", + "457-regs", + "458-checker-instruct-simplification", + "459-dead-phi", + "460-multiple-returns3", + "461-get-reference-vreg", + "466-get-live-vreg", + "467-regalloc-pair", + "468-checker-bool-simplif-regression", + "471-uninitialized-locals", + "472-unreachable-if-regression", + "475-regression-inliner-ids", + "480-checker-dead-blocks", + "496-checker-inlining-class-loader", + "498-type-propagation", + "501-null-constant-dce", + "501-regression-packed-switch", + "503-dead-instructions", + "504-regression-baseline-entry", + "506-verify-aput", + "509-pre-header", + "510-checker-try-catch", + "511-clinit-interface", + "515-dce-dominator", + "516-dead-move-result", + "517-checker-builder-fallthrough", + "518-null-array-get", + "520-equivalent-phi", + "529-checker-unresolved", + "530-checker-lse", + "530-checker-lse-ctor-fences", + "530-checker-lse3", + "530-checker-regression-reftyp-final", + "536-checker-intrinsic-optimization", + "536-checker-needs-access-check", + "541-regression-inlined-deopt", + "543-env-long-ref", + "545-tracing-and-jit", + "550-checker-regression-wide-store", + "551-invoke-super", + "552-checker-primitive-typeprop", + "552-invoke-non-existent-super", + "553-invoke-super", + "556-invoke-super", + "559-checker-irreducible-loop", + "563-checker-fakestring", + "564-checker-irreducible-loop", + "565-checker-doublenegbitwise", + "565-checker-irreducible-loop", + "566-polymorphic-inlining", + "567-checker-compare", + "569-checker-pattern-replacement", + "570-checker-osr", + "571-irreducible-loop", + "574-irreducible-and-constant-area", + "575-checker-string-init-alias", + "580-checker-string-fact-intrinsics", + "585-inline-unresolved", + "586-checker-null-array-get", + "587-inline-class-error", + "588-checker-irreducib-lifetime-hole", + "591-new-instance-string", + "592-checker-regression-bool-input", + "593-checker-boolean-2-integral-conv", + "593-checker-shift-and-simplifier", + "594-invoke-super", + "595-error-class", + "595-profile-saving", + "596-app-images", + "596-checker-dead-phi", + "596-monitor-inflation", + "597-deopt-busy-loop", + "597-deopt-invoke-stub", + "597-deopt-new-string", + "599-checker-irreducible-loop", + "600-verifier-fails", + "601-method-access", + "602-deoptimizeable", + "605-new-string-from-bytes", + "608-checker-unresolved-lse", + "612-jit-dex-cache", + "613-inlining-dex-cache", + "616-cha", + "616-cha-abstract", + "616-cha-interface", + "616-cha-interface-default", + "616-cha-miranda", + "622-simplifyifs-exception-edges", + "624-checker-stringops", + "626-const-class-linking", + "628-vdex", + "629-vdex-speed", + "630-safecast-array", + "631-checker-fp-abs", + "633-checker-rtp-getclass", + "634-vdex-duplicate", + "636-wrong-static-access", + "638-checker-inline-cache-intrinsic", + "638-checker-inline-caches", + "638-no-line-number", + "641-irreducible-inline", + "643-checker-bogus-ic", + "645-checker-abs-simd", + "647-jni-get-field-id", + "647-sinking-catch", + "648-inline-caches-unresolved", + "649-vdex-duplicate-method", + "652-deopt-intrinsic", + "656-annotation-lookup-generic-jni", + "656-checker-simd-opt", + "659-unpadded-array", + "660-clinit", + "660-store-8-16", + "661-classloader-allocator", + "661-oat-writer-layout", + "663-checker-select-generator", + "663-odd-dex-size", + "663-odd-dex-size2", + "663-odd-dex-size3", + "663-odd-dex-size4", + "667-jit-jni-stub", + "667-out-of-bounds", + "668-aiobe", + "674-hiddenapi", + "674-hotness-compiled", + "674-vdex-uncompress", + "675-checker-unverified-method", + "676-proxy-jit-at-first-use", + "676-resolve-field-type", + "706-checker-scheduler", + "707-checker-invalid-profile", + "714-invoke-custom-lambda-metafactory", + "800-smali", + "801-VoidCheckCast", + "802-deoptimization", + "804-class-extends-itself", + "900-hello-plugin", + "901-hello-ti-agent", + "903-hello-tagging", + "904-object-allocation", + "906-iterate-heap", + "909-attach-agent", + "910-methods", + "911-get-stack-trace", + "912-classes", + "913-heaps", + "918-fields", + "920-objects", + "922-properties", + "924-threads", + "925-threadgroups", + "927-timers", + "929-search", + "931-agent-thread", + "933-misc-events", + "936-search-onload", + "939-hello-transformation-bcp", + "944-transform-classloaders", + "946-obsolete-throw", + "948-change-annotations", + "950-redefine-intrinsic", + "952-invoke-custom", + "954-invoke-polymorphic-verifier", + "955-methodhandles-smali", + "956-methodhandles", + "957-methodhandle-transforms", + "958-methodhandle-stackframe", + "972-default-imt-collision", + "972-iface-super-multidex", + "973-default-multidex", + "974-verify-interface-super", + "975-iface-private", + "976-conflict-no-methods", + "978-virtual-interface", + "980-redefine-object", + "981-dedup-original-dex", + "983-source-transform-verify", + "986-native-method-bind", + "988-method-trace", + "989-method-trace-throw", + "993-breakpoints", + "1900-track-alloc", + "1906-suspend-list-me-first", + "1914-get-local-instance", + "1926-missed-frame-pop", + "1930-monitor-info", + "1932-monitor-events-misc", + "1935-get-set-current-frame-jit", + "1938-transform-abstract-single-impl", + "1939-proxy-frames", + "1940-ddms-ext", + "1945-proxy-method-arguments", + "1946-list-descriptors", + "1947-breakpoint-redefine-deopt" + ], + "variant": "jvm", + "bug": "b/73888836", + "description": ["Failing on JVM. Needs further investigating."] } + + ] diff --git a/test/testrunner/device_config.py b/test/testrunner/device_config.py index c7ed6f7fbc..1fad7d297d 100644 --- a/test/testrunner/device_config.py +++ b/test/testrunner/device_config.py @@ -1,7 +1,7 @@ device_config = { # Configuration syntax: # -# device: The value of ro.product.name or 'host' +# device: The value of ro.product.name or 'host' or 'jvm' # properties: (Use one or more of these). # * run-test-args: additional run-test-args # diff --git a/test/testrunner/run_build_test_target.py b/test/testrunner/run_build_test_target.py index 531508e6b3..fcc5505a95 100755 --- a/test/testrunner/run_build_test_target.py +++ b/test/testrunner/run_build_test_target.py @@ -96,15 +96,20 @@ if target.has_key('golem'): if target.has_key('run-test'): run_test_command = [os.path.join(env.ANDROID_BUILD_TOP, 'art/test/testrunner/testrunner.py')] - run_test_command += target.get('run-test', []) + test_flags = target.get('run-test', []) + run_test_command += test_flags # Let testrunner compute concurrency based on #cpus. # b/65822340 # run_test_command += ['-j', str(n_threads)] + + # In the config assume everything will run with --host and on ART. + # However for only [--jvm] this is undesirable, so don't pass in ART-specific flags. + if ['--jvm'] != test_flags: + run_test_command += ['--host'] + run_test_command += ['--dex2oat-jobs'] + run_test_command += ['4'] run_test_command += ['-b'] - run_test_command += ['--host'] run_test_command += ['--verbose'] - run_test_command += ['--dex2oat-jobs'] - run_test_command += ['4'] sys.stdout.write(str(run_test_command) + '\n') sys.stdout.flush() diff --git a/test/testrunner/target_config.py b/test/testrunner/target_config.py index 3064c76ffd..9d0377510a 100644 --- a/test/testrunner/target_config.py +++ b/test/testrunner/target_config.py @@ -31,12 +31,7 @@ target_config = { }, 'art-test-javac' : { - 'make' : 'test-art-host-gtest', - 'run-test' : [], - 'env' : { - 'ANDROID_COMPILE_WITH_JACK' : 'false', - 'ART_USE_READ_BARRIER' : 'true' - } + 'run-test' : ['--jvm'] }, # ART run-test configurations diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py index 4329ad4863..3974ccb4f9 100755 --- a/test/testrunner/testrunner.py +++ b/test/testrunner/testrunner.py @@ -136,7 +136,7 @@ def gather_test_info(): # TODO: Avoid duplication of the variant names in different lists. VARIANT_TYPE_DICT['pictest'] = {'pictest', 'npictest'} VARIANT_TYPE_DICT['run'] = {'ndebug', 'debug'} - VARIANT_TYPE_DICT['target'] = {'target', 'host'} + VARIANT_TYPE_DICT['target'] = {'target', 'host', 'jvm'} VARIANT_TYPE_DICT['trace'] = {'trace', 'ntrace', 'stream'} VARIANT_TYPE_DICT['image'] = {'picimage', 'no-image', 'multipicimage'} VARIANT_TYPE_DICT['debuggable'] = {'ndebuggable', 'debuggable'} @@ -193,7 +193,7 @@ def setup_test_env(): _user_input_variants['jvmti'].add('no-jvmti') # By default we run all 'compiler' variants. - if not _user_input_variants['compiler']: + if not _user_input_variants['compiler'] and _user_input_variants['target'] != 'jvm': _user_input_variants['compiler'].add('optimizing') _user_input_variants['compiler'].add('jit') _user_input_variants['compiler'].add('interpreter') @@ -215,7 +215,6 @@ def setup_test_env(): if not _user_input_variants['image']: # Default _user_input_variants['image'].add('picimage') - if not _user_input_variants['pictest']: # Default _user_input_variants['pictest'].add('npictest') @@ -269,11 +268,10 @@ def find_extra_device_arguments(target): """ Gets any extra arguments from the device_config. """ - if target == 'host': - return device_config.get(target, { 'run-test-args' : [] })['run-test-args'] - else: - device = get_device_name() - return device_config.get(device, { 'run-test-args' : [] })['run-test-args'] + device_name = target + if target == 'target': + device_name = get_device_name() + return device_config.get(device_name, { 'run-test-args' : [] })['run-test-args'] def get_device_name(): """ @@ -308,15 +306,27 @@ def run_tests(tests): tests: The set of tests to be run. """ options_all = '' + + # jvm does not run with all these combinations, + # or at least it doesn't make sense for most of them. + # TODO: support some jvm variants like jvmti ? + target_input_variants = _user_input_variants['target'] + uncombinated_target_input_variants = [] + if 'jvm' in target_input_variants: + _user_input_variants['target'].remove('jvm') + uncombinated_target_input_variants.append('jvm') + global total_test_count total_test_count = len(tests) - for variant_type in VARIANT_TYPE_DICT: - if not (variant_type == 'target' or 'address_sizes' in variant_type): - total_test_count *= len(_user_input_variants[variant_type]) + if target_input_variants: + for variant_type in VARIANT_TYPE_DICT: + if not (variant_type == 'target' or 'address_sizes' in variant_type): + total_test_count *= len(_user_input_variants[variant_type]) target_address_combinations = 0 - for target in _user_input_variants['target']: + for target in target_input_variants: for address_size in _user_input_variants['address_sizes_target'][target]: target_address_combinations += 1 + target_address_combinations += len(uncombinated_target_input_variants) total_test_count *= target_address_combinations if env.ART_TEST_WITH_STRACE: @@ -339,17 +349,32 @@ def run_tests(tests): if dex2oat_jobs != -1: options_all += ' --dex2oat-jobs ' + str(dex2oat_jobs) - config = itertools.product(tests, _user_input_variants['target'], _user_input_variants['run'], - _user_input_variants['prebuild'], _user_input_variants['compiler'], - _user_input_variants['relocate'], _user_input_variants['trace'], - _user_input_variants['gc'], _user_input_variants['jni'], - _user_input_variants['image'], _user_input_variants['pictest'], - _user_input_variants['debuggable'], _user_input_variants['jvmti'], - _user_input_variants['cdex_level']) + def iter_config(tests, input_variants, user_input_variants): + config = itertools.product(tests, input_variants, user_input_variants['run'], + user_input_variants['prebuild'], user_input_variants['compiler'], + user_input_variants['relocate'], user_input_variants['trace'], + user_input_variants['gc'], user_input_variants['jni'], + user_input_variants['image'], user_input_variants['pictest'], + user_input_variants['debuggable'], user_input_variants['jvmti'], + user_input_variants['cdex_level']) + return config + + # [--host, --target] combines with all the other user input variants. + config = iter_config(tests, target_input_variants, _user_input_variants) + # [--jvm] currently combines with nothing else. most of the extra flags we'd insert + # would be unrecognizable by the 'java' binary, so avoid inserting any extra flags for now. + uncombinated_config = iter_config(tests, uncombinated_target_input_variants, { 'run': [''], + 'prebuild': [''], 'compiler': [''], + 'relocate': [''], 'trace': [''], + 'gc': [''], 'jni': [''], + 'image': [''], 'pictest': [''], + 'debuggable': [''], 'jvmti': [''], + 'cdex_level': ['']}) + + def start_combination(config_tuple, address_size): + test, target, run, prebuild, compiler, relocate, trace, gc, \ + jni, image, pictest, debuggable, jvmti, cdex_level = config_tuple - for test, target, run, prebuild, compiler, relocate, trace, gc, \ - jni, image, pictest, debuggable, jvmti, cdex_level in config: - for address_size in _user_input_variants['address_sizes_target'][target]: if stop_testrunner: # When ART_TEST_KEEP_GOING is set to false, then as soon as a test # fails, stop_testrunner is set to True. When this happens, the method @@ -384,6 +409,8 @@ def run_tests(tests): if target == 'host': options_test += ' --host' + elif target == 'jvm': + options_test += ' --jvm' if run == 'ndebug': options_test += ' -O' @@ -488,6 +515,14 @@ def run_tests(tests): worker.daemon = True worker.start() + for config_tuple in config: + target = config_tuple[1] + for address_size in _user_input_variants['address_sizes_target'][target]: + start_combination(config_tuple, address_size) + + for config_tuple in uncombinated_config: + start_combination(config_tuple, "") # no address size + while threading.active_count() > 2: time.sleep(0.1) @@ -969,6 +1004,8 @@ def main(): build_targets += 'test-art-host-run-test-dependencies' if 'target' in _user_input_variants['target']: build_targets += 'test-art-target-run-test-dependencies' + if 'jvm' in _user_input_variants['target']: + build_targets += 'test-art-host-run-test-dependencies' build_command = 'make' build_command += ' DX=' build_command += ' -j' diff --git a/test/ti-stress/stress.cc b/test/ti-stress/stress.cc index 7fc289faeb..d2da244397 100644 --- a/test/ti-stress/stress.cc +++ b/test/ti-stress/stress.cc @@ -29,22 +29,19 @@ #include "utils.h" #pragma clang diagnostic push -// slicer defines its own CHECK. b/65422458 -#pragma push_macro("CHECK") -#undef CHECK // Slicer's headers have code that triggers these warnings. b/65298177 #pragma clang diagnostic ignored "-Wunused-parameter" #pragma clang diagnostic ignored "-Wsign-compare" -#include "code_ir.h" -#include "control_flow_graph.h" -#include "dex_ir.h" -#include "dex_ir_builder.h" -#include "instrumentation.h" -#include "reader.h" -#include "writer.h" - -#pragma pop_macro("CHECK") + +#include "slicer/code_ir.h" +#include "slicer/control_flow_graph.h" +#include "slicer/dex_ir.h" +#include "slicer/dex_ir_builder.h" +#include "slicer/instrumentation.h" +#include "slicer/reader.h" +#include "slicer/writer.h" + #pragma clang diagnostic pop namespace art { |