/* * 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.
*/
// 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)
// 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)
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();
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;
}
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);
} elseif (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());
}
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);
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);
} elseif (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, 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
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()) { returnfalse;
}
InstanceKlass* iklass = InstanceKlass::cast(klass); return Dependencies::find_finalizable_subclass(iklass) != nullptr;
C2V_END
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
// 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);
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);
if (jap.return_type() == T_VOID) { return NULL;
} elseif (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;
}
/* * 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)); returntrue;
}
} returnfalse;
}
/* * 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;
}
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());
}
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
// 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, "!");
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.