summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.common_test.mk7
-rw-r--r--build/Android.gtest.mk1
-rw-r--r--runtime/arch/arm64/instruction_set_features_arm64.cc1
-rw-r--r--runtime/class_linker.cc4
-rw-r--r--runtime/instrumentation.cc46
-rw-r--r--runtime/interpreter/interpreter_common.cc5
-rw-r--r--sigchainlib/Android.bp30
-rw-r--r--sigchainlib/sigchain.cc199
-rw-r--r--sigchainlib/sigchain_test.cc187
-rw-r--r--sigchainlib/version-script32.txt2
-rw-r--r--sigchainlib/version-script64.txt2
-rw-r--r--test/004-SignalTest/signaltest.cc18
-rw-r--r--test/115-native-bridge/expected.txt2
-rw-r--r--test/115-native-bridge/nativebridge.cc16
-rw-r--r--test/1926-missed-frame-pop/src/art/Test1926.java27
-rw-r--r--test/714-invoke-custom-lambda-metafactory/expected.txt2
-rw-r--r--test/952-invoke-custom-lookup/build27
-rw-r--r--test/952-invoke-custom-lookup/classes.dexbin2700 -> 0 bytes
-rw-r--r--test/952-invoke-custom-lookup/classes.jarbin3005 -> 0 bytes
-rw-r--r--test/952-invoke-custom-lookup/expected.txt10
-rw-r--r--test/952-invoke-custom-lookup/info.txt1
-rwxr-xr-x[-rw-r--r--]test/952-invoke-custom/build36
-rw-r--r--test/952-invoke-custom/expected.txt5
-rw-r--r--test/952-invoke-custom/generator/TestInvokeCustomWithConcurrentThreads.java231
-rw-r--r--test/952-invoke-custom/generator/TestLinkerMethodMinimalArguments.java137
-rw-r--r--test/952-invoke-custom/generator/TestLinkerMethodMultipleArgumentTypes.java140
-rwxr-xr-xtest/952-invoke-custom/generator/build-test.sh86
-rw-r--r--test/952-invoke-custom/info.txt10
-rw-r--r--test/952-invoke-custom/src-art/Main.java159
-rw-r--r--test/952-invoke-custom/src-art/TestDataInvokeCustomWithConcurrentThreads.java147
-rw-r--r--test/952-invoke-custom/src-art/TestDataLinkerMethodMinimalArguments.java106
-rw-r--r--test/952-invoke-custom/src-art/TestDataLinkerMethodMultipleArgumentTypes.java108
-rw-r--r--test/952-invoke-custom/src/Main.java90
-rw-r--r--test/952-invoke-custom/src/TestBase.java95
-rw-r--r--test/952-invoke-custom/src/TestInvokeCustomWithConcurrentThreads.java162
-rw-r--r--test/952-invoke-custom/src/TestLinkerMethodMinimalArguments.java86
-rw-r--r--test/952-invoke-custom/src/TestLinkerMethodMultipleArgumentTypes.java119
-rw-r--r--test/952-invoke-custom/src/TestLinkerUnrelatedBSM.java84
-rw-r--r--test/952-invoke-custom/src/UnrelatedBSM.java30
-rw-r--r--test/952-invoke-custom/src/annotations/CalledByIndy.java42
-rw-r--r--test/952-invoke-custom/src/annotations/Constant.java47
-rw-r--r--test/952-invoke-custom/src/annotations/LinkerFieldHandle.java36
-rw-r--r--test/952-invoke-custom/src/annotations/LinkerMethodHandle.java38
-rw-r--r--test/952-invoke-custom/src/annotations/MethodHandleKind.java30
-rw-r--r--test/952-invoke-custom/src/transformer/IndyTransformer.java263
-rw-r--r--test/983-source-transform-verify/source_transform_slicer.cc7
-rw-r--r--test/knownfailures.json311
-rw-r--r--test/testrunner/device_config.py2
-rwxr-xr-xtest/testrunner/run_build_test_target.py13
-rw-r--r--test/testrunner/target_config.py7
-rwxr-xr-xtest/testrunner/testrunner.py81
-rw-r--r--test/ti-stress/stress.cc21
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
deleted file mode 100644
index 670d93dedf..0000000000
--- a/test/952-invoke-custom-lookup/classes.dex
+++ /dev/null
Binary files differ
diff --git a/test/952-invoke-custom-lookup/classes.jar b/test/952-invoke-custom-lookup/classes.jar
deleted file mode 100644
index aa6a1f65fa..0000000000
--- a/test/952-invoke-custom-lookup/classes.jar
+++ /dev/null
Binary files differ
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 {