Fix 044-proxy. Implement proxy for now, working on x86 and ARM.
Already added a TODO to do the assembly code for x86 and ARM for proxy.
Use LLVM .ll for multi-architecture now.
Change-Id: Ibdeeee113dcf284592e9d7769d3044438cb1e453
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 08792eb..b94003a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -43,6 +43,9 @@
#include "os.h"
#include "runtime.h"
#include "runtime_support.h"
+#if defined(ART_USE_LLVM_COMPILER)
+#include "compiler_llvm/runtime_support_llvm.h"
+#endif
#include "ScopedLocalRef.h"
#include "space.h"
#include "stack_indirect_reference_table.h"
@@ -2299,6 +2302,11 @@
ObjectArray<Method>* proxy_direct_methods = proxy_class->GetDirectMethods();
CHECK_EQ(proxy_direct_methods->GetLength(), 15);
Method* proxy_constructor = proxy_direct_methods->Get(2);
+#if defined(ART_USE_LLVM_COMPILER)
+ // Ensure link.
+ // TODO: Remove this after fixing the link problem by in-place linking.
+ art_fix_stub_from_code(proxy_constructor);
+#endif
// Clone the existing constructor of Proxy (our constructor would just invoke it so steal its
// code_ too)
Method* constructor = down_cast<Method*>(proxy_constructor->Clone());
@@ -2336,7 +2344,12 @@
method->SetCoreSpillMask(refs_and_args->GetCoreSpillMask());
method->SetFpSpillMask(refs_and_args->GetFpSpillMask());
method->SetFrameSizeInBytes(refs_and_args->GetFrameSizeInBytes());
+#if !defined(ART_USE_LLVM_COMPILER)
method->SetCode(reinterpret_cast<void*>(art_proxy_invoke_handler));
+#else
+ method->SetCode(reinterpret_cast<const void*>(
+ static_cast<uintptr_t>(compiler_llvm::special_stub::kProxyStub)));
+#endif
return method;
}
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 9354bb6..a5de7a3 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -158,3 +158,5 @@
i1)
declare %JavaObject* @art_fix_stub_from_code(%JavaObject*)
+
+declare void @art_proxy_invoke_handler_from_code(%JavaObject*, ...)
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 6889ed9..cdde019 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -290,6 +290,13 @@
/*Params=*/FuncTy_30_args,
/*isVarArg=*/false);
+std::vector<Type*>FuncTy_31_args;
+FuncTy_31_args.push_back(PointerTy_1);
+FunctionType* FuncTy_31 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_31_args,
+ /*isVarArg=*/true);
+
// Function Declarations
@@ -876,6 +883,17 @@
AttrListPtr func_art_fix_stub_from_code_PAL;
func_art_fix_stub_from_code->setAttributes(func_art_fix_stub_from_code_PAL);
+Function* func_art_proxy_invoke_handler_from_code = mod->getFunction("art_proxy_invoke_handler_from_code");
+if (!func_art_proxy_invoke_handler_from_code) {
+func_art_proxy_invoke_handler_from_code = Function::Create(
+ /*Type=*/FuncTy_31,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_proxy_invoke_handler_from_code", mod); // (external, no body)
+func_art_proxy_invoke_handler_from_code->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_art_proxy_invoke_handler_from_code_PAL;
+func_art_proxy_invoke_handler_from_code->setAttributes(func_art_proxy_invoke_handler_from_code_PAL);
+
// Global Variable Declarations
diff --git a/src/compiler_llvm/ir_builder.h b/src/compiler_llvm/ir_builder.h
index 0762a0d..d199b76 100644
--- a/src/compiler_llvm/ir_builder.h
+++ b/src/compiler_llvm/ir_builder.h
@@ -89,6 +89,26 @@
return CreatePtrDisp(base, total_offset, ret_ty);
}
+ llvm::Value* LoadFromObjectOffset(llvm::Value* object_addr, int32_t offset, llvm::Type* type) {
+ // Convert offset to llvm::value
+ llvm::Value* llvm_offset = getPtrEquivInt(offset);
+ // Calculate the value's address
+ llvm::Value* value_addr = CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
+ // Load
+ return CreateLoad(value_addr);
+ }
+
+ void StoreToObjectOffset(llvm::Value* object_addr, int32_t offset, llvm::Value* new_value) {
+ // Convert offset to llvm::value
+ llvm::Value* llvm_offset = getPtrEquivInt(offset);
+ // Calculate the value's address
+ llvm::Value* value_addr = CreatePtrDisp(object_addr,
+ llvm_offset,
+ new_value->getType()->getPointerTo());
+ // Store
+ CreateStore(new_value, value_addr);
+ }
+
//--------------------------------------------------------------------------
// Runtime Helper Function
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 252daef..68ce2d8 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -88,9 +88,9 @@
} else {
// Load class object
this_object_or_class_object =
- LoadFromObjectOffset(method_object_addr,
- Method::DeclaringClassOffset().Int32Value(),
- irb_.getJObjectTy());
+ irb_.LoadFromObjectOffset(method_object_addr,
+ Method::DeclaringClassOffset().Int32Value(),
+ irb_.getJObjectTy());
}
// Actual argument (ignore method and this object)
arg_begin = arg_iter;
@@ -126,34 +126,35 @@
irb_.CreateStore(method_object_addr, method_field_addr);
// Store the line number
- StoreToObjectOffset(shadow_frame_,
- ShadowFrame::LineNumOffset(),
- irb_.getInt32(dex_file_->GetLineNumFromPC(method_, 0)));
+ irb_.StoreToObjectOffset(shadow_frame_,
+ ShadowFrame::LineNumOffset(),
+ irb_.getInt32(dex_file_->GetLineNumFromPC(method_, 0)));
// Store the number of the pointer slots
- StoreToObjectOffset(shadow_frame_,
- ShadowFrame::NumberOfReferencesOffset(),
- irb_.getInt32(sirt_size));
+ irb_.StoreToObjectOffset(shadow_frame_,
+ ShadowFrame::NumberOfReferencesOffset(),
+ irb_.getInt32(sirt_size));
// Push the shadow frame
llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
irb_.CreateCall(irb_.GetRuntime(PushShadowFrame), shadow_frame_upcast);
// Get JNIEnv
- llvm::Value* jni_env_object_addr = LoadFromObjectOffset(thread_object_addr,
- Thread::JniEnvOffset().Int32Value(),
- irb_.getJObjectTy());
+ llvm::Value* jni_env_object_addr =
+ irb_.LoadFromObjectOffset(thread_object_addr,
+ Thread::JniEnvOffset().Int32Value(),
+ irb_.getJObjectTy());
// Set thread state to kNative
- StoreToObjectOffset(thread_object_addr,
- Thread::StateOffset().Int32Value(),
- irb_.getInt32(kNative));
+ irb_.StoreToObjectOffset(thread_object_addr,
+ Thread::StateOffset().Int32Value(),
+ irb_.getInt32(kNative));
// Get callee code_addr
llvm::Value* code_addr =
- LoadFromObjectOffset(method_object_addr,
- Method::NativeMethodOffset().Int32Value(),
- GetFunctionType(method_idx_, is_static, true)->getPointerTo());
+ irb_.LoadFromObjectOffset(method_object_addr,
+ Method::NativeMethodOffset().Int32Value(),
+ GetFunctionType(method_idx_, is_static, true)->getPointerTo());
// Load actual parameters
std::vector<llvm::Value*> args;
@@ -230,18 +231,18 @@
// saved_local_ref_cookie = env->local_ref_cookie
llvm::Value* saved_local_ref_cookie =
- LoadFromObjectOffset(jni_env_object_addr,
- JNIEnvExt::LocalRefCookieOffset().Int32Value(),
- irb_.getInt32Ty());
+ irb_.LoadFromObjectOffset(jni_env_object_addr,
+ JNIEnvExt::LocalRefCookieOffset().Int32Value(),
+ irb_.getInt32Ty());
// env->local_ref_cookie = env->locals.segment_state
llvm::Value* segment_state =
- LoadFromObjectOffset(jni_env_object_addr,
- JNIEnvExt::SegmentStateOffset().Int32Value(),
- irb_.getInt32Ty());
- StoreToObjectOffset(jni_env_object_addr,
- JNIEnvExt::LocalRefCookieOffset().Int32Value(),
- segment_state);
+ irb_.LoadFromObjectOffset(jni_env_object_addr,
+ JNIEnvExt::SegmentStateOffset().Int32Value(),
+ irb_.getInt32Ty());
+ irb_.StoreToObjectOffset(jni_env_object_addr,
+ JNIEnvExt::LocalRefCookieOffset().Int32Value(),
+ segment_state);
// Call!!!
@@ -254,9 +255,9 @@
}
// Set thread state to kRunnable
- StoreToObjectOffset(thread_object_addr,
- Thread::StateOffset().Int32Value(),
- irb_.getInt32(kRunnable));
+ irb_.StoreToObjectOffset(thread_object_addr,
+ Thread::StateOffset().Int32Value(),
+ irb_.getInt32(kRunnable));
if (return_shorty == 'L') {
// If the return value is reference, it may point to SIRT, we should decode it.
@@ -267,17 +268,17 @@
// env->locals.segment_state = env->local_ref_cookie
llvm::Value* local_ref_cookie =
- LoadFromObjectOffset(jni_env_object_addr,
- JNIEnvExt::LocalRefCookieOffset().Int32Value(),
- irb_.getInt32Ty());
- StoreToObjectOffset(jni_env_object_addr,
- JNIEnvExt::SegmentStateOffset().Int32Value(),
- local_ref_cookie);
+ irb_.LoadFromObjectOffset(jni_env_object_addr,
+ JNIEnvExt::LocalRefCookieOffset().Int32Value(),
+ irb_.getInt32Ty());
+ irb_.StoreToObjectOffset(jni_env_object_addr,
+ JNIEnvExt::SegmentStateOffset().Int32Value(),
+ local_ref_cookie);
// env->local_ref_cookie = saved_local_ref_cookie
- StoreToObjectOffset(jni_env_object_addr,
- JNIEnvExt::LocalRefCookieOffset().Int32Value(),
- saved_local_ref_cookie);
+ irb_.StoreToObjectOffset(jni_env_object_addr,
+ JNIEnvExt::LocalRefCookieOffset().Int32Value(),
+ saved_local_ref_cookie);
// Pop the shadow frame
irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
@@ -348,29 +349,5 @@
return llvm::FunctionType::get(ret_type, args_type, false);
}
-llvm::Value* JniCompiler::LoadFromObjectOffset(llvm::Value* object_addr,
- int32_t offset,
- llvm::Type* type) {
- // Convert offset to llvm::value
- llvm::Value* llvm_offset = irb_.getPtrEquivInt(offset);
- // Calculate the value's address
- llvm::Value* value_addr = irb_.CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
- // Load
- return irb_.CreateLoad(value_addr);
-}
-
-void JniCompiler::StoreToObjectOffset(llvm::Value* object_addr,
- int32_t offset,
- llvm::Value* new_value) {
- // Convert offset to llvm::value
- llvm::Value* llvm_offset = irb_.getPtrEquivInt(offset);
- // Calculate the value's address
- llvm::Value* value_addr = irb_.CreatePtrDisp(object_addr,
- llvm_offset,
- new_value->getType()->getPointerTo());
- // Store
- irb_.CreateStore(new_value, value_addr);
-}
-
} // namespace compiler_llvm
} // namespace art
diff --git a/src/compiler_llvm/jni_compiler.h b/src/compiler_llvm/jni_compiler.h
index d91293d..15a789c 100644
--- a/src/compiler_llvm/jni_compiler.h
+++ b/src/compiler_llvm/jni_compiler.h
@@ -62,10 +62,6 @@
bool is_static, bool is_target_function);
private:
- llvm::Value* LoadFromObjectOffset(llvm::Value* object_addr, int32_t offset, llvm::Type* type);
-
- void StoreToObjectOffset(llvm::Value* object_addr, int32_t offset, llvm::Value* new_value);
-
CompilationUnit* cunit_;
Compiler const* compiler_;
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 50ed471..fb6cc19 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -27,6 +27,7 @@
#include "object.h"
#include "object_utils.h"
#include "runtime_support_func.h"
+#include "runtime_support_llvm.h"
#include "shadow_frame.h"
#include "stl_util.h"
#include "stringprintf.h"
@@ -2884,6 +2885,7 @@
EmitLoadActualParameters(args, callee_method_idx, dec_insn,
arg_fmt, is_static);
+#if 0
// Invoke callee
EmitUpdateLineNumFromDexPC(dex_pc);
llvm::Value* retval = irb_.CreateCall(code_addr, args);
@@ -2897,6 +2899,72 @@
if (ret_shorty != 'V') {
EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
}
+#else
+ uint32_t callee_access_flags = is_static ? kAccStatic : 0;
+ UniquePtr<OatCompilationUnit> callee_oat_compilation_unit(
+ oat_compilation_unit_->GetCallee(callee_method_idx, callee_access_flags));
+
+ char ret_shorty = callee_oat_compilation_unit->GetShorty()[0];
+
+
+ EmitUpdateLineNumFromDexPC(dex_pc);
+
+
+ llvm::BasicBlock* block_normal = CreateBasicBlockWithDexPC(dex_pc, "normal");
+ llvm::BasicBlock* block_proxy_stub = CreateBasicBlockWithDexPC(dex_pc, "proxy");
+ llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+ llvm::Type* accurate_ret_type = irb_.getJType(ret_shorty, kAccurate);
+ llvm::Value* retval_addr = NULL;
+ if (ret_shorty != 'V') {
+ retval_addr = irb_.CreateAlloca(accurate_ret_type);
+ }
+
+
+ // TODO: Remove this after we solve the proxy trampoline calling convention problem.
+ llvm::Value* code_addr_int = irb_.CreatePtrToInt(code_addr, irb_.getPtrEquivIntTy());
+ llvm::Value* proxy_stub_int = irb_.getPtrEquivInt(special_stub::kProxyStub);
+ llvm::Value* is_proxy_stub = irb_.CreateICmpEQ(code_addr_int, proxy_stub_int);
+ irb_.CreateCondBr(is_proxy_stub, block_proxy_stub, block_normal);
+
+
+ irb_.SetInsertPoint(block_normal);
+ {
+ // Invoke callee
+ llvm::Value* result = irb_.CreateCall(code_addr, args);
+ if (ret_shorty != 'V') {
+ irb_.CreateStore(result, retval_addr);
+ }
+ }
+ irb_.CreateBr(block_continue);
+
+
+ irb_.SetInsertPoint(block_proxy_stub);
+ {
+ llvm::Value* temp_space_addr;
+ if (ret_shorty != 'V') {
+ temp_space_addr = irb_.CreateAlloca(irb_.getJValueTy());
+ args.push_back(temp_space_addr);
+ }
+ irb_.CreateCall(irb_.GetRuntime(ProxyInvokeHandler), args);
+ if (ret_shorty != 'V') {
+ llvm::Value* result_addr =
+ irb_.CreateBitCast(temp_space_addr, accurate_ret_type->getPointerTo());
+ llvm::Value* retval = irb_.CreateLoad(result_addr);
+ irb_.CreateStore(retval, retval_addr);
+ }
+ }
+ irb_.CreateBr(block_continue);
+
+
+ irb_.SetInsertPoint(block_continue);
+
+ if (ret_shorty != 'V') {
+ llvm::Value* retval = irb_.CreateLoad(retval_addr);
+ EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
+ }
+ EmitGuard_ExceptionLandingPad(dex_pc);
+#endif
irb_.CreateBr(GetNextBasicBlock(dex_pc));
}
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index a271c71..0e58e9c 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -63,4 +63,5 @@
V(FindCatchBlock, art_find_catch_block_from_code) \
V(EnsureResolved, art_ensure_resolved_from_code) \
V(FixStub, art_fix_stub_from_code) \
+ V(ProxyInvokeHandler, art_proxy_invoke_handler_from_code) \
V(DecodeJObjectInThread, art_decode_jobject_in_thread)
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index c566aea..d354bee 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -19,13 +19,16 @@
#include "nth_caller_visitor.h"
#include "object.h"
#include "object_utils.h"
+#include "reflection.h"
#include "runtime_support.h"
#include "runtime_support_llvm.h"
+#include "ScopedLocalRef.h"
#include "shadow_frame.h"
#include "thread.h"
#include "thread_list.h"
#include <algorithm>
+#include <cstdarg>
#include <stdint.h>
namespace art {
@@ -629,6 +632,157 @@
return code;
}
+// Handler for invocation on proxy methods. We create a boxed argument array. And we invoke
+// the invocation handler which is a field within the proxy object receiver.
+void art_proxy_invoke_handler_from_code(Method* proxy_method, ...) {
+ va_list ap;
+ va_start(ap, proxy_method);
+
+ Object* receiver = va_arg(ap, Object*);
+ Thread* thread = Thread::Current();
+ MethodHelper proxy_mh(proxy_method);
+ const size_t num_params = proxy_mh.NumArgs();
+
+ // Start new JNI local reference state
+ JNIEnvExt* env = thread->GetJniEnv();
+ ScopedJniEnvLocalRefState env_state(env);
+
+ // Create local ref. copies of proxy method and the receiver
+ jobject rcvr_jobj = AddLocalReference<jobject>(env, receiver);
+
+ // Convert proxy method into expected interface method
+ Method* interface_method = proxy_method->FindOverriddenMethod();
+ DCHECK(interface_method != NULL);
+ DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
+
+ // Set up arguments array and place in local IRT during boxing (which may allocate/GC)
+ jvalue args_jobj[3];
+ args_jobj[0].l = rcvr_jobj;
+ args_jobj[1].l = AddLocalReference<jobject>(env, interface_method);
+ // Args array, if no arguments then NULL (don't include receiver in argument count)
+ args_jobj[2].l = NULL;
+ ObjectArray<Object>* args = NULL;
+ if ((num_params - 1) > 0) {
+ args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(num_params - 1);
+ if (args == NULL) {
+ CHECK(thread->IsExceptionPending());
+ return;
+ }
+ args_jobj[2].l = AddLocalReference<jobjectArray>(env, args);
+ }
+
+ // Get parameter types.
+ const char* shorty = proxy_mh.GetShorty();
+ ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes();
+ if (param_types == NULL) {
+ CHECK(thread->IsExceptionPending());
+ return;
+ }
+
+ // Box arguments.
+ for (size_t i = 0; i < (num_params - 1);++i) {
+ JValue val;
+ switch (shorty[i+1]) {
+ case 'Z':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'I':
+ case 'F':
+ val.i = va_arg(ap, jint);
+ break;
+ case 'L':
+ val.l = va_arg(ap, Object*);
+ break;
+ case 'D':
+ case 'J':
+ val.j = va_arg(ap, jlong);
+ break;
+ }
+ Class* param_type = param_types->Get(i);
+ if (param_type->IsPrimitive()) {
+ BoxPrimitive(param_type->GetPrimitiveType(), val);
+ if (thread->IsExceptionPending()) {
+ return;
+ }
+ }
+ args->Set(i, val.l);
+ }
+
+ // Get the InvocationHandler method and the field that holds it within the Proxy object
+ static jmethodID inv_hand_invoke_mid = NULL;
+ static jfieldID proxy_inv_hand_fid = NULL;
+ if (proxy_inv_hand_fid == NULL) {
+ ScopedLocalRef<jclass> proxy(env, env->FindClass("java/lang/reflect/Proxy"));
+ proxy_inv_hand_fid = env->GetFieldID(proxy.get(), "h", "Ljava/lang/reflect/InvocationHandler;");
+ ScopedLocalRef<jclass> inv_hand_class(env, env->FindClass("java/lang/reflect/InvocationHandler"));
+ inv_hand_invoke_mid = env->GetMethodID(inv_hand_class.get(), "invoke",
+ "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
+ }
+
+ DCHECK(env->IsInstanceOf(rcvr_jobj, env->FindClass("java/lang/reflect/Proxy")));
+
+ jobject inv_hand = env->GetObjectField(rcvr_jobj, proxy_inv_hand_fid);
+ // Call InvocationHandler.invoke
+ jobject result = env->CallObjectMethodA(inv_hand, inv_hand_invoke_mid, args_jobj);
+
+ // Place result in stack args
+ if (!thread->IsExceptionPending()) {
+ if (shorty[0] == 'V') {
+ return;
+ }
+ Object* result_ref = thread->DecodeJObject(result);
+ JValue* result_unboxed = va_arg(ap, JValue*);
+ if (result_ref == NULL) {
+ result_unboxed->l = NULL;
+ } else {
+ bool unboxed_okay = UnboxPrimitive(result_ref, proxy_mh.GetReturnType(), *result_unboxed, "result");
+ if (!unboxed_okay) {
+ thread->ClearException();
+ thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
+ "Couldn't convert result of type %s to %s",
+ PrettyTypeOf(result_ref).c_str(),
+ PrettyDescriptor(proxy_mh.GetReturnType()).c_str());
+ return;
+ }
+ }
+ } else {
+ // In the case of checked exceptions that aren't declared, the exception must be wrapped by
+ // a UndeclaredThrowableException.
+ Throwable* exception = thread->GetException();
+ thread->ClearException();
+ if (!exception->IsCheckedException()) {
+ thread->SetException(exception);
+ } else {
+ SynthesizedProxyClass* proxy_class =
+ down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
+ int throws_index = -1;
+ size_t num_virt_methods = proxy_class->NumVirtualMethods();
+ for (size_t i = 0; i < num_virt_methods; i++) {
+ if (proxy_class->GetVirtualMethod(i) == proxy_method) {
+ throws_index = i;
+ break;
+ }
+ }
+ CHECK_NE(throws_index, -1);
+ ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
+ Class* exception_class = exception->GetClass();
+ bool declares_exception = false;
+ for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
+ Class* declared_exception = declared_exceptions->Get(i);
+ declares_exception = declared_exception->IsAssignableFrom(exception_class);
+ }
+ if (declares_exception) {
+ thread->SetException(exception);
+ } else {
+ ThrowNewUndeclaredThrowableException(thread, env, exception);
+ }
+ }
+ }
+
+ va_end(ap);
+}
+
void* art_find_runtime_support_func(void* context, char const* name) {
struct func_entry_t {
char const* name;
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index ab5c804..1120251 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -19,6 +19,16 @@
namespace art {
+namespace compiler_llvm {
+namespace special_stub {
+ enum SpecialStub {
+ kProxyStub = 16,
+ kMaxSpecialStub
+ };
+}
+} // namespace compiler_llvm
+
+
class Method;
class Object;
diff --git a/src/oat/runtime/support_proxy.cc b/src/oat/runtime/support_proxy.cc
index dd92fb1..25cafc2 100644
--- a/src/oat/runtime/support_proxy.cc
+++ b/src/oat/runtime/support_proxy.cc
@@ -17,32 +17,13 @@
#include "object.h"
#include "object_utils.h"
#include "reflection.h"
+#include "runtime_support.h"
#include "thread.h"
#include "ScopedLocalRef.h"
namespace art {
-static void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) {
- ScopedLocalRef<jclass> jlr_UTE_class(env,
- env->FindClass("java/lang/reflect/UndeclaredThrowableException"));
- if (jlr_UTE_class.get() == NULL) {
- LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
- } else {
- jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>",
- "(Ljava/lang/Throwable;)V");
- jthrowable jexception = AddLocalReference<jthrowable>(env, exception);
- ScopedLocalRef<jthrowable> jlr_UTE(env,
- reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor,
- jexception)));
- int rc = env->Throw(jlr_UTE.get());
- if (rc != JNI_OK) {
- LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
- }
- }
- CHECK(self->IsExceptionPending());
-}
-
// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
// which is responsible for recording callee save registers. We explicitly handlerize incoming
// reference arguments (so they survive GC) and create a boxed argument array. Finally we invoke
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index d6efe1d..38a680e 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -16,6 +16,8 @@
#include "runtime_support.h"
+#include "ScopedLocalRef.h"
+
namespace art {
void ThrowNewIllegalAccessErrorClass(Thread* self,
@@ -529,4 +531,24 @@
return klass;
}
+void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) {
+ ScopedLocalRef<jclass> jlr_UTE_class(env,
+ env->FindClass("java/lang/reflect/UndeclaredThrowableException"));
+ if (jlr_UTE_class.get() == NULL) {
+ LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
+ } else {
+ jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>",
+ "(Ljava/lang/Throwable;)V");
+ jthrowable jexception = AddLocalReference<jthrowable>(env, exception);
+ ScopedLocalRef<jthrowable> jlr_UTE(env,
+ reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor,
+ jexception)));
+ int rc = env->Throw(jlr_UTE.get());
+ if (rc != JNI_OK) {
+ LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
+ }
+ }
+ CHECK(self->IsExceptionPending());
+}
+
} // namespace art
diff --git a/src/runtime_support.h b/src/runtime_support.h
index bbb9512..673a535 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -207,6 +207,8 @@
return class_linker->ResolveString(string_idx, referrer);
}
+extern void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception);
+
} // namespace art
#endif // ART_SRC_RUNTIME_SUPPORT_H_