Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  jvmciCompilerToVM.cpp   Sprache: C

 
/*
 * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * 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/classLoaderData.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmClasses.hpp"
#include "code/scopeDesc.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compilerEvent.hpp"
#include "compiler/disassembler.hpp"
#include "compiler/oopMap.hpp"
#include "interpreter/linkResolver.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "jfr/jfrEvents.hpp"
#include "jvmci/jvmciCompilerToVM.hpp"
#include "jvmci/jvmciCodeInstaller.hpp"
#include "jvmci/jvmciRuntime.hpp"
#include "logging/log.hpp"
#include "logging/logTag.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.hpp"
#include "oops/constantPool.inline.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/method.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/methodHandles.hpp"
#include "prims/nativeLookup.hpp"
#include "runtime/atomic.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/reflectionUtils.hpp"
#include "runtime/stackFrameStream.inline.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/vframe_hp.hpp"
#include "runtime/vframe.inline.hpp"
#if INCLUDE_JFR
#include "jfr/jfr.hpp"
#endif

JVMCIKlassHandle::JVMCIKlassHandle(Thread* thread, Klass* klass) {
  _thread = thread;
  _klass = klass;
  if (klass != NULL) {
    _holder = Handle(_thread, klass->klass_holder());
  }
}

JVMCIKlassHandle& JVMCIKlassHandle::operator=(Klass* klass) {
  _klass = klass;
  if (klass != NULL) {
    _holder = Handle(_thread, klass->klass_holder());
  }
  return *this;
}

static void requireInHotSpot(const char* caller, JVMCI_TRAPS) {
  if (!JVMCIENV->is_hotspot()) {
    JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot call %s from JVMCI shared library", caller));
  }
}

class JVMCITraceMark : public StackObj {
  const char* _msg;
 public:
  JVMCITraceMark(const char* msg) {
    _msg = msg;
    JVMCI_event_2("Enter %s", _msg);
  }
  ~JVMCITraceMark() {
    JVMCI_event_2(" Exit %s", _msg);
  }
};


Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
  assert(_index < _args->length(), "out of bounds");
  oop arg=((objArrayOop) (_args))->obj_at(_index++);
  assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch");
  return Handle(Thread::current(), arg);
}

// Bring the JVMCI compiler thread into the VM state.
#define JVMCI_VM_ENTRY_MARK                                       \
  MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread));       \
  ThreadInVMfromNative __tiv(thread);                             \
  HandleMarkCleaner __hm(thread);                                 \
  JavaThread* THREAD = thread;                                        \
  debug_only(VMNativeEntryWrapper __vew;)

// Native method block that transitions current thread to '_thread_in_vm'.
#define C2V_BLOCK(result_type, name, signature)      \
  JVMCI_VM_ENTRY_MARK;                               \
  ResourceMark rm;                                   \
  JNI_JVMCIENV(JVMCI::compilation_tick(thread), env);

static JavaThread* get_current_thread(bool allow_null=true) {
  Thread* thread = Thread::current_or_null_safe();
  if (thread == NULL) {
    assert(allow_null, "npe");
    return NULL;
  }
  return JavaThread::cast(thread);
}

// Entry to native method implementation that transitions
// current thread to '_thread_in_vm'.
#define C2V_VMENTRY(result_type, name, signature)        \
  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
  JavaThread* thread = get_current_thread();             \
  if (thread == NULL) {                                  \
    env->ThrowNew(JNIJVMCI::InternalError::clazz(),      \
        err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \
    return;                                              \
  }                                                      \
  C2V_BLOCK(result_type, name, signature)                \
  JVMCITraceMark jtm("CompilerToVM::" #name);

#define C2V_VMENTRY_(result_type, name, signature, result) \
  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
  JavaThread* thread = get_current_thread();             \
  if (thread == NULL) {                                  \
    env->ThrowNew(JNIJVMCI::InternalError::clazz(),      \
        err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \
    return result;                                       \
  }                                                      \
  C2V_BLOCK(result_type, name, signature)                \
  JVMCITraceMark jtm("CompilerToVM::" #name);

#define C2V_VMENTRY_NULL(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, NULL)
#define C2V_VMENTRY_0(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, 0)

// Entry to native method implementation that does not transition
// current thread to '_thread_in_vm'.
#define C2V_VMENTRY_PREFIX(result_type, name, signature) \
  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
  JavaThread* thread = get_current_thread();

#define C2V_END }

#define JNI_THROW(caller, name, msg) do {                                         \
    jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg);               \
    if (__throw_res != JNI_OK) {                                                  \
      tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \
    }                                                                             \
    return;                                                                       \
  } while (0);

#define JNI_THROW_(caller, name, msg, result) do {                                \
    jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg);               \
    if (__throw_res != JNI_OK) {                                                  \
      tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \
    }                                                                             \
    return result;                                                                \
  } while (0)

jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS);

C2V_VMENTRY_NULL(jobjectArray, readConfiguration, (JNIEnv* env))
  jobjectArray config = readConfiguration0(env, JVMCI_CHECK_NULL);
  return config;
}

C2V_VMENTRY_NULL(jobject, getFlagValue, (JNIEnv* env, jobject c2vm, jobject name_handle))
#define RETURN_BOXED_LONG(value) jvalue p; p.j = (jlong) (value); JVMCIObject box = JVMCIENV->create_box(T_LONG, &p, JVMCI_CHECK_NULL); return box.as_jobject();
#define RETURN_BOXED_DOUBLE(value) jvalue p; p.d = (jdouble) (value); JVMCIObject box = JVMCIENV->create_box(T_DOUBLE, &p, JVMCI_CHECK_NULL); return box.as_jobject();
  JVMCIObject name = JVMCIENV->wrap(name_handle);
  if (name.is_null()) {
    JVMCI_THROW_NULL(NullPointerException);
  }
  const char* cstring = JVMCIENV->as_utf8_string(name);
  const JVMFlag* flag = JVMFlag::find_declared_flag(cstring);
  if (flag == NULL) {
    return c2vm;
  }
  if (flag->is_bool()) {
    jvalue prim;
    prim.z = flag->get_bool();
    JVMCIObject box = JVMCIENV->create_box(T_BOOLEAN, &prim, JVMCI_CHECK_NULL);
    return JVMCIENV->get_jobject(box);
  } else if (flag->is_ccstr()) {
    JVMCIObject value = JVMCIENV->create_string(flag->get_ccstr(), JVMCI_CHECK_NULL);
    return JVMCIENV->get_jobject(value);
  } else if (flag->is_intx()) {
    RETURN_BOXED_LONG(flag->get_intx());
  } else if (flag->is_int()) {
    RETURN_BOXED_LONG(flag->get_int());
  } else if (flag->is_uint()) {
    RETURN_BOXED_LONG(flag->get_uint());
  } else if (flag->is_uint64_t()) {
    RETURN_BOXED_LONG(flag->get_uint64_t());
  } else if (flag->is_size_t()) {
    RETURN_BOXED_LONG(flag->get_size_t());
  } else if (flag->is_uintx()) {
    RETURN_BOXED_LONG(flag->get_uintx());
  } else if (flag->is_double()) {
    RETURN_BOXED_DOUBLE(flag->get_double());
  } else {
    JVMCI_ERROR_NULL("VM flag %s has unsupported type %s", flag->name(), flag->type_string());
  }
#undef RETURN_BOXED_LONG
#undef RETURN_BOXED_DOUBLE
C2V_END

// Macros for argument pairs representing a wrapper object and its wrapped VM pointer
#define ARGUMENT_PAIR(name) jobject name ## _obj, jlong name ## _pointer
#define UNPACK_PAIR(type, name) ((type*) name ## _pointer)

C2V_VMENTRY_NULL(jbyteArray, getBytecode, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  methodHandle method(THREAD, UNPACK_PAIR(Method, method));

  int code_size = method->code_size();
  jbyte* reconstituted_code = NEW_RESOURCE_ARRAY(jbyte, code_size);

  guarantee(method->method_holder()->is_rewritten(), "Method's holder should be rewritten");
  // iterate over all bytecodes and replace non-Java bytecodes

  for (BytecodeStream s(method); s.next() != Bytecodes::_illegal; ) {
    Bytecodes::Code code = s.code();
    Bytecodes::Code raw_code = s.raw_code();
    int bci = s.bci();
    int len = s.instruction_size();

    // Restore original byte code.
    reconstituted_code[bci] =  (jbyte) (s.is_wide()? Bytecodes::_wide : code);
    if (len > 1) {
      memcpy(reconstituted_code + (bci + 1), s.bcp()+1, len-1);
    }

    if (len > 1) {
      // Restore the big-endian constant pool indexes.
      // Cf. Rewriter::scan_method
      switch (code) {
        case Bytecodes::_getstatic:
        case Bytecodes::_putstatic:
        case Bytecodes::_getfield:
        case Bytecodes::_putfield:
        case Bytecodes::_invokevirtual:
        case Bytecodes::_invokespecial:
        case Bytecodes::_invokestatic:
        case Bytecodes::_invokeinterface:
        case Bytecodes::_invokehandle: {
          int cp_index = Bytes::get_native_u2((address) reconstituted_code + (bci + 1));
          Bytes::put_Java_u2((address) reconstituted_code + (bci + 1), (u2) cp_index);
          break;
        }

        case Bytecodes::_invokedynamic: {
          int cp_index = Bytes::get_native_u4((address) reconstituted_code + (bci + 1));
          Bytes::put_Java_u4((address) reconstituted_code + (bci + 1), (u4) cp_index);
          break;
        }

        default:
          break;
      }

      // Not all ldc byte code are rewritten.
      switch (raw_code) {
        case Bytecodes::_fast_aldc: {
          int cpc_index = reconstituted_code[bci + 1] & 0xff;
          int cp_index = method->constants()->object_to_cp_index(cpc_index);
          assert(cp_index < method->constants()->length(), "sanity check");
          reconstituted_code[bci + 1] = (jbyte) cp_index;
          break;
        }

        case Bytecodes::_fast_aldc_w: {
          int cpc_index = Bytes::get_native_u2((address) reconstituted_code + (bci + 1));
          int cp_index = method->constants()->object_to_cp_index(cpc_index);
          assert(cp_index < method->constants()->length(), "sanity check");
          Bytes::put_Java_u2((address) reconstituted_code + (bci + 1), (u2) cp_index);
          break;
        }

        default:
          break;
      }
    }
  }

  JVMCIPrimitiveArray result = JVMCIENV->new_byteArray(code_size, JVMCI_CHECK_NULL);
  JVMCIENV->copy_bytes_from(reconstituted_code, result, 0, code_size);
  return JVMCIENV->get_jbyteArray(result);
C2V_END

C2V_VMENTRY_0(jint, getExceptionTableLength, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  Method* method = UNPACK_PAIR(Method, method);
  return method->exception_table_length();
C2V_END

C2V_VMENTRY_0(jlong, getExceptionTableStart, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  Method* method = UNPACK_PAIR(Method, method);
  if (method->exception_table_length() == 0) {
    return 0L;
  }
  return (jlong) (address) method->exception_table_start();
C2V_END

C2V_VMENTRY_NULL(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject executable_handle))
  requireInHotSpot("asResolvedJavaMethod", JVMCI_CHECK_NULL);
  oop executable = JNIHandles::resolve(executable_handle);
  oop mirror = NULL;
  int slot = 0;

  if (executable->klass() == vmClasses::reflect_Constructor_klass()) {
    mirror = java_lang_reflect_Constructor::clazz(executable);
    slot = java_lang_reflect_Constructor::slot(executable);
  } else {
    assert(executable->klass() == vmClasses::reflect_Method_klass(), "wrong type");
    mirror = java_lang_reflect_Method::clazz(executable);
    slot = java_lang_reflect_Method::slot(executable);
  }
  Klass* holder = java_lang_Class::as_Klass(mirror);
  methodHandle method (THREAD, InstanceKlass::cast(holder)->method_with_idnum(slot));
  JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
}

C2V_VMENTRY_NULL(jobject, getResolvedJavaMethod, (JNIEnv* env, jobject, jobject base, jlong offset))
  Method* method = NULL;
  JVMCIObject base_object = JVMCIENV->wrap(base);
  if (base_object.is_null()) {
    method = *((Method**)(offset));
  } else {
    Handle obj = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
    if (obj->is_a(vmClasses::ResolvedMethodName_klass())) {
      method = (Method*) (intptr_t) obj->long_field(offset);
    } else {
      JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Unexpected type: %s", obj->klass()->external_name()));
    }
  }
  if (method == NULL) {
    JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Unexpected type: %s", JVMCIENV->klass_name(base_object)));
  }
  assert (method->is_method(), "invalid read");
  JVMCIObject result = JVMCIENV->get_jvmci_method(methodHandle(THREAD, method), JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
}

C2V_VMENTRY_NULL(jobject, getConstantPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass_or_method), jboolean is_klass))
  ConstantPool* cp = NULL;
  if (UNPACK_PAIR(address, klass_or_method) == 0) {
    JVMCI_THROW_NULL(NullPointerException);
  }
  if (!is_klass) {
    cp = (UNPACK_PAIR(Method, klass_or_method))->constMethod()->constants();
  } else {
    cp = InstanceKlass::cast(UNPACK_PAIR(Klass, klass_or_method))->constants();
  }

  JVMCIObject result = JVMCIENV->get_jvmci_constant_pool(constantPoolHandle(THREAD, cp), JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
}

C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed))
  JVMCIKlassHandle klass(THREAD);
  JVMCIObject base_object = JVMCIENV->wrap(base);
  jlong base_address = 0;
  if (base_object.is_non_null() && offset == oopDesc::klass_offset_in_bytes()) {
    if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
      Handle base_oop = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
      klass = base_oop->klass();
    } else {
      assert(false"What types are we actually expecting here?");
    }
  } else if (!compressed) {
    if (base_object.is_non_null()) {
      if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(base_object)) {
        base_address = (intptr_t) JVMCIENV->asMethod(base_object);
      } else if (JVMCIENV->isa_HotSpotConstantPool(base_object)) {
        base_address = (intptr_t) JVMCIENV->asConstantPool(base_object);
      } else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base_object)) {
        base_address = (intptr_t) JVMCIENV->asKlass(base_object);
      } else if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
        Handle base_oop = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
        if (base_oop->is_a(vmClasses::Class_klass())) {
          base_address = cast_from_oop<jlong>(base_oop());
        }
      }
      if (base_address == 0) {
        JVMCI_THROW_MSG_NULL(IllegalArgumentException,
                    err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", JVMCIENV->klass_name(base_object), offset, compressed ? "true" : "false"));
      }
    }
    klass = *((Klass**) (intptr_t) (base_address + offset));
  } else {
    JVMCI_THROW_MSG_NULL(IllegalArgumentException,
                err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s",
                        base_object.is_non_null() ? JVMCIENV->klass_name(base_object) : "null",
                        offset, compressed ? "true" : "false"));
  }
  assert (klass == NULL || klass->is_klass(), "invalid read");
  JVMCIObject result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
}

C2V_VMENTRY_NULL(jobject, findUniqueConcreteMethod, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), ARGUMENT_PAIR(method)))
  methodHandle method (THREAD, UNPACK_PAIR(Method, method));
  InstanceKlass* holder = InstanceKlass::cast(UNPACK_PAIR(Klass, klass));
  if (holder->is_interface()) {
    JVMCI_THROW_MSG_NULL(InternalError, err_msg("Interface %s should be handled in Java code", holder->external_name()));
  }
  if (method->can_be_statically_bound()) {
    JVMCI_THROW_MSG_NULL(InternalError, err_msg("Effectively static method %s.%s should be handled in Java code", method->method_holder()->external_name(), method->external_name()));
  }

  methodHandle ucm;
  {
    MutexLocker locker(Compile_lock);
    ucm = methodHandle(THREAD, Dependencies::find_unique_concrete_method(holder, method()));
  }
  JVMCIObject result = JVMCIENV->get_jvmci_method(ucm, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_NULL(jobject, getImplementor, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass)))
  Klass* klass = UNPACK_PAIR(Klass, klass);
  if (!klass->is_interface()) {
    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
        err_msg("Expected interface type, got %s", klass->external_name()));
  }
  InstanceKlass* iklass = InstanceKlass::cast(klass);
  JVMCIKlassHandle handle(THREAD);
  {
    // Need Compile_lock around implementor()
    MutexLocker locker(Compile_lock);
    handle = iklass->implementor();
  }
  JVMCIObject implementor = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(implementor);
C2V_END

C2V_VMENTRY_0(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  Method* method = UNPACK_PAIR(Method, method);
  return method->is_ignored_by_security_stack_walk();
C2V_END

C2V_VMENTRY_0(jboolean, isCompilable,(JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  Method* method = UNPACK_PAIR(Method, method);
  // Skip redefined methods
  if (method->is_old()) {
    return false;
  }
  return !method->is_not_compilable(CompLevel_full_optimization);
C2V_END

C2V_VMENTRY_0(jboolean, hasNeverInlineDirective,(JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  methodHandle method (THREAD, UNPACK_PAIR(Method, method));
  return !Inline || CompilerOracle::should_not_inline(method) || method->dont_inline();
C2V_END

C2V_VMENTRY_0(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  methodHandle method (THREAD, UNPACK_PAIR(Method, method));
  return CompilerOracle::should_inline(method) || method->force_inline();
C2V_END

C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGUMENT_PAIR(accessing_klass), jboolean resolve))
  JVMCIObject name = JVMCIENV->wrap(jname);
  const char* str = JVMCIENV->as_utf8_string(name);
  TempNewSymbol class_name = SymbolTable::new_symbol(str);

  if (class_name->utf8_length() <= 1) {
    JVMCI_THROW_MSG_0(InternalError, err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string()));
  }

  JVMCIKlassHandle resolved_klass(THREAD);
  Klass* accessing_klass = UNPACK_PAIR(Klass, accessing_klass);
  Handle class_loader;
  Handle protection_domain;
  if (accessing_klass != nullptr) {
    class_loader = Handle(THREAD, accessing_klass->class_loader());
    protection_domain = Handle(THREAD, accessing_klass->protection_domain());
  } else {
    // Use the System class loader
    class_loader = Handle(THREAD, SystemDictionary::java_system_loader());
    JVMCIENV->runtime()->initialize(JVMCI_CHECK_NULL);
  }

  if (resolve) {
    resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_NULL);
    if (resolved_klass == nullptr) {
      JVMCI_THROW_MSG_NULL(ClassNotFoundException, str);
    }
  } else {
    if (Signature::has_envelope(class_name)) {
      // This is a name from a signature.  Strip off the trimmings.
      // Call recursive to keep scope of strippedsym.
      TempNewSymbol strippedsym = Signature::strip_envelope(class_name);
      resolved_klass = SystemDictionary::find_instance_klass(THREAD, strippedsym,
                                                             class_loader,
                                                             protection_domain);
    } else if (Signature::is_array(class_name)) {
      SignatureStream ss(class_name, false);
      int ndim = ss.skip_array_prefix();
      if (ss.type() == T_OBJECT) {
        Symbol* strippedsym = ss.as_symbol();
        resolved_klass = SystemDictionary::find_instance_klass(THREAD, strippedsym,
                                                               class_loader,
                                                               protection_domain);
        if (!resolved_klass.is_null()) {
          resolved_klass = resolved_klass->array_klass(ndim, CHECK_NULL);
        }
      } else {
        resolved_klass = TypeArrayKlass::cast(Universe::typeArrayKlassObj(ss.type()))->array_klass(ndim, CHECK_NULL);
      }
    } else {
      resolved_klass = SystemDictionary::find_instance_klass(THREAD, class_name,
                                                             class_loader,
                                                             protection_domain);
    }
  }
  JVMCIObject result = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_NULL(jobject, getArrayType, (JNIEnv* env, jobject, jchar type_char, ARGUMENT_PAIR(klass)))
  JVMCIKlassHandle array_klass(THREAD);
  Klass* klass = UNPACK_PAIR(Klass, klass);
  if (klass == nullptr) {
    BasicType type = JVMCIENV->typeCharToBasicType(type_char, JVMCI_CHECK_0);
    if (type == T_VOID) {
      return nullptr;
    }
    array_klass = Universe::typeArrayKlassObj(type);
    if (array_klass == nullptr) {
      JVMCI_THROW_MSG_NULL(InternalError, err_msg("No array klass for primitive type %s", type2name(type)));
    }
  } else {
    array_klass = klass->array_klass(CHECK_NULL);
  }
  JVMCIObject result = JVMCIENV->get_jvmci_type(array_klass, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_NULL(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror))
  requireInHotSpot("lookupClass", JVMCI_CHECK_NULL);
  if (mirror == nullptr) {
    return nullptr;
  }
  JVMCIKlassHandle klass(THREAD);
  klass = java_lang_Class::as_Klass(JNIHandles::resolve(mirror));
  if (klass == nullptr) {
    JVMCI_THROW_MSG_NULL(IllegalArgumentException, "Primitive classes are unsupported");
  }
  JVMCIObject result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_NULL(jobject, getUncachedStringInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  constantTag tag = cp->tag_at(index);
  if (!tag.is_string()) {
    JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Unexpected constant pool tag at index %d: %d", index, tag.value()));
  }
  oop obj = cp->uncached_string_at(index, CHECK_NULL);
  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(obj));
C2V_END

C2V_VMENTRY_NULL(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  oop obj = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL);
  constantTag tag = cp->tag_at(index);
  if (tag.is_dynamic_constant() || tag.is_dynamic_constant_in_error()) {
    if (obj == Universe::the_null_sentinel()) {
      return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_NULL_POINTER());
    }
    BasicType bt = Signature::basic_type(cp->uncached_signature_ref_at(index));
    if (!is_reference_type(bt)) {
      if (!is_java_primitive(bt)) {
        return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_ILLEGAL());
      }

      // Convert standard box (e.g. java.lang.Integer) to JVMCI box (e.g. jdk.vm.ci.meta.PrimitiveConstant)
      jvalue value;
      jlong raw_value;
      jchar type_char;
      BasicType bt2 = java_lang_boxing_object::get_value(obj, &value);
      assert(bt2 == bt, "");
      switch (bt2) {
        case T_LONG:    type_char = 'J'; raw_value = value.j; break;
        case T_DOUBLE:  type_char = 'D'; raw_value = value.j; break;
        case T_FLOAT:   type_char = 'F'; raw_value = value.i; break;
        case T_INT:     type_char = 'I'; raw_value = value.i; break;
        case T_SHORT:   type_char = 'S'; raw_value = value.s; break;
        case T_BYTE:    type_char = 'B'; raw_value = value.b; break;
        case T_CHAR:    type_char = 'C'; raw_value = value.c; break;
        case T_BOOLEAN: type_char = 'Z'; raw_value = value.z; break;
        default:        return JVMCIENV->get_jobject(JVMCIENV->get_JavaConstant_ILLEGAL());
      }

      JVMCIObject result = JVMCIENV->call_JavaConstant_forPrimitive(type_char, raw_value, JVMCI_CHECK_NULL);
      return JVMCIENV->get_jobject(result);
    }
  }
  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(obj));
C2V_END

C2V_VMENTRY_NULL(jobjectArray, resolveBootstrapMethod, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  constantTag tag = cp->tag_at(index);
  bool is_indy = tag.is_invoke_dynamic();
  bool is_condy = tag.is_dynamic_constant();
  if (!(is_condy || is_indy)) {
    JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Unexpected constant pool tag at index %d: %d", index, tag.value()));
  }
  // Resolve the bootstrap specifier, its name, type, and static arguments
  BootstrapInfo bootstrap_specifier(cp, index);
  Handle bsm = bootstrap_specifier.resolve_bsm(CHECK_NULL);

  // call java.lang.invoke.MethodHandle::asFixedArity() -> MethodHandle
  // to get a DirectMethodHandle from which we can then extract a Method*
  JavaValue result(T_OBJECT);
  JavaCalls::call_virtual(&result,
                         bsm,
                         vmClasses::MethodHandle_klass(),
                         vmSymbols::asFixedArity_name(),
                         vmSymbols::asFixedArity_signature(),
                         CHECK_NULL);
  bsm = Handle(THREAD, result.get_oop());

  // Check assumption about getting a DirectMethodHandle
  if (!java_lang_invoke_DirectMethodHandle::is_instance(bsm())) {
    JVMCI_THROW_MSG_NULL(InternalError, err_msg("Unexpected MethodHandle subclass: %s", bsm->klass()->external_name()));
  }
  // Create return array describing the bootstrap method invocation (BSMI)
  JVMCIObjectArray bsmi = JVMCIENV->new_Object_array(4, JVMCI_CHECK_NULL);

  // Extract Method* and wrap it in a ResolvedJavaMethod
  Handle member = Handle(THREAD, java_lang_invoke_DirectMethodHandle::member(bsm()));
  JVMCIObject bsmi_method = JVMCIENV->get_jvmci_method(methodHandle(THREAD, java_lang_invoke_MemberName::vmtarget(member())), JVMCI_CHECK_NULL);
  JVMCIENV->put_object_at(bsmi, 0, bsmi_method);

  JVMCIObject bsmi_name = JVMCIENV->create_string(bootstrap_specifier.name(), JVMCI_CHECK_NULL);
  JVMCIENV->put_object_at(bsmi, 1, bsmi_name);

  Handle type_arg = bootstrap_specifier.type_arg();
  JVMCIObject bsmi_type = JVMCIENV->get_object_constant(type_arg());
  JVMCIENV->put_object_at(bsmi, 2, bsmi_type);

  Handle arg_values = bootstrap_specifier.arg_values();
  if (arg_values.not_null()) {
    if (!arg_values->is_array()) {
      JVMCIENV->put_object_at(bsmi, 3, JVMCIENV->get_object_constant(arg_values()));
    } else if (arg_values->is_objArray()) {
      objArrayHandle args_array = objArrayHandle(THREAD, (objArrayOop) arg_values());
      int len = args_array->length();
      JVMCIObjectArray arguments = JVMCIENV->new_JavaConstant_array(len, JVMCI_CHECK_NULL);
      JVMCIENV->put_object_at(bsmi, 3, arguments);
      for (int i = 0; i < len; i++) {
        oop x = args_array->obj_at(i);
        if (x != nullptr) {
          JVMCIENV->put_object_at(arguments, i, JVMCIENV->get_object_constant(x));
        } else {
          JVMCIENV->put_object_at(arguments, i, JVMCIENV->get_JavaConstant_NULL_POINTER());
        }
      }
    } else if (arg_values->is_typeArray()) {
      typeArrayHandle bsci = typeArrayHandle(THREAD, (typeArrayOop) arg_values());
      JVMCIPrimitiveArray arguments = JVMCIENV->new_intArray(bsci->length(), JVMCI_CHECK_NULL);
      JVMCIENV->put_object_at(bsmi, 3, arguments);
      for (int i = 0; i < bsci->length(); i++) {
        JVMCIENV->put_int_at(arguments, i, bsci->int_at(i));
      }
    }
  }
  return JVMCIENV->get_jobjectArray(bsmi);
C2V_END

C2V_VMENTRY_0(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  return cp->name_and_type_ref_index_at(index);
C2V_END

C2V_VMENTRY_NULL(jobject, lookupNameInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint which))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  JVMCIObject sym = JVMCIENV->create_string(cp->name_ref_at(which), JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(sym);
C2V_END

C2V_VMENTRY_NULL(jobject, lookupSignatureInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint which))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  JVMCIObject sym = JVMCIENV->create_string(cp->signature_ref_at(which), JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(sym);
C2V_END

C2V_VMENTRY_0(jint, lookupKlassRefIndexInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  return cp->klass_ref_index_at(index);
C2V_END

C2V_VMENTRY_NULL(jobject, resolveTypeInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  Klass* klass = cp->klass_at(index, CHECK_NULL);
  JVMCIKlassHandle resolved_klass(THREAD, klass);
  if (resolved_klass->is_instance_klass()) {
    InstanceKlass::cast(resolved_klass())->link_class(CHECK_NULL);
    if (!InstanceKlass::cast(resolved_klass())->is_linked()) {
      // link_class() should not return here if there is an issue.
      JVMCI_THROW_MSG_NULL(InternalError, err_msg("Class %s must be linked", resolved_klass()->external_name()));
    }
  }
  JVMCIObject klassObject = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(klassObject);
C2V_END

C2V_VMENTRY_NULL(jobject, lookupKlassInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  Klass* loading_klass = cp->pool_holder();
  bool is_accessible = false;
  JVMCIKlassHandle klass(THREAD, JVMCIRuntime::get_klass_by_index(cp, index, is_accessible, loading_klass));
  Symbol* symbol = nullptr;
  if (klass.is_null()) {
    constantTag tag = cp->tag_at(index);
    if (tag.is_klass()) {
      // The klass has been inserted into the constant pool
      // very recently.
      klass = cp->resolved_klass_at(index);
    } else if (tag.is_symbol()) {
      symbol = cp->symbol_at(index);
    } else {
      assert(cp->tag_at(index).is_unresolved_klass(), "wrong tag");
      symbol = cp->klass_name_at(index);
    }
  }
  JVMCIObject result;
  if (!klass.is_null()) {
    result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
  } else {
    result = JVMCIENV->create_string(symbol, JVMCI_CHECK_NULL);
  }
  return JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_NULL(jobject, lookupAppendixInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index);
  return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(appendix_oop));
C2V_END

C2V_VMENTRY_NULL(jobject, lookupMethodInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index, jbyte opcode, ARGUMENT_PAIR(caller)))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  methodHandle caller(THREAD, UNPACK_PAIR(Method, caller));
  InstanceKlass* pool_holder = cp->pool_holder();
  Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
  methodHandle method(THREAD, JVMCIRuntime::get_method_by_index(cp, index, bc, pool_holder));
  JFR_ONLY(if (method.not_null()) Jfr::on_resolution(caller(), method(), CHECK_NULL);)
  JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_0(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  return cp->remap_instruction_operand_from_cache(index);
C2V_END

C2V_VMENTRY_NULL(jobject, resolveFieldInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index, ARGUMENT_PAIR(method), jbyte opcode, jintArray info_handle))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
  fieldDescriptor fd;
  methodHandle mh(THREAD, UNPACK_PAIR(Method, method));
  LinkInfo link_info(cp, index, mh, CHECK_NULL);
  LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_NULL);
  JVMCIPrimitiveArray info = JVMCIENV->wrap(info_handle);
  if (info.is_null() || JVMCIENV->get_length(info) != 3) {
    JVMCI_ERROR_NULL("info must not be null and have a length of 3");
  }
  JVMCIENV->put_int_at(info, 0, fd.access_flags().as_int());
  JVMCIENV->put_int_at(info, 1, fd.offset());
  JVMCIENV->put_int_at(info, 2, fd.index());
  JVMCIKlassHandle handle(THREAD, fd.field_holder());
  JVMCIObject field_holder = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(field_holder);
C2V_END

C2V_VMENTRY_0(jint, getVtableIndexForInterfaceMethod, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), ARGUMENT_PAIR(method)))
  Klass* klass = UNPACK_PAIR(Klass, klass);
  methodHandle method(THREAD, UNPACK_PAIR(Method, method));
  InstanceKlass* holder = method->method_holder();
  if (klass->is_interface()) {
    JVMCI_THROW_MSG_0(InternalError, err_msg("Interface %s should be handled in Java code", klass->external_name()));
  }
  if (!holder->is_interface()) {
    JVMCI_THROW_MSG_0(InternalError, err_msg("Method %s is not held by an interface, this case should be handled in Java code", method->name_and_sig_as_C_string()));
  }
  if (!klass->is_instance_klass()) {
    JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s must be instance klass", klass->external_name()));
  }
  if (!InstanceKlass::cast(klass)->is_linked()) {
    JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s must be linked", klass->external_name()));
  }
  if (!klass->is_subtype_of(holder)) {
    JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s does not implement interface %s", klass->external_name(), holder->external_name()));
  }
  return LinkResolver::vtable_index_of_interface_method(klass, method);
C2V_END

C2V_VMENTRY_NULL(jobject, resolveMethod, (JNIEnv* env, jobject, ARGUMENT_PAIR(receiver), ARGUMENT_PAIR(method), ARGUMENT_PAIR(caller)))
  Klass* recv_klass = UNPACK_PAIR(Klass, receiver);
  Klass* caller_klass = UNPACK_PAIR(Klass, caller);
  methodHandle method(THREAD, UNPACK_PAIR(Method, method));

  Klass* resolved     = method->method_holder();
  Symbol* h_name      = method->name();
  Symbol* h_signature = method->signature();

  if (MethodHandles::is_signature_polymorphic_method(method())) {
      // Signature polymorphic methods are already resolved, JVMCI just returns NULL in this case.
      return nullptr;
  }

  if (method->name() == vmSymbols::clone_name() &&
      resolved == vmClasses::Object_klass() &&
      recv_klass->is_array_klass()) {
    // Resolution of the clone method on arrays always returns Object.clone even though that method
    // has protected access.  There's some trickery in the access checking to make this all work out
    // so it's necessary to pass in the array class as the resolved class to properly trigger this.
    // Otherwise it's impossible to resolve the array clone methods through JVMCI.  See
    // LinkResolver::check_method_accessability for the matching logic.
    resolved = recv_klass;
  }

  LinkInfo link_info(resolved, h_name, h_signature, caller_klass);
  Method* m = nullptr;
  // Only do exact lookup if receiver klass has been linked.  Otherwise,
  // the vtable has not been setup, and the LinkResolver will fail.
  if (recv_klass->is_array_klass() ||
      (InstanceKlass::cast(recv_klass)->is_linked() && !recv_klass->is_interface())) {
    if (resolved->is_interface()) {
      m = LinkResolver::resolve_interface_call_or_null(recv_klass, link_info);
    } else {
      m = LinkResolver::resolve_virtual_call_or_null(recv_klass, link_info);
    }
  }

  if (m == nullptr) {
    // Return NULL if there was a problem with lookup (uninitialized class, etc.)
    return nullptr;
  }

  JVMCIObject result = JVMCIENV->get_jvmci_method(methodHandle(THREAD, m), JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_0(jboolean, hasFinalizableSubclass,(JNIEnv* env, jobject, ARGUMENT_PAIR(klass)))
  Klass* klass = UNPACK_PAIR(Klass, klass);
  assert(klass != nullptr, "method must not be called for primitive types");
  if (!klass->is_instance_klass()) {
    return false;
  }
  InstanceKlass* iklass = InstanceKlass::cast(klass);
  return Dependencies::find_finalizable_subclass(iklass) != nullptr;
C2V_END

C2V_VMENTRY_NULL(jobject, getClassInitializer, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass)))
  Klass* klass = UNPACK_PAIR(Klass, klass);
  if (!klass->is_instance_klass()) {
    return nullptr;
  }
  InstanceKlass* iklass = InstanceKlass::cast(klass);
  methodHandle clinit(THREAD, iklass->class_initializer());
  JVMCIObject result = JVMCIENV->get_jvmci_method(clinit, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_0(jlong, getMaxCallTargetOffset, (JNIEnv* env, jobject, jlong addr))
  address target_addr = (address) addr;
  if (target_addr != 0x0) {
    int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int));
    int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int));
    return MAX2(ABS(off_low), ABS(off_high));
  }
  return -1;
C2V_END

C2V_VMENTRY(void, setNotInlinableOrCompilable,(JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  methodHandle method(THREAD, UNPACK_PAIR(Method, method));
  method->set_not_c1_compilable();
  method->set_not_c2_compilable();
  method->set_dont_inline(true);
C2V_END

C2V_VMENTRY_0(jint, getInstallCodeFlags, (JNIEnv *env, jobject))
  int flags = 0;
#ifndef PRODUCT
  flags |= 0x0001; // VM will install block comments
  flags |= 0x0004; // Enable HotSpotJVMCIRuntime.Option.CodeSerializationTypeInfo if not explicitly set
#endif
  if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
    // VM needs to track method dependencies
    flags |= 0x0002;
  }
  return flags;
C2V_END

C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject,
    jlong compiled_code_buffer,
    jlong serialization_ns,
    bool with_type_info,
    jobject compiled_code,
    jobjectArray object_pool,
    jobject installed_code,
    jlong failed_speculations_address,
    jbyteArray speculations_obj))
  HandleMark hm(THREAD);
  JNIHandleMark jni_hm(thread);

  JVMCIObject compiled_code_handle = JVMCIENV->wrap(compiled_code);
  objArrayHandle object_pool_handle(thread, JVMCIENV->is_hotspot() ? (objArrayOop) JNIHandles::resolve(object_pool) : nullptr);

  CodeBlob* cb = NULL;
  JVMCIObject installed_code_handle = JVMCIENV->wrap(installed_code);
  JVMCIPrimitiveArray speculations_handle = JVMCIENV->wrap(speculations_obj);

  int speculations_len = JVMCIENV->get_length(speculations_handle);
  char* speculations = NEW_RESOURCE_ARRAY(char, speculations_len);
  JVMCIENV->copy_bytes_to(speculations_handle, (jbyte*) speculations, 0, speculations_len);

  JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK_JNI_ERR);
  JVMCICompiler::CodeInstallStats* stats = compiler->code_install_stats(!thread->is_Compiler_thread());
  elapsedTimer *timer = stats->timer();
  timer->add_nanoseconds(serialization_ns);
  TraceTime install_time("installCode", timer);

  CodeInstaller installer(JVMCIENV);

  JVMCI::CodeInstallResult result = installer.install(compiler,
      compiled_code_buffer,
      with_type_info,
      compiled_code_handle,
      object_pool_handle,
      cb,
      installed_code_handle,
      (FailedSpeculation**)(address) failed_speculations_address,
      speculations,
      speculations_len,
      JVMCI_CHECK_0);

  if (PrintCodeCacheOnCompilation) {
    stringStream s;
    // Dump code cache into a buffer before locking the tty,
    {
      MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
      CodeCache::print_summary(&s, false);
    }
    ttyLocker ttyl;
    tty->print_raw_cr(s.freeze());
  }

  if (result != JVMCI::ok) {
    assert(cb == NULL, "should be");
  } else {
    stats->on_install(cb);
    if (installed_code_handle.is_non_null()) {
      if (cb->is_nmethod()) {
        assert(JVMCIENV->isa_HotSpotNmethod(installed_code_handle), "wrong type");
        // Clear the link to an old nmethod first
        JVMCIObject nmethod_mirror = installed_code_handle;
        JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, JVMCI_CHECK_0);
      } else {
        assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type");
      }
      // Initialize the link to the new code blob
      JVMCIENV->initialize_installed_code(installed_code_handle, cb, JVMCI_CHECK_0);
    }
  }
  return result;
C2V_END

C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv* env, jobject))
  JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK);
  CompilerStatistics* stats = compiler->stats();
  stats->_standard.reset();
  stats->_osr.reset();
C2V_END

C2V_VMENTRY_NULL(jobject, disassembleCodeBlob, (JNIEnv* env, jobject, jobject installedCode))
  HandleMark hm(THREAD);

  if (installedCode == NULL) {
    JVMCI_THROW_MSG_NULL(NullPointerException, "installedCode is null");
  }

  JVMCIObject installedCodeObject = JVMCIENV->wrap(installedCode);
  CodeBlob* cb = JVMCIENV->get_code_blob(installedCodeObject);
  if (cb == NULL) {
    return NULL;
  }

  // We don't want the stringStream buffer to resize during disassembly as it
  // uses scoped resource memory. If a nested function called during disassembly uses
  // a ResourceMark and the buffer expands within the scope of the mark,
  // the buffer becomes garbage when that scope is exited. Experience shows that
  // the disassembled code is typically about 10x the code size so a fixed buffer
  // sized to 20x code size plus a fixed amount for header info should be sufficient.
  int bufferSize = cb->code_size() * 20 + 1024;
  char* buffer = NEW_RESOURCE_ARRAY(char, bufferSize);
  stringStream st(buffer, bufferSize);
  Disassembler::decode(cb, &st);
  if (st.size() <= 0) {
    return NULL;
  }

  JVMCIObject result = JVMCIENV->create_string(st.as_string(), JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_NULL(jobject, getStackTraceElement, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), int bci))
  HandleMark hm(THREAD);

  methodHandle method(THREAD, UNPACK_PAIR(Method, method));
  JVMCIObject element = JVMCIENV->new_StackTraceElement(method, bci, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(element);
C2V_END

C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject args, jobject hs_nmethod))
  // The incoming arguments array would have to contain JavaConstants instead of regular objects
  // and the return value would have to be wrapped as a JavaConstant.
  requireInHotSpot("executeHotSpotNmethod", JVMCI_CHECK_NULL);

  HandleMark hm(THREAD);

  JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
  nmethod* nm = JVMCIENV->get_nmethod(nmethod_mirror);
  if (nm == NULL || !nm->is_in_use()) {
    JVMCI_THROW_NULL(InvalidInstalledCodeException);
  }
  methodHandle mh(THREAD, nm->method());
  Symbol* signature = mh->signature();
  JavaCallArguments jca(mh->size_of_parameters());

  JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
  JavaValue result(jap.return_type());
  jca.set_alternative_target(Handle(THREAD, JNIHandles::resolve(nmethod_mirror.as_jobject())));
  JavaCalls::call(&result, mh, &jca, CHECK_NULL);

  if (jap.return_type() == T_VOID) {
    return NULL;
  } else if (is_reference_type(jap.return_type())) {
    return JNIHandles::make_local(THREAD, result.get_oop());
  } else {
    jvalue *value = (jvalue *) result.get_value_addr();
    // Narrow the value down if required (Important on big endian machines)
    switch (jap.return_type()) {
      case T_BOOLEAN:
       value->z = (jboolean) value->i;
       break;
      case T_BYTE:
       value->b = (jbyte) value->i;
       break;
      case T_CHAR:
       value->c = (jchar) value->i;
       break;
      case T_SHORT:
       value->s = (jshort) value->i;
       break;
      default:
        break;
    }
    JVMCIObject o = JVMCIENV->create_box(jap.return_type(), value, JVMCI_CHECK_NULL);
    return JVMCIENV->get_jobject(o);
  }
C2V_END

C2V_VMENTRY_NULL(jlongArray, getLineNumberTable, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  Method* method = UNPACK_PAIR(Method, method);
  if (!method->has_linenumber_table()) {
    return NULL;
  }
  u2 num_entries = 0;
  CompressedLineNumberReadStream streamForSize(method->compressed_linenumber_table());
  while (streamForSize.read_pair()) {
    num_entries++;
  }

  CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
  JVMCIPrimitiveArray result = JVMCIENV->new_longArray(2 * num_entries, JVMCI_CHECK_NULL);

  int i = 0;
  jlong value;
  while (stream.read_pair()) {
    value = ((jlong) stream.bci());
    JVMCIENV->put_long_at(result, i, value);
    value = ((jlong) stream.line());
    JVMCIENV->put_long_at(result, i + 1, value);
    i += 2;
  }

  return (jlongArray) JVMCIENV->get_jobject(result);
C2V_END

C2V_VMENTRY_0(jlong, getLocalVariableTableStart, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  Method* method = UNPACK_PAIR(Method, method);
  if (!method->has_localvariable_table()) {
    return 0;
  }
  return (jlong) (address) method->localvariable_table_start();
C2V_END

C2V_VMENTRY_0(jint, getLocalVariableTableLength, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  Method* method = UNPACK_PAIR(Method, method);
  return method->localvariable_table_length();
C2V_END

C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
  methodHandle method(THREAD, UNPACK_PAIR(Method, method));
  MethodCounters* mcs = method->method_counters();
  if (mcs != NULL) {
    mcs->clear_counters();
  }
  NOT_PRODUCT(method->set_compiled_invocation_count(0));

  CompiledMethod* code = method->code();
  if (code != NULL) {
    code->make_not_entrant();
  }

  MethodData* method_data = method->method_data();
  if (method_data == NULL) {
    ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
    method_data = MethodData::allocate(loader_data, method, CHECK);
    method->set_method_data(method_data);
  } else {
    method_data->initialize();
  }
C2V_END


C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize))
  JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
  JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, JVMCI_CHECK);
C2V_END

C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject))
  // Returns a zero length array if counters aren't enabled
  JVMCIPrimitiveArray array = JVMCIENV->new_longArray(JVMCICounterSize, JVMCI_CHECK_NULL);
  if (JVMCICounterSize > 0) {
    jlong* temp_array = NEW_RESOURCE_ARRAY(jlong, JVMCICounterSize);
    JavaThread::collect_counters(temp_array, JVMCICounterSize);
    JVMCIENV->copy_longs_from(temp_array, array, 0, JVMCICounterSize);
  }
  return (jlongArray) JVMCIENV->get_jobject(array);
C2V_END

C2V_VMENTRY_0(jint, getCountersSize, (JNIEnv* env, jobject))
  return (jint) JVMCICounterSize;
C2V_END

C2V_VMENTRY_0(jboolean, setCountersSize, (JNIEnv* env, jobject, jint new_size))
  return JavaThread::resize_all_jvmci_counters(new_size);
C2V_END

C2V_VMENTRY_0(jint, allocateCompileId, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), int entry_bci))
  HandleMark hm(THREAD);
  methodHandle method(THREAD, UNPACK_PAIR(Method, method));
  if (method.is_null()) {
    JVMCI_THROW_0(NullPointerException);
  }
  if (entry_bci >= method->code_size() || entry_bci < -1) {
    JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Unexpected bci %d", entry_bci));
  }
  return CompileBroker::assign_compile_id_unlocked(THREAD, method, entry_bci);
C2V_END


C2V_VMENTRY_0(jboolean, isMature, (JNIEnv* env, jobject, jlong method_data_pointer))
  MethodData* mdo = (MethodData*) method_data_pointer;
  return mdo != NULL && mdo->is_mature();
C2V_END

C2V_VMENTRY_0(jboolean, hasCompiledCodeForOSR, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), int entry_bci, int comp_level))
  Method* method = UNPACK_PAIR(Method, method);
  return method->lookup_osr_nmethod_for(entry_bci, comp_level, true) != NULL;
C2V_END

C2V_VMENTRY_NULL(jobject, getSymbol, (JNIEnv* env, jobject, jlong symbol))
  JVMCIObject sym = JVMCIENV->create_string((Symbol*)(address)symbol, JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(sym);
C2V_END

C2V_VMENTRY_NULL(jobject, getSignatureName, (JNIEnv* env, jobject, jlong klass_pointer))
  Klass* klass = UNPACK_PAIR(Klass, klass);
  JVMCIObject signature = JVMCIENV->create_string(klass->signature_name(), JVMCI_CHECK_NULL);
  return JVMCIENV->get_jobject(signature);
C2V_END

/*
 * Used by matches() to convert a ResolvedJavaMethod[] to an array of Method*.
 */

GrowableArray<Method*>* init_resolved_methods(jobjectArray methods, JVMCIEnv* JVMCIENV) {
  objArrayOop methods_oop = (objArrayOop) JNIHandles::resolve(methods);
  GrowableArray<Method*>* resolved_methods = new GrowableArray<Method*>(methods_oop->length());
  for (int i = 0; i < methods_oop->length(); i++) {
    oop resolved = methods_oop->obj_at(i);
    Method* resolved_method = NULL;
    if (resolved->klass() == HotSpotJVMCI::HotSpotResolvedJavaMethodImpl::klass()) {
      resolved_method = HotSpotJVMCI::asMethod(JVMCIENV, resolved);
    }
    resolved_methods->append(resolved_method);
  }
  return resolved_methods;
}

/*
 * Used by c2v_iterateFrames to check if `method` matches one of the ResolvedJavaMethods in the `methods` array.
 * The ResolvedJavaMethod[] array is converted to a Method* array that is then cached in the resolved_methods_ref in/out parameter.
 * In case of a match, the matching ResolvedJavaMethod is returned in matched_jvmci_method_ref.
 */

bool matches(jobjectArray methods, Method* method, GrowableArray<Method*>** resolved_methods_ref, Handle* matched_jvmci_method_ref, Thread* THREAD, JVMCIEnv* JVMCIENV) {
  GrowableArray<Method*>* resolved_methods = *resolved_methods_ref;
  if (resolved_methods == NULL) {
    resolved_methods = init_resolved_methods(methods, JVMCIENV);
    *resolved_methods_ref = resolved_methods;
  }
  assert(method != NULL, "method should not be NULL");
  assert(resolved_methods->length() == ((objArrayOop) JNIHandles::resolve(methods))->length(), "arrays must have the same length");
  for (int i = 0; i < resolved_methods->length(); i++) {
    Method* m = resolved_methods->at(i);
    if (m == method) {
      *matched_jvmci_method_ref = Handle(THREAD, ((objArrayOop) JNIHandles::resolve(methods))->obj_at(i));
      return true;
    }
  }
  return false;
}

/*
 * Resolves an interface call to a concrete method handle.
 */

methodHandle resolve_interface_call(Klass* spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
  CallInfo callinfo;
  Handle receiver = args->receiver();
  Klass* recvrKlass = receiver.is_null() ? (Klass*)NULL : receiver->klass();
  LinkInfo link_info(spec_klass, name, signature);
  LinkResolver::resolve_interface_call(
          callinfo, receiver, recvrKlass, link_info, true, CHECK_(methodHandle()));
  methodHandle method(THREAD, callinfo.selected_method());
  assert(method.not_null(), "should have thrown exception");
  return method;
}

/*
 * Used by c2v_iterateFrames to make a new vframeStream at the given compiled frame id (stack pointer) and vframe id.
 */

void resync_vframestream_to_compiled_frame(vframeStream& vfst, intptr_t* stack_pointer, int vframe_id, JavaThread* thread, TRAPS) {
  vfst = vframeStream(thread);
  while (vfst.frame_id() != stack_pointer && !vfst.at_end()) {
    vfst.next();
  }
  if (vfst.frame_id() != stack_pointer) {
    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "stack frame not found after deopt")
  }
  if (vfst.is_interpreted_frame()) {
    THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "compiled stack frame expected")
  }
  while (vfst.vframe_id() != vframe_id) {
    if (vfst.at_end()) {
      THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "vframe not found after deopt")
    }
    vfst.next();
    assert(!vfst.is_interpreted_frame(), "Wrong frame type");
  }
}

/*
 * Used by c2v_iterateFrames. Returns an array of any unallocated scope objects or NULL if none.
 */

GrowableArray<ScopeValue*>* get_unallocated_objects_or_null(GrowableArray<ScopeValue*>* scope_objects) {
  GrowableArray<ScopeValue*>* unallocated = NULL;
  for (int i = 0; i < scope_objects->length(); i++) {
    ObjectValue* sv = (ObjectValue*) scope_objects->at(i);
    if (sv->value().is_null()) {
      if (unallocated == NULL) {
        unallocated = new GrowableArray<ScopeValue*>(scope_objects->length());
      }
      unallocated->append(sv);
    }
  }
  return unallocated;
}

C2V_VMENTRY_NULL(jobject, iterateFrames, (JNIEnv* env, jobject compilerToVM, jobjectArray initial_methods, jobjectArray match_methods, jint initialSkip, jobject visitor_handle))

  if (!thread->has_last_Java_frame()) {
    return NULL;
  }
  Handle visitor(THREAD, JNIHandles::resolve_non_null(visitor_handle));

  requireInHotSpot("iterateFrames", JVMCI_CHECK_NULL);

  HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);

  vframeStream vfst(thread);
  jobjectArray methods = initial_methods;
  methodHandle visitor_method;
  GrowableArray<Method*>* resolved_methods = NULL;

  while (!vfst.at_end()) { // frame loop
    bool realloc_called = false;
    intptr_t* frame_id = vfst.frame_id();

    // Previous compiledVFrame of this frame; use with at_scope() to reuse scope object pool.
    compiledVFrame* prev_cvf = NULL;

    for (; !vfst.at_end() && vfst.frame_id() == frame_id; vfst.next()) { // vframe loop
      int frame_number = 0;
      Method *method = vfst.method();
      int bci = vfst.bci();

      Handle matched_jvmci_method;
      if (methods == NULL || matches(methods, method, &resolved_methods, &matched_jvmci_method, THREAD, JVMCIENV)) {
        if (initialSkip > 0) {
          initialSkip--;
          continue;
        }
        javaVFrame* vf;
        if (prev_cvf != NULL && prev_cvf->frame_pointer()->id() == frame_id) {
          assert(prev_cvf->is_compiled_frame(), "expected compiled Java frame");
          vf = prev_cvf->at_scope(vfst.decode_offset(), vfst.vframe_id());
        } else {
          vf = vfst.asJavaVFrame();
        }

        StackValueCollection* locals = NULL;
        typeArrayHandle localIsVirtual_h;
        if (vf->is_compiled_frame()) {
          // compiled method frame
          compiledVFrame* cvf = compiledVFrame::cast(vf);

          ScopeDesc* scope = cvf->scope();
          // native wrappers do not have a scope
          if (scope != NULL && scope->objects() != NULL) {
            prev_cvf = cvf;

            GrowableArray<ScopeValue*>* objects = NULL;
            if (!realloc_called) {
              objects = scope->objects();
            } else {
              // some object might already have been re-allocated, only reallocate the non-allocated ones
              objects = get_unallocated_objects_or_null(scope->objects());
            }

            if (objects != NULL) {
              RegisterMap reg_map(vf->register_map());
              bool realloc_failures = Deoptimization::realloc_objects(thread, vf->frame_pointer(), ®_map,&nbsp;objects, CHECK_NULL);
              Deoptimization::reassign_fields(vf->frame_pointer(), ®_map, objects, realloc_failuresfalse);
              realloc_called = true;
            }

            GrowableArray<ScopeValue*>* local_values = scope->locals();
            for (int i = 0; i < local_values->length(); i++) {
              ScopeValue* value = local_values->at(i);
              if (value->is_object()) {
                if (localIsVirtual_h.is_null()) {
                  typeArrayOop array_oop = oopFactory::new_boolArray(local_values->length(), CHECK_NULL);
                  localIsVirtual_h = typeArrayHandle(THREAD, array_oop);
                }
                localIsVirtual_h->bool_at_put(i, true);
              }
            }
          }

          locals = cvf->locals();
          frame_number = cvf->vframe_id();
        } else {
          // interpreted method frame
          interpretedVFrame* ivf = interpretedVFrame::cast(vf);

          locals = ivf->locals();
        }
        assert(bci == vf->bci(), "wrong bci");
        assert(method == vf->method(), "wrong method");

        Handle frame_reference = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
        HotSpotJVMCI::HotSpotStackFrameReference::set_bci(JVMCIENV, frame_reference(), bci);
        if (matched_jvmci_method.is_null()) {
          methodHandle mh(THREAD, method);
          JVMCIObject jvmci_method = JVMCIENV->get_jvmci_method(mh, JVMCI_CHECK_NULL);
          matched_jvmci_method = Handle(THREAD, JNIHandles::resolve(jvmci_method.as_jobject()));
        }
        HotSpotJVMCI::HotSpotStackFrameReference::set_method(JVMCIENV, frame_reference(), matched_jvmci_method());
        HotSpotJVMCI::HotSpotStackFrameReference::set_localIsVirtual(JVMCIENV, frame_reference(), localIsVirtual_h());

        HotSpotJVMCI::HotSpotStackFrameReference::set_compilerToVM(JVMCIENV, frame_reference(), JNIHandles::resolve(compilerToVM));
        HotSpotJVMCI::HotSpotStackFrameReference::set_stackPointer(JVMCIENV, frame_reference(), (jlong) frame_id);
        HotSpotJVMCI::HotSpotStackFrameReference::set_frameNumber(JVMCIENV, frame_reference(), frame_number);

        // initialize the locals array
        objArrayOop array_oop = oopFactory::new_objectArray(locals->size(), CHECK_NULL);
        objArrayHandle array(THREAD, array_oop);
        for (int i = 0; i < locals->size(); i++) {
          StackValue* var = locals->at(i);
          if (var->type() == T_OBJECT) {
            array->obj_at_put(i, locals->at(i)->get_obj()());
          }
        }
        HotSpotJVMCI::HotSpotStackFrameReference::set_locals(JVMCIENV, frame_reference(), array());
        HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, frame_reference(), JNI_FALSE);

        JavaValue result(T_OBJECT);
        JavaCallArguments args(visitor);
        if (visitor_method.is_null()) {
          visitor_method = resolve_interface_call(HotSpotJVMCI::InspectedFrameVisitor::klass(), vmSymbols::visitFrame_name(), vmSymbols::visitFrame_signature(), &args, CHECK_NULL);
        }

        args.push_oop(frame_reference);
        JavaCalls::call(&result, visitor_method, &args, CHECK_NULL);
        if (result.get_oop() != NULL) {
          return JNIHandles::make_local(thread, result.get_oop());
        }
        if (methods == initial_methods) {
          methods = match_methods;
          if (resolved_methods != NULL && JNIHandles::resolve(match_methods) != JNIHandles::resolve(initial_methods)) {
            resolved_methods = NULL;
          }
        }
        assert(initialSkip == 0, "There should be no match before initialSkip == 0");
        if (HotSpotJVMCI::HotSpotStackFrameReference::objectsMaterialized(JVMCIENV, frame_reference()) == JNI_TRUE) {
          // the frame has been deoptimized, we need to re-synchronize the frame and vframe
          prev_cvf = NULL;
          intptr_t* stack_pointer = (intptr_t*) HotSpotJVMCI::HotSpotStackFrameReference::stackPointer(JVMCIENV, frame_reference());
          resync_vframestream_to_compiled_frame(vfst, stack_pointer, frame_number, thread, CHECK_NULL);
        }
      }
    } // end of vframe loop
  } // end of frame loop

  // the end was reached without finding a matching method
  return NULL;
C2V_END

C2V_VMENTRY(void, resolveInvokeDynamicInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  CallInfo callInfo;
  LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, Bytecodes::_invokedynamic, CHECK);
  ConstantPoolCacheEntry* cp_cache_entry = cp->invokedynamic_cp_cache_entry_at(index);
  cp_cache_entry->set_dynamic_call(cp, callInfo);
C2V_END

C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  Klass* holder = cp->klass_ref_at(index, CHECK);
  Symbol* name = cp->name_ref_at(index);
  if (MethodHandles::is_signature_polymorphic_name(holder, name)) {
    CallInfo callInfo;
    LinkResolver::resolve_invoke(callInfo, Handle(), cp, index, Bytecodes::_invokehandle, CHECK);
    ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
    cp_cache_entry->set_method_handle(cp, callInfo);
  }
C2V_END

C2V_VMENTRY_0(jint, isResolvedInvokeHandleInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
  constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
  ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
  if (cp_cache_entry->is_resolved(Bytecodes::_invokehandle)) {
    // MethodHandle.invoke* --> LambdaForm?
    ResourceMark rm;

    LinkInfo link_info(cp, index, CATCH);

    Klass* resolved_klass = link_info.resolved_klass();

    Symbol* name_sym = cp->name_ref_at(index);

    vmassert(MethodHandles::is_method_handle_invoke_name(resolved_klass, name_sym), "!");
    vmassert(MethodHandles::is_signature_polymorphic_name(resolved_klass, name_sym), "!");

    methodHandle adapter_method(THREAD, cp_cache_entry->f1_as_method());

    methodHandle resolved_method(adapter_method);

    // Can we treat it as a regular invokevirtual?
    if (resolved_method->method_holder() == resolved_klass && resolved_method->name() == name_sym) {
      vmassert(!resolved_method->is_static(),"!");
      vmassert(MethodHandles::is_signature_polymorphic_method(resolved_method()),"!");
      vmassert(!MethodHandles::is_signature_polymorphic_static(resolved_method->intrinsic_id()), "!");
      vmassert(cp_cache_entry->appendix_if_resolved(cp) == NULL, "!");

      methodHandle m(THREAD, LinkResolver::linktime_resolve_virtual_method_or_null(link_info));
      vmassert(m == resolved_method, "!!");
      return -1;
    }

    return Bytecodes::_invokevirtual;
  }
  if (cp_cache_entry->is_resolved(Bytecodes::_invokedynamic)) {
    return Bytecodes::_invokedynamic;
  }
  return -1;
C2V_END


C2V_VMENTRY_NULL(jobject, getSignaturePolymorphicHolders, (JNIEnv* env, jobject))
  JVMCIObjectArray holders = JVMCIENV->new_String_array(2, JVMCI_CHECK_NULL);
  JVMCIObject mh = JVMCIENV->create_string("Ljava/lang/invoke/MethodHandle;", JVMCI_CHECK_NULL);
  JVMCIObject vh = JVMCIENV->create_string("Ljava/lang/invoke/VarHandle;", JVMCI_CHECK_NULL);
  JVMCIENV->put_object_at(holders, 0, mh);
  JVMCIENV->put_object_at(holders, 1, vh);
--> --------------------

--> maximum size reached

--> --------------------

92%


¤ Dauer der Verarbeitung: 0.31 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge