Skip to content

Commit

Permalink
8263776: [JVMCI] add helper to perform Java upcalls
Browse files Browse the repository at this point in the history
Co-authored-by: Tom Rodriguez <never@openjdk.org>
Reviewed-by: shade
Backport-of: 6b4c654
  • Loading branch information
jerboaa and Tom Rodriguez committed Aug 25, 2021
1 parent 7539e75 commit 3bc2275
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 0 deletions.
108 changes: 108 additions & 0 deletions src/hotspot/share/jvmci/jvmciRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,114 @@ JRT_ENTRY(void, JVMCIRuntime::throw_class_cast_exception(JavaThread* thread, con
SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, message);
JRT_END

class ArgumentPusher : public SignatureIterator {
protected:
JavaCallArguments* _jca;
jlong _argument;
bool _pushed;

jlong next_arg() {
guarantee(!_pushed, "one argument");
_pushed = true;
return _argument;
}

float next_float() {
guarantee(!_pushed, "one argument");
_pushed = true;
jvalue v;
v.i = (jint) _argument;
return v.f;
}

double next_double() {
guarantee(!_pushed, "one argument");
_pushed = true;
jvalue v;
v.j = _argument;
return v.d;
}

Handle next_object() {
guarantee(!_pushed, "one argument");
_pushed = true;
return Handle(Thread::current(), (oop) (address) _argument);
}

public:
ArgumentPusher(Symbol* signature, JavaCallArguments* jca, jlong argument) : SignatureIterator(signature) {
this->_return_type = T_ILLEGAL;
_jca = jca;
_argument = argument;
_pushed = false;
iterate();
}

inline void do_object() { _jca->push_oop(next_object()); }

inline void do_bool() { if (!is_return_type()) _jca->push_int((jboolean) next_arg()); }
inline void do_char() { if (!is_return_type()) _jca->push_int((jchar) next_arg()); }
inline void do_short() { if (!is_return_type()) _jca->push_int((jint) next_arg()); }
inline void do_byte() { if (!is_return_type()) _jca->push_int((jbyte) next_arg()); }
inline void do_int() { if (!is_return_type()) _jca->push_int((jint) next_arg()); }

inline void do_long() { if (!is_return_type()) _jca->push_long((jlong) next_arg()); }
inline void do_float() { if (!is_return_type()) _jca->push_float(next_float()); }
inline void do_double() { if (!is_return_type()) _jca->push_double(next_double()); }

inline void do_object(int begin, int end) { if (!is_return_type()) do_object(); }
inline void do_array(int begin, int end) { if (!is_return_type()) do_object(); }

inline void do_void() { }
};


JRT_ENTRY(jlong, JVMCIRuntime::invoke_static_method_one_arg(JavaThread* thread, Method* method, jlong argument))
ResourceMark rm;
HandleMark hm;

methodHandle mh(thread, method);
if (mh->size_of_parameters() > 1 && !mh->is_static()) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Invoked method must be static and take at most one argument");
}

Symbol* signature = mh->signature();
JavaCallArguments jca(mh->size_of_parameters());
ArgumentPusher jap(signature, &jca, argument);
BasicType return_type = jap.get_ret_type();
JavaValue result(return_type);
JavaCalls::call(&result, mh, &jca, CHECK_0);

if (return_type == T_VOID) {
return 0;
} else if (return_type == T_OBJECT || return_type == T_ARRAY) {
thread->set_vm_result((oop) result.get_jobject());
return 0;
} else {
jvalue *value = (jvalue *) result.get_value_addr();
// Narrow the value down if required (Important on big endian machines)
switch (return_type) {
case T_BOOLEAN:
return (jboolean) value->i;
case T_BYTE:
return (jbyte) value->i;
case T_CHAR:
return (jchar) value->i;
case T_SHORT:
return (jshort) value->i;
case T_INT:
case T_FLOAT:
return value->i;
case T_LONG:
case T_DOUBLE:
return value->j;
default:
fatal("Unexpected type %s", type2name(return_type));
return 0;
}
}
JRT_END

JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, bool as_string, bool newline))
ttyLocker ttyl;

Expand Down
5 changes: 5 additions & 0 deletions src/hotspot/share/jvmci/jvmciRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ class JVMCIRuntime: public AllStatic {
// Forces initialization of the JVMCI runtime.
static void force_initialization(TRAPS);

// A helper to allow invocation of an arbitrary Java method. For simplicity the method is
// restricted to a static method that takes at most one argument. For calling convention
// simplicty all types are passed by being converted into a jlong
static jlong invoke_static_method_one_arg(JavaThread* thread, Method* method, jlong argument);

// Test only function
static int test_deoptimize_call_int(JavaThread* thread, int value);
};
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/jvmci/vmStructs_jvmci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,8 @@
declare_function(JVMCIRuntime::dynamic_new_array) \
declare_function(JVMCIRuntime::dynamic_new_instance) \
\
declare_function(JVMCIRuntime::invoke_static_method_one_arg) \
\
declare_function(JVMCIRuntime::thread_is_interrupted) \
declare_function(JVMCIRuntime::vm_message) \
declare_function(JVMCIRuntime::identity_hash_code) \
Expand Down

1 comment on commit 3bc2275

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.