/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/symbolTable.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/oopMapCache.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/reflection.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
/*
* JSR 292 reference implementation: method handles
* The JDK 7 reference implementation represented method handle
* combinations as chains. Each link in the chain had a "vmentry"
* field which pointed at a bit of assembly code which performed
* one transformation before dispatching to the next link in the chain.
*
* The current reference implementation pushes almost all code generation
* responsibility to (trusted) Java code. A method handle contains a
* pointer to its "LambdaForm", which embodies all details of the method
* handle's behavior. The LambdaForm is a normal Java object, managed
* by a runtime coded in Java.
*/
//------------------------------------------------------------------------------
// MethodHandles::generate_adapters
//
if (_adapter_code == NULL)
{
g.generate();
}
}
//------------------------------------------------------------------------------
// MethodHandlesAdapterGenerator::generate
//
// Generate generic method handle adapters.
// Generate interpreter entries
}
// If the entry is not set, it will throw AbstractMethodError.
}
}
if (_enabled != z) {
_enabled = z;
}
}
// MemberName support
// import java_lang_invoke_MemberName.*
enum {
};
}
return init_method_MemberName(mname_oop, m, true, k);
}
return init_method_MemberName(mname_oop, m, false, k);
}
// Note: This only works if the MemberName has already been resolved.
// FIXME: how does k (receiver_limit) contribute?
return init_field_MemberName(mname_oop, klassOop(vmtarget), accessFlags_from(basic_mods), NULL, NULL, vmindex);
} else {
return NULL;
}
}
return NULL;
}
if (receiver_limit == NULL)
if (m->is_initializer()) {
} else if (receiver_limit != mklass &&
return NULL; // bad receiver limit
// it is a miranda method, so m->vtable_index is not what we want
} else if (!do_dispatch || m->can_be_statically_bound()) {
} else {
vmindex = m->vtable_index();
}
// Note: name and type can be lazily computed by resolve_MemberName,
// if Java code needs them as resolved String and MethodType objects.
// The clazz must be eagerly stored, because it provides a GC
// root to help keep alive the methodOop.
// If relevant, the vtable or itable value is stored as vmindex.
// This is done eagerly, since it is readily available without
// constructing any new objects.
// TO DO: maybe intern mname_oop
return mname_oop;
}
// The resolved MemberName must not be accompanied by an appendix argument,
// since there is no way to bind this value into the MemberName.
// Caller is responsible to prevent this from happening.
}
// LinkResolver does not report itable indexes! (fix this?)
} else if (m->can_be_statically_bound()) {
// LinkResolver reports vtable index even for final methods!
} else {
}
}
flags |= IS_FIELD | ((mods.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
// Note: name and type can be lazily computed by resolve_MemberName,
// if Java code needs them as resolved String and Class objects.
// Note that the incoming type oop might be pre-resolved (non-null).
// The base clazz and field offset (vmindex) must be eagerly stored,
// because they unambiguously identify the field.
// Although the fieldDescriptor::_index would also identify the field,
// we do not use it, because it is harder to decode.
// TO DO: maybe intern mname_oop
return mname_oop;
}
return Handle();
#if 0
info.access_flags(),
field_offset, false /*is_setter*/);
#endif
}
// JVM 2.9 Special Methods:
// A method is signature polymorphic if and only if all of the following conditions hold :
// * It is declared in the java.lang.invoke.MethodHandle class.
// * It has a single formal parameter of type Object[].
// * It has a return type of Object.
// * It has the ACC_VARARGS and ACC_NATIVE flags set.
return false;
// The following test will fail spuriously during bootstrap of MethodHandle itself:
// if (klass != SystemDictionary::MethodHandle_klass())
// Test the name instead:
return false;
if (m == NULL) return false;
}
switch (iid) {
}
assert(false, "");
return 0;
}
switch (iid) {
case vmIntrinsics::_invokeBasic: return 0;
}
return 0;
}
switch (name_id) {
// The ID _invokeGeneric stands for all non-static signature-polymorphic methods, except built-ins.
// The only built-in non-static signature-polymorphic method is MethodHandle.invokeBasic:
// There is one static signature-polymorphic method for each JVM invocation mode.
}
// Cover the case of invokeExact and any future variants of invokeFoo.
return vmIntrinsics::_invokeGeneric;
// Note: The pseudo-intrinsic _compiledLambdaForm is never linked against.
// Instead it is used to mark lambda forms bound to invokehandle or invokedynamic.
return vmIntrinsics::_none;
}
return iid;
return vmIntrinsics::_invokeGeneric;
}
return vmIntrinsics::_none;
}
// convert the external string or reflective type to an internal signature
if (intern_if_not_found) {
} else {
}
} else {
}
}
for (int i = 0; i < len; i++) {
case 'L':
return false;
continue;
case '(': case ')': case 'V':
case 'I': case 'J': case 'F': case 'D':
continue;
//case '[':
//case 'Z': case 'B': case 'C': case 'S':
default:
return false;
}
}
return true;
}
return sig;
} else if (is_basic_type_signature(sig)) {
return sig; // that was easy
if (is_subword_type(bt)) {
} else {
}
} else {
if (keep_last_arg)
if (ss.at_return_type()) {
}
if (arg_pos == keep_arg_pos) {
(int) ss.raw_length());
} else {
if (is_subword_type(bt))
}
arg_pos++;
}
}
// detune assert in case the injected argument is not a basic type:
keep_last_arg, "");
return bsig;
}
bool keep_arrays,
bool keep_basic_names) {
int array = 0;
bool prev_type = false;
for (int i = 0; i < len; i++) {
switch (ch) {
case '(': case ')':
prev_type = false;
continue;
case '[':
if (!keep_basic_names && keep_arrays)
array++;
continue;
case 'L':
{
}
if (!keep_basic_names) {
} else {
for (int j = start; j < i; j++)
prev_type = true;
}
break;
}
default:
{
ch = '[';
array = 0;
}
const char* n = NULL;
if (keep_basic_names)
if (n == NULL) {
// unknown letter, or we don't want to know its name
} else {
prev_type = true;
}
break;
}
}
// Switch break goes here to take care of array suffix:
if (prev_type) {
while (array > 0) {
--array;
}
}
array = 0;
}
}
}
return StringTable::lookup(s);
}
if (is_java_primitive(bt)) {
}
// Here are some more short cuts for common types.
// They are optional, since reference types can be resolved lazily.
if (s == vmSymbols::object_signature()) {
return object_java_mirror();
} else if (s == vmSymbols::class_signature()) {
} else if (s == vmSymbols::string_signature()) {
}
}
return NULL;
}
// An unresolved member name is a mere symbolic reference.
// which refers dirctly to JVM internals.
// Already resolved.
return mname;
}
if (!ref_kind_is_valid(ref_kind)) {
}
DEBUG_ONLY(int old_vmindex);
}
{
}
}
}
// convert the external string name to an internal symbol
return empty; // illegal name
(ref_kind == JVM_REF_invokeVirtual ||
// static invocation mode is required for _linkToVirtual, etc.:
ref_kind == JVM_REF_invokeStatic)) {
// Virtual methods invoke and invokeExact, plus internal invokers like _invokeBasic.
// For a static reference it could an internal linkage routine like _linkToVirtual, etc.
mh_invoke_id = iid;
}
}
// convert the external string or reflective type to an internal signature
TempNewSymbol type = lookup_signature(type_str(), (mh_invoke_id != vmIntrinsics::_none), CHECK_(empty));
// Time to do the lookup.
case IS_METHOD:
{
{
if (ref_kind == JVM_REF_invokeStatic) {
//do_dispatch = false; // no need, since statics are never dispatched
} else if (ref_kind == JVM_REF_invokeInterface) {
} else if (ref_kind == JVM_REF_invokeSpecial) {
do_dispatch = false; // force non-virtual linkage
} else if (ref_kind == JVM_REF_invokeVirtual) {
} else {
}
if (HAS_PENDING_EXCEPTION) {
return empty;
}
}
}
case IS_CONSTRUCTOR:
{
{
} else {
break; // will throw after end of switch
}
if (HAS_PENDING_EXCEPTION) {
return empty;
}
}
}
case IS_FIELD:
{
// This is taken from LinkResolver::resolve_field, sans access checks.
// check if field exists; i.e., if a klass containing the field def has been selected
return mname;
}
default:
}
return empty;
}
// Conversely, a member name which is only initialized from JVM internals
// may have null defc, name, and type fields.
// which refers directly to JVM internals.
}
if (suppress != 0) {
}
case IS_METHOD:
case IS_CONSTRUCTOR:
{
if (m.is_null()) break;
if (!have_defc) {
}
if (!have_name) {
//not java_lang_String::create_from_symbol; let's intern member names
}
if (!have_type) {
}
return;
}
case IS_FIELD:
{
// This is taken from LinkResolver::resolve_field, sans access checks.
break; // cannot expand
if (!have_defc) {
}
if (!have_name) {
//not java_lang_String::create_from_symbol; let's intern member names
}
if (!have_type) {
// If it is a primitive field type, don't mess with short strings like "I".
}
}
return;
}
}
}
// this code contains no safepoints!
// %%% take caller into account!
// overflow measurement:
bool classes_only = false;
}
else
}
if ((match_flags & IS_TYPE) != 0) {
// NYI, and Core Reflection works quite well for this query
}
if ((match_flags & IS_FIELD) != 0) {
continue;
continue;
// passed the filters
if (rskip > 0) {
--rskip;
return -99; // caller bug!
} else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow
}
}
}
// watch out for these guys:
bool negate_name_test = false;
// fix name so that it captures the intention of IS_CONSTRUCTOR
if (!(match_flags & IS_METHOD)) {
// constructors only
return 0; // no constructors of this method name
}
} else if (!(match_flags & IS_CONSTRUCTOR)) {
// methods only
negate_name_test = true; // if we see the name, we *omit* the entry
return 0; // no methods of this constructor name
}
} else {
// caller will accept either sort; no need to adjust name
}
if (m_name == clinit_name)
continue;
continue;
continue;
// passed the filters
if (rskip > 0) {
--rskip;
return -99; // caller bug!
} else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow
}
}
}
// return number of elements we at leasted wanted to initialize
}
//
// Here are the native methods in java.lang.invoke.MethodHandleNatives
// They are the private interface between this JVM and the HotSpot-specific
// Java code that implements JSR 292 method handles.
//
// Note: We use a JVM_ENTRY macro to define each of these, for this is the way
// that intrinsic (non-JNI) native methods are defined in HotSpot.
//
switch (which) {
case MethodHandles::GC_COUNT_GWT:
#ifdef COMPILER2
return true;
#else
return false;
#endif
}
return 0;
}
#ifndef PRODUCT
template(MethodHandles,GC_COUNT_GWT) \
template(java_lang_invoke_MemberName,MN_IS_METHOD) \
template(java_lang_invoke_MemberName,MN_IS_CONSTRUCTOR) \
template(java_lang_invoke_MemberName,MN_IS_FIELD) \
template(java_lang_invoke_MemberName,MN_IS_TYPE) \
template(java_lang_invoke_MemberName,MN_SEARCH_SUPERCLASSES) \
template(java_lang_invoke_MemberName,MN_SEARCH_INTERFACES) \
template(java_lang_invoke_MemberName,MN_REFERENCE_KIND_SHIFT) \
template(java_lang_invoke_MemberName,MN_REFERENCE_KIND_MASK) \
template(MethodHandles,GC_LAMBDA_SUPPORT) \
/*end*/
if (which < 0) return false;
bool ok = true;
int count = 0;
++count;
return false;
}
#endif // PRODUCT
#ifndef PRODUCT
if (advertise_con_value(which)) {
for (int i = 0; i < which; i++)
}
return con;
}
#endif
return 0;
}
// void init(MemberName self, AccessibleObject ref)
}
// void expand(MemberName self)
}
// void resolve(MemberName self, Class<?> caller)
JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) {
// The trusted Java code that calls this method should already have performed
// access checks on behalf of the given caller. But, we can verify this.
klassOop reference_klass = java_lang_Class::as_klassOop(java_lang_invoke_MemberName::clazz(mname()));
if (reference_klass != NULL) {
// Emulate LinkResolver::check_klass_accessability.
true)) {
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), Klass::cast(reference_klass)->external_name());
}
}
}
}
} else {
}
}
}
} else {
? (flags & JVM_ACC_STATIC) != 0
: (flags & JVM_ACC_STATIC) == 0)) {
}
}
return 0;
}
}
}
// use the other function to perform sanity checks:
}
result->obj_at_put(0, x);
x = NULL;
x = vmtarget();
} else {
else
}
}
// static native int getMembers(Class<?> defc, String matchName, String matchSig,
// int matchFlags, Class<?> caller, int skip, MemberName[] results);
}
}
}
// try a direct resolve
// %%% TO DO
}
// TO DO: expand at least some of the MemberNames, to avoid massive callbacks
return res;
}
JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
{
// Walk all nmethods depending on this call site.
}
}
JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
{
// Walk all nmethods depending on this call site.
}
}
/**
* Throws a java/lang/UnsupportedOperationException unconditionally.
* This is required by the specification of MethodHandle.invoke if
* invoked directly.
*/
THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "MethodHandle.invoke cannot be invoked reflectively");
return NULL;
}
/**
* Throws a java/lang/UnsupportedOperationException unconditionally.
* This is required by the specification of MethodHandle.invokeExact if
* invoked directly.
*/
THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "MethodHandle.invokeExact cannot be invoked reflectively");
return NULL;
}
/// JVM_RegisterMethodHandleMethods
// These are the native methods on java.lang.invoke.MethodHandleNatives.
// static native int getNamedCon(int which, Object[] name)
// static native int getMembers(Class<?> defc, String matchName, String matchSig,
// int matchFlags, Class<?> caller, int skip, MemberName[] results);
};
// UnsupportedOperationException throwers
};
/**
* Helper method to register native methods.
*/
static bool register_natives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods) {
warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
env->ExceptionClear();
return false;
}
return true;
}
/**
* This one function is exported, used by NativeLookup.
*/
if (!EnableInvokeDynamic) {
warning("JSR 292 is disabled in this JVM. Use -XX:+UnlockDiagnosticVMOptions -XX:+EnableInvokeDynamic to enable.");
return; // bind nothing
}
bool enable_MH = true;
enable_MH = false;
} else {
}
if (enable_MH) {
if (enable_MH) {
enable_MH = register_natives(env, MHN_class, MHN_methods, sizeof(MHN_methods)/sizeof(JNINativeMethod));
}
if (enable_MH) {
enable_MH = register_natives(env, MH_class, MH_methods, sizeof(MH_methods)/sizeof(JNINativeMethod));
}
}
if (TraceInvokeDynamic) {
}
if (enable_MH) {
MethodHandles::set_enabled(true);
}
}