src/share/vm/interpreter/linkResolver.cpp

Tue, 07 Aug 2012 14:32:08 -0700

author
twisti
date
Tue, 07 Aug 2012 14:32:08 -0700
changeset 3974
93c71eb28866
parent 3969
1d7922586cf6
child 4037
da91efe96a93
permissions
-rw-r--r--

7188911: nightly failures after JSR 292 lazy method handle update (round 2)
Reviewed-by: kvn, jrose

duke@435 1 /*
jrose@2638 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "classfile/systemDictionary.hpp"
stefank@2314 27 #include "classfile/vmSymbols.hpp"
stefank@2314 28 #include "compiler/compileBroker.hpp"
stefank@2314 29 #include "gc_interface/collectedHeap.inline.hpp"
stefank@2314 30 #include "interpreter/bytecode.hpp"
stefank@2314 31 #include "interpreter/interpreterRuntime.hpp"
stefank@2314 32 #include "interpreter/linkResolver.hpp"
stefank@2314 33 #include "memory/resourceArea.hpp"
stefank@2314 34 #include "memory/universe.inline.hpp"
stefank@2314 35 #include "oops/instanceKlass.hpp"
stefank@2314 36 #include "oops/objArrayOop.hpp"
stefank@2314 37 #include "prims/methodHandles.hpp"
stefank@2314 38 #include "prims/nativeLookup.hpp"
stefank@2314 39 #include "runtime/compilationPolicy.hpp"
stefank@2314 40 #include "runtime/fieldDescriptor.hpp"
stefank@2314 41 #include "runtime/frame.inline.hpp"
stefank@2314 42 #include "runtime/handles.inline.hpp"
stefank@2314 43 #include "runtime/reflection.hpp"
stefank@2314 44 #include "runtime/signature.hpp"
stefank@2314 45 #include "runtime/vmThread.hpp"
stefank@2314 46 #ifdef TARGET_OS_FAMILY_linux
stefank@2314 47 # include "thread_linux.inline.hpp"
stefank@2314 48 #endif
stefank@2314 49 #ifdef TARGET_OS_FAMILY_solaris
stefank@2314 50 # include "thread_solaris.inline.hpp"
stefank@2314 51 #endif
stefank@2314 52 #ifdef TARGET_OS_FAMILY_windows
stefank@2314 53 # include "thread_windows.inline.hpp"
stefank@2314 54 #endif
never@3156 55 #ifdef TARGET_OS_FAMILY_bsd
never@3156 56 # include "thread_bsd.inline.hpp"
never@3156 57 #endif
duke@435 58
duke@435 59 //------------------------------------------------------------------------------------------------------------------------
duke@435 60 // Implementation of FieldAccessInfo
duke@435 61
coleenp@2497 62 void FieldAccessInfo::set(KlassHandle klass, Symbol* name, int field_index, int field_offset,
duke@435 63 BasicType field_type, AccessFlags access_flags) {
duke@435 64 _klass = klass;
duke@435 65 _name = name;
duke@435 66 _field_index = field_index;
duke@435 67 _field_offset = field_offset;
duke@435 68 _field_type = field_type;
duke@435 69 _access_flags = access_flags;
duke@435 70 }
duke@435 71
duke@435 72
duke@435 73 //------------------------------------------------------------------------------------------------------------------------
duke@435 74 // Implementation of CallInfo
duke@435 75
duke@435 76
duke@435 77 void CallInfo::set_static(KlassHandle resolved_klass, methodHandle resolved_method, TRAPS) {
duke@435 78 int vtable_index = methodOopDesc::nonvirtual_vtable_index;
duke@435 79 set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, vtable_index, CHECK);
duke@435 80 }
duke@435 81
duke@435 82
duke@435 83 void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, TRAPS) {
duke@435 84 // This is only called for interface methods. If the resolved_method
duke@435 85 // comes from java/lang/Object, it can be the subject of a virtual call, so
duke@435 86 // we should pick the vtable index from the resolved method.
duke@435 87 // Other than that case, there is no valid vtable index to specify.
duke@435 88 int vtable_index = methodOopDesc::invalid_vtable_index;
never@1577 89 if (resolved_method->method_holder() == SystemDictionary::Object_klass()) {
duke@435 90 assert(resolved_method->vtable_index() == selected_method->vtable_index(), "sanity check");
duke@435 91 vtable_index = resolved_method->vtable_index();
duke@435 92 }
duke@435 93 set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK);
duke@435 94 }
duke@435 95
duke@435 96 void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) {
duke@435 97 assert(vtable_index >= 0 || vtable_index == methodOopDesc::nonvirtual_vtable_index, "valid index");
duke@435 98 set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK);
twisti@3969 99 assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call");
duke@435 100 }
duke@435 101
twisti@3969 102 void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix, TRAPS) {
twisti@3969 103 if (resolved_method.is_null()) {
twisti@3969 104 THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null");
twisti@3969 105 }
jrose@2015 106 KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
twisti@3969 107 assert(resolved_method->intrinsic_id() == vmIntrinsics::_invokeBasic ||
twisti@3969 108 resolved_method->is_compiled_lambda_form(),
twisti@3969 109 "linkMethod must return one of these");
jrose@2015 110 int vtable_index = methodOopDesc::nonvirtual_vtable_index;
jrose@2015 111 assert(resolved_method->vtable_index() == vtable_index, "");
twisti@3969 112 set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, vtable_index, CHECK);
twisti@3969 113 _resolved_appendix = resolved_appendix;
jrose@2015 114 }
jrose@2015 115
duke@435 116 void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) {
duke@435 117 assert(resolved_method->signature() == selected_method->signature(), "signatures must correspond");
duke@435 118 _resolved_klass = resolved_klass;
duke@435 119 _selected_klass = selected_klass;
duke@435 120 _resolved_method = resolved_method;
duke@435 121 _selected_method = selected_method;
duke@435 122 _vtable_index = vtable_index;
twisti@3969 123 _resolved_appendix = Handle();
iveresov@2138 124 if (CompilationPolicy::must_be_compiled(selected_method)) {
twisti@1570 125 // This path is unusual, mostly used by the '-Xcomp' stress test mode.
twisti@1570 126
iveresov@2138 127 // Note: with several active threads, the must_be_compiled may be true
iveresov@2138 128 // while can_be_compiled is false; remove assert
iveresov@2138 129 // assert(CompilationPolicy::can_be_compiled(selected_method), "cannot compile");
duke@435 130 if (THREAD->is_Compiler_thread()) {
duke@435 131 // don't force compilation, resolve was on behalf of compiler
duke@435 132 return;
duke@435 133 }
twisti@1570 134 if (instanceKlass::cast(selected_method->method_holder())->is_not_initialized()) {
twisti@1570 135 // 'is_not_initialized' means not only '!is_initialized', but also that
twisti@1570 136 // initialization has not been started yet ('!being_initialized')
twisti@1570 137 // Do not force compilation of methods in uninitialized classes.
twisti@1570 138 // Note that doing this would throw an assert later,
twisti@1570 139 // in CompileBroker::compile_method.
twisti@1570 140 // We sometimes use the link resolver to do reflective lookups
twisti@1570 141 // even before classes are initialized.
twisti@1570 142 return;
twisti@1570 143 }
duke@435 144 CompileBroker::compile_method(selected_method, InvocationEntryBci,
iveresov@3035 145 CompilationPolicy::policy()->initial_compile_level(),
iveresov@2138 146 methodHandle(), 0, "must_be_compiled", CHECK);
duke@435 147 }
duke@435 148 }
duke@435 149
duke@435 150
duke@435 151 //------------------------------------------------------------------------------------------------------------------------
duke@435 152 // Klass resolution
duke@435 153
duke@435 154 void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) {
duke@435 155 if (!Reflection::verify_class_access(ref_klass->as_klassOop(),
duke@435 156 sel_klass->as_klassOop(),
duke@435 157 true)) {
duke@435 158 ResourceMark rm(THREAD);
duke@435 159 Exceptions::fthrow(
duke@435 160 THREAD_AND_LOCATION,
coleenp@2497 161 vmSymbols::java_lang_IllegalAccessError(),
duke@435 162 "tried to access class %s from class %s",
duke@435 163 sel_klass->external_name(),
duke@435 164 ref_klass->external_name()
duke@435 165 );
duke@435 166 return;
duke@435 167 }
duke@435 168 }
duke@435 169
duke@435 170 void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, int index, TRAPS) {
duke@435 171 klassOop result_oop = pool->klass_ref_at(index, CHECK);
duke@435 172 result = KlassHandle(THREAD, result_oop);
duke@435 173 }
duke@435 174
duke@435 175 void LinkResolver::resolve_klass_no_update(KlassHandle& result, constantPoolHandle pool, int index, TRAPS) {
duke@435 176 klassOop result_oop =
duke@435 177 constantPoolOopDesc::klass_ref_at_if_loaded_check(pool, index, CHECK);
duke@435 178 result = KlassHandle(THREAD, result_oop);
duke@435 179 }
duke@435 180
duke@435 181
duke@435 182 //------------------------------------------------------------------------------------------------------------------------
duke@435 183 // Method resolution
duke@435 184 //
duke@435 185 // According to JVM spec. $5.4.3c & $5.4.3d
duke@435 186
coleenp@2497 187 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
coleenp@2497 188 methodOop result_oop = klass->uncached_lookup_method(name, signature);
twisti@2698 189 if (EnableInvokeDynamic && result_oop != NULL) {
twisti@3969 190 vmIntrinsics::ID iid = result_oop->intrinsic_id();
twisti@3969 191 if (MethodHandles::is_signature_polymorphic(iid)) {
twisti@3969 192 // Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method.
jrose@1862 193 return;
jrose@1862 194 }
jrose@1862 195 }
duke@435 196 result = methodHandle(THREAD, result_oop);
duke@435 197 }
duke@435 198
duke@435 199 // returns first instance method
coleenp@2497 200 void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
coleenp@2497 201 methodOop result_oop = klass->uncached_lookup_method(name, signature);
duke@435 202 result = methodHandle(THREAD, result_oop);
duke@435 203 while (!result.is_null() && result->is_static()) {
duke@435 204 klass = KlassHandle(THREAD, Klass::cast(result->method_holder())->super());
coleenp@2497 205 result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature));
duke@435 206 }
duke@435 207 }
duke@435 208
duke@435 209
coleenp@2497 210 int LinkResolver::vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
duke@435 211 ResourceMark rm(THREAD);
duke@435 212 klassVtable *vt = instanceKlass::cast(klass())->vtable();
coleenp@2497 213 return vt->index_of_miranda(name, signature);
duke@435 214 }
duke@435 215
coleenp@2497 216 void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
duke@435 217 instanceKlass *ik = instanceKlass::cast(klass());
coleenp@2497 218 result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature));
duke@435 219 }
duke@435 220
twisti@3969 221 void LinkResolver::lookup_polymorphic_method(methodHandle& result,
twisti@3969 222 KlassHandle klass, Symbol* name, Symbol* full_signature,
twisti@3969 223 KlassHandle current_klass,
twisti@3969 224 Handle* appendix_result_or_null,
twisti@3969 225 TRAPS) {
twisti@3969 226 vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name);
twisti@3969 227 if (TraceMethodHandles) {
twisti@3969 228 tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s",
twisti@3969 229 vmIntrinsics::name_at(iid), klass->external_name(),
twisti@3969 230 name->as_C_string(), full_signature->as_C_string());
twisti@3969 231 }
twisti@2698 232 if (EnableInvokeDynamic &&
jrose@1862 233 klass() == SystemDictionary::MethodHandle_klass() &&
twisti@3969 234 iid != vmIntrinsics::_none) {
twisti@3969 235 if (MethodHandles::is_signature_polymorphic_intrinsic(iid)) {
twisti@3969 236 // Most of these do not need an up-call to Java to resolve, so can be done anywhere.
twisti@3969 237 // Do not erase last argument type (MemberName) if it is a static linkTo method.
twisti@3969 238 bool keep_last_arg = MethodHandles::is_signature_polymorphic_static(iid);
twisti@3969 239 TempNewSymbol basic_signature =
twisti@3969 240 MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK);
twisti@3969 241 if (TraceMethodHandles) {
twisti@3969 242 tty->print_cr("lookup_polymorphic_method %s %s => basic %s",
twisti@3969 243 name->as_C_string(),
twisti@3969 244 full_signature->as_C_string(),
twisti@3969 245 basic_signature->as_C_string());
jrose@2015 246 }
twisti@3969 247 result = SystemDictionary::find_method_handle_intrinsic(iid,
twisti@3969 248 basic_signature,
twisti@3969 249 CHECK);
twisti@3969 250 if (result.not_null()) {
twisti@3969 251 assert(result->is_method_handle_intrinsic(), "MH.invokeBasic or MH.linkTo* intrinsic");
twisti@3969 252 assert(result->intrinsic_id() != vmIntrinsics::_invokeGeneric, "wrong place to find this");
twisti@3969 253 assert(basic_signature == result->signature(), "predict the result signature");
twisti@3969 254 if (TraceMethodHandles) {
twisti@3969 255 tty->print("lookup_polymorphic_method => intrinsic ");
twisti@3969 256 result->print_on(tty);
twisti@3969 257 }
twisti@3969 258 return;
twisti@3969 259 }
twisti@3969 260 } else if (iid == vmIntrinsics::_invokeGeneric
twisti@3969 261 && !THREAD->is_Compiler_thread()
twisti@3969 262 && appendix_result_or_null != NULL) {
twisti@3969 263 // This is a method with type-checking semantics.
twisti@3969 264 // We will ask Java code to spin an adapter method for it.
twisti@3969 265 if (!MethodHandles::enabled()) {
twisti@3969 266 // Make sure the Java part of the runtime has been booted up.
twisti@3969 267 klassOop natives = SystemDictionary::MethodHandleNatives_klass();
twisti@3969 268 if (natives == NULL || instanceKlass::cast(natives)->is_not_initialized()) {
twisti@3969 269 SystemDictionary::resolve_or_fail(vmSymbols::java_lang_invoke_MethodHandleNatives(),
twisti@3969 270 Handle(),
twisti@3969 271 Handle(),
twisti@3969 272 true,
twisti@3969 273 CHECK);
twisti@3969 274 }
twisti@3969 275 }
twisti@3969 276
twisti@3969 277 Handle appendix;
twisti@3969 278 result = SystemDictionary::find_method_handle_invoker(name,
twisti@3969 279 full_signature,
twisti@3969 280 current_klass,
twisti@3969 281 &appendix,
twisti@3969 282 CHECK);
twisti@3969 283 if (TraceMethodHandles) {
twisti@3969 284 tty->print("lookup_polymorphic_method => (via Java) ");
twisti@3969 285 result->print_on(tty);
twisti@3969 286 tty->print(" lookup_polymorphic_method => appendix = ");
twisti@3969 287 if (appendix.is_null()) tty->print_cr("(none)");
twisti@3969 288 else appendix->print_on(tty);
twisti@3969 289 }
twisti@3969 290 if (result.not_null()) {
twisti@3969 291 #ifdef ASSERT
twisti@3969 292 TempNewSymbol basic_signature =
twisti@3969 293 MethodHandles::lookup_basic_type_signature(full_signature, CHECK);
twisti@3969 294 int actual_size_of_params = result->size_of_parameters();
twisti@3969 295 int expected_size_of_params = ArgumentSizeComputer(basic_signature).size();
twisti@3969 296 // +1 for MethodHandle.this, +1 for trailing MethodType
twisti@3969 297 if (!MethodHandles::is_signature_polymorphic_static(iid)) expected_size_of_params += 1;
twisti@3969 298 if (appendix.not_null()) expected_size_of_params += 1;
twisti@3969 299 if (actual_size_of_params != expected_size_of_params) {
twisti@3969 300 tty->print_cr("*** basic_signature=%s", basic_signature->as_C_string());
twisti@3969 301 tty->print_cr("*** result for %s: ", vmIntrinsics::name_at(iid));
twisti@3969 302 result->print();
twisti@3969 303 }
twisti@3969 304 assert(actual_size_of_params == expected_size_of_params,
twisti@3969 305 err_msg("%d != %d", actual_size_of_params, expected_size_of_params));
twisti@3969 306 #endif //ASSERT
twisti@3969 307
twisti@3969 308 assert(appendix_result_or_null != NULL, "");
twisti@3969 309 (*appendix_result_or_null) = appendix;
twisti@3969 310 return;
twisti@3969 311 }
jrose@1145 312 }
jrose@1145 313 }
jrose@1145 314 }
jrose@1145 315
duke@435 316 void LinkResolver::check_method_accessability(KlassHandle ref_klass,
duke@435 317 KlassHandle resolved_klass,
duke@435 318 KlassHandle sel_klass,
duke@435 319 methodHandle sel_method,
duke@435 320 TRAPS) {
duke@435 321
duke@435 322 AccessFlags flags = sel_method->access_flags();
duke@435 323
duke@435 324 // Special case: arrays always override "clone". JVMS 2.15.
duke@435 325 // If the resolved klass is an array class, and the declaring class
duke@435 326 // is java.lang.Object and the method is "clone", set the flags
duke@435 327 // to public.
duke@435 328 //
duke@435 329 // We'll check for the method name first, as that's most likely
duke@435 330 // to be false (so we'll short-circuit out of these tests).
duke@435 331 if (sel_method->name() == vmSymbols::clone_name() &&
never@1577 332 sel_klass() == SystemDictionary::Object_klass() &&
duke@435 333 resolved_klass->oop_is_array()) {
duke@435 334 // We need to change "protected" to "public".
duke@435 335 assert(flags.is_protected(), "clone not protected?");
duke@435 336 jint new_flags = flags.as_int();
duke@435 337 new_flags = new_flags & (~JVM_ACC_PROTECTED);
duke@435 338 new_flags = new_flags | JVM_ACC_PUBLIC;
duke@435 339 flags.set_flags(new_flags);
duke@435 340 }
twisti@3969 341 // assert(extra_arg_result_or_null != NULL, "must be able to return extra argument");
duke@435 342
duke@435 343 if (!Reflection::verify_field_access(ref_klass->as_klassOop(),
duke@435 344 resolved_klass->as_klassOop(),
duke@435 345 sel_klass->as_klassOop(),
duke@435 346 flags,
duke@435 347 true)) {
duke@435 348 ResourceMark rm(THREAD);
duke@435 349 Exceptions::fthrow(
duke@435 350 THREAD_AND_LOCATION,
coleenp@2497 351 vmSymbols::java_lang_IllegalAccessError(),
duke@435 352 "tried to access method %s.%s%s from class %s",
duke@435 353 sel_klass->external_name(),
duke@435 354 sel_method->name()->as_C_string(),
duke@435 355 sel_method->signature()->as_C_string(),
duke@435 356 ref_klass->external_name()
duke@435 357 );
duke@435 358 return;
duke@435 359 }
duke@435 360 }
duke@435 361
twisti@3969 362 void LinkResolver::resolve_method_statically(methodHandle& resolved_method, KlassHandle& resolved_klass,
twisti@3969 363 Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS) {
duke@435 364
duke@435 365 // resolve klass
twisti@3969 366 if (code == Bytecodes::_invokedynamic) {
twisti@3969 367 resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
twisti@3969 368 Symbol* method_name = vmSymbols::invoke_name();
twisti@3969 369 Symbol* method_signature = pool->signature_ref_at(index);
twisti@3969 370 KlassHandle current_klass(THREAD, pool->pool_holder());
twisti@3969 371 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
twisti@3969 372 return;
twisti@3969 373 }
twisti@3969 374
duke@435 375 resolve_klass(resolved_klass, pool, index, CHECK);
duke@435 376
coleenp@2497 377 Symbol* method_name = pool->name_ref_at(index);
coleenp@2497 378 Symbol* method_signature = pool->signature_ref_at(index);
duke@435 379 KlassHandle current_klass(THREAD, pool->pool_holder());
duke@435 380
jrose@2982 381 if (pool->has_preresolution()
jrose@2982 382 || (resolved_klass() == SystemDictionary::MethodHandle_klass() &&
twisti@3969 383 MethodHandles::is_signature_polymorphic_name(resolved_klass(), method_name))) {
jrose@2982 384 methodOop result_oop = constantPoolOopDesc::method_at_if_loaded(pool, index);
jrose@2982 385 if (result_oop != NULL) {
jrose@2982 386 resolved_method = methodHandle(THREAD, result_oop);
jrose@2982 387 return;
jrose@2982 388 }
jrose@2982 389 }
jrose@2982 390
twisti@3969 391 if (code == Bytecodes::_invokeinterface) {
twisti@3969 392 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
twisti@3969 393 } else {
twisti@3969 394 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
twisti@3969 395 }
duke@435 396 }
duke@435 397
duke@435 398 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass,
coleenp@2497 399 Symbol* method_name, Symbol* method_signature,
duke@435 400 KlassHandle current_klass, bool check_access, TRAPS) {
duke@435 401
duke@435 402 // 1. check if klass is not interface
duke@435 403 if (resolved_klass->is_interface()) {
jcoomes@2856 404 ResourceMark rm(THREAD);
duke@435 405 char buf[200];
duke@435 406 jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name());
duke@435 407 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
duke@435 408 }
duke@435 409
twisti@3969 410 Handle nested_exception;
twisti@3969 411
duke@435 412 // 2. lookup method in resolved klass and its super klasses
duke@435 413 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
duke@435 414
duke@435 415 if (resolved_method.is_null()) { // not found in the class hierarchy
duke@435 416 // 3. lookup method in all the interfaces implemented by the resolved klass
duke@435 417 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
duke@435 418
duke@435 419 if (resolved_method.is_null()) {
twisti@3969 420 // JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc
twisti@3969 421 lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature,
twisti@3969 422 current_klass, (Handle*)NULL, THREAD);
twisti@3969 423 if (HAS_PENDING_EXCEPTION) {
twisti@3969 424 nested_exception = Handle(THREAD, PENDING_EXCEPTION);
twisti@3969 425 CLEAR_PENDING_EXCEPTION;
twisti@3969 426 }
jrose@1145 427 }
jrose@1145 428
jrose@1145 429 if (resolved_method.is_null()) {
duke@435 430 // 4. method lookup failed
duke@435 431 ResourceMark rm(THREAD);
twisti@3969 432 THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(),
twisti@3969 433 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
twisti@3969 434 method_name,
twisti@3969 435 method_signature),
twisti@3969 436 nested_exception);
duke@435 437 }
duke@435 438 }
duke@435 439
duke@435 440 // 5. check if method is concrete
duke@435 441 if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) {
duke@435 442 ResourceMark rm(THREAD);
duke@435 443 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
duke@435 444 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
coleenp@2497 445 method_name,
coleenp@2497 446 method_signature));
duke@435 447 }
duke@435 448
duke@435 449 // 6. access checks, access checking may be turned off when calling from within the VM.
duke@435 450 if (check_access) {
duke@435 451 assert(current_klass.not_null() , "current_klass should not be null");
duke@435 452
duke@435 453 // check if method can be accessed by the referring class
duke@435 454 check_method_accessability(current_klass,
duke@435 455 resolved_klass,
duke@435 456 KlassHandle(THREAD, resolved_method->method_holder()),
duke@435 457 resolved_method,
duke@435 458 CHECK);
duke@435 459
duke@435 460 // check loader constraints
duke@435 461 Handle loader (THREAD, instanceKlass::cast(current_klass())->class_loader());
duke@435 462 Handle class_loader (THREAD, instanceKlass::cast(resolved_method->method_holder())->class_loader());
duke@435 463 {
duke@435 464 ResourceMark rm(THREAD);
duke@435 465 char* failed_type_name =
duke@435 466 SystemDictionary::check_signature_loaders(method_signature, loader,
duke@435 467 class_loader, true, CHECK);
duke@435 468 if (failed_type_name != NULL) {
duke@435 469 const char* msg = "loader constraint violation: when resolving method"
duke@435 470 " \"%s\" the class loader (instance of %s) of the current class, %s,"
duke@435 471 " and the class loader (instance of %s) for resolved class, %s, have"
duke@435 472 " different Class objects for the type %s used in the signature";
coleenp@2497 473 char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature);
duke@435 474 const char* loader1 = SystemDictionary::loader_name(loader());
duke@435 475 char* current = instanceKlass::cast(current_klass())->name()->as_C_string();
duke@435 476 const char* loader2 = SystemDictionary::loader_name(class_loader());
duke@435 477 char* resolved = instanceKlass::cast(resolved_klass())->name()->as_C_string();
duke@435 478 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
duke@435 479 strlen(current) + strlen(loader2) + strlen(resolved) +
duke@435 480 strlen(failed_type_name);
duke@435 481 char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
duke@435 482 jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
duke@435 483 resolved, failed_type_name);
duke@435 484 THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
duke@435 485 }
duke@435 486 }
duke@435 487 }
duke@435 488 }
duke@435 489
duke@435 490 void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
duke@435 491 KlassHandle resolved_klass,
coleenp@2497 492 Symbol* method_name,
coleenp@2497 493 Symbol* method_signature,
duke@435 494 KlassHandle current_klass,
duke@435 495 bool check_access, TRAPS) {
duke@435 496
duke@435 497 // check if klass is interface
duke@435 498 if (!resolved_klass->is_interface()) {
jcoomes@2856 499 ResourceMark rm(THREAD);
duke@435 500 char buf[200];
duke@435 501 jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", Klass::cast(resolved_klass())->external_name());
duke@435 502 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
duke@435 503 }
duke@435 504
duke@435 505 // lookup method in this interface or its super, java.lang.Object
duke@435 506 lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
duke@435 507
duke@435 508 if (resolved_method.is_null()) {
duke@435 509 // lookup method in all the super-interfaces
duke@435 510 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
duke@435 511 if (resolved_method.is_null()) {
duke@435 512 // no method found
duke@435 513 ResourceMark rm(THREAD);
duke@435 514 THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
duke@435 515 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
coleenp@2497 516 method_name,
coleenp@2497 517 method_signature));
duke@435 518 }
duke@435 519 }
duke@435 520
duke@435 521 if (check_access) {
duke@435 522 HandleMark hm(THREAD);
duke@435 523 Handle loader (THREAD, instanceKlass::cast(current_klass())->class_loader());
duke@435 524 Handle class_loader (THREAD, instanceKlass::cast(resolved_method->method_holder())->class_loader());
duke@435 525 {
duke@435 526 ResourceMark rm(THREAD);
duke@435 527 char* failed_type_name =
duke@435 528 SystemDictionary::check_signature_loaders(method_signature, loader,
duke@435 529 class_loader, true, CHECK);
duke@435 530 if (failed_type_name != NULL) {
duke@435 531 const char* msg = "loader constraint violation: when resolving "
duke@435 532 "interface method \"%s\" the class loader (instance of %s) of the "
duke@435 533 "current class, %s, and the class loader (instance of %s) for "
duke@435 534 "resolved class, %s, have different Class objects for the type %s "
duke@435 535 "used in the signature";
coleenp@2497 536 char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature);
duke@435 537 const char* loader1 = SystemDictionary::loader_name(loader());
duke@435 538 char* current = instanceKlass::cast(current_klass())->name()->as_C_string();
duke@435 539 const char* loader2 = SystemDictionary::loader_name(class_loader());
duke@435 540 char* resolved = instanceKlass::cast(resolved_klass())->name()->as_C_string();
duke@435 541 size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
duke@435 542 strlen(current) + strlen(loader2) + strlen(resolved) +
duke@435 543 strlen(failed_type_name);
duke@435 544 char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
duke@435 545 jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
duke@435 546 resolved, failed_type_name);
duke@435 547 THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
duke@435 548 }
duke@435 549 }
duke@435 550 }
duke@435 551 }
duke@435 552
duke@435 553 //------------------------------------------------------------------------------------------------------------------------
duke@435 554 // Field resolution
duke@435 555
duke@435 556 void LinkResolver::check_field_accessability(KlassHandle ref_klass,
duke@435 557 KlassHandle resolved_klass,
duke@435 558 KlassHandle sel_klass,
duke@435 559 fieldDescriptor& fd,
duke@435 560 TRAPS) {
duke@435 561 if (!Reflection::verify_field_access(ref_klass->as_klassOop(),
duke@435 562 resolved_klass->as_klassOop(),
duke@435 563 sel_klass->as_klassOop(),
duke@435 564 fd.access_flags(),
duke@435 565 true)) {
duke@435 566 ResourceMark rm(THREAD);
duke@435 567 Exceptions::fthrow(
duke@435 568 THREAD_AND_LOCATION,
coleenp@2497 569 vmSymbols::java_lang_IllegalAccessError(),
duke@435 570 "tried to access field %s.%s from class %s",
duke@435 571 sel_klass->external_name(),
duke@435 572 fd.name()->as_C_string(),
duke@435 573 ref_klass->external_name()
duke@435 574 );
duke@435 575 return;
duke@435 576 }
duke@435 577 }
duke@435 578
duke@435 579 void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, TRAPS) {
duke@435 580 resolve_field(result, pool, index, byte, check_only, true, CHECK);
duke@435 581 }
duke@435 582
duke@435 583 void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, bool update_pool, TRAPS) {
duke@435 584 assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
duke@435 585 byte == Bytecodes::_getfield || byte == Bytecodes::_putfield, "bad bytecode");
duke@435 586
duke@435 587 bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
duke@435 588 bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic);
duke@435 589
duke@435 590 // resolve specified klass
duke@435 591 KlassHandle resolved_klass;
duke@435 592 if (update_pool) {
duke@435 593 resolve_klass(resolved_klass, pool, index, CHECK);
duke@435 594 } else {
duke@435 595 resolve_klass_no_update(resolved_klass, pool, index, CHECK);
duke@435 596 }
duke@435 597 // Load these early in case the resolve of the containing klass fails
coleenp@2497 598 Symbol* field = pool->name_ref_at(index);
coleenp@2497 599 Symbol* sig = pool->signature_ref_at(index);
duke@435 600 // Check if there's a resolved klass containing the field
duke@435 601 if( resolved_klass.is_null() ) {
duke@435 602 ResourceMark rm(THREAD);
duke@435 603 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
duke@435 604 }
duke@435 605
duke@435 606 // Resolve instance field
duke@435 607 fieldDescriptor fd; // find_field initializes fd if found
duke@435 608 KlassHandle sel_klass(THREAD, instanceKlass::cast(resolved_klass())->find_field(field, sig, &fd));
duke@435 609 // check if field exists; i.e., if a klass containing the field def has been selected
duke@435 610 if (sel_klass.is_null()){
duke@435 611 ResourceMark rm(THREAD);
duke@435 612 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
duke@435 613 }
duke@435 614
duke@435 615 // check access
duke@435 616 KlassHandle ref_klass(THREAD, pool->pool_holder());
duke@435 617 check_field_accessability(ref_klass, resolved_klass, sel_klass, fd, CHECK);
duke@435 618
duke@435 619 // check for errors
duke@435 620 if (is_static != fd.is_static()) {
jcoomes@2856 621 ResourceMark rm(THREAD);
duke@435 622 char msg[200];
duke@435 623 jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", Klass::cast(resolved_klass())->external_name(), fd.name()->as_C_string());
duke@435 624 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg);
duke@435 625 }
duke@435 626
duke@435 627 // Final fields can only be accessed from its own class.
duke@435 628 if (is_put && fd.access_flags().is_final() && sel_klass() != pool->pool_holder()) {
duke@435 629 THROW(vmSymbols::java_lang_IllegalAccessError());
duke@435 630 }
duke@435 631
duke@435 632 // initialize resolved_klass if necessary
duke@435 633 // note 1: the klass which declared the field must be initialized (i.e, sel_klass)
duke@435 634 // according to the newest JVM spec (5.5, p.170) - was bug (gri 7/28/99)
duke@435 635 //
duke@435 636 // note 2: we don't want to force initialization if we are just checking
duke@435 637 // if the field access is legal; e.g., during compilation
duke@435 638 if (is_static && !check_only) {
duke@435 639 sel_klass->initialize(CHECK);
duke@435 640 }
duke@435 641
duke@435 642 {
duke@435 643 HandleMark hm(THREAD);
duke@435 644 Handle ref_loader (THREAD, instanceKlass::cast(ref_klass())->class_loader());
duke@435 645 Handle sel_loader (THREAD, instanceKlass::cast(sel_klass())->class_loader());
coleenp@2497 646 Symbol* signature_ref = pool->signature_ref_at(index);
duke@435 647 {
duke@435 648 ResourceMark rm(THREAD);
duke@435 649 char* failed_type_name =
duke@435 650 SystemDictionary::check_signature_loaders(signature_ref,
duke@435 651 ref_loader, sel_loader,
duke@435 652 false,
duke@435 653 CHECK);
duke@435 654 if (failed_type_name != NULL) {
duke@435 655 const char* msg = "loader constraint violation: when resolving field"
duke@435 656 " \"%s\" the class loader (instance of %s) of the referring class, "
duke@435 657 "%s, and the class loader (instance of %s) for the field's resolved "
duke@435 658 "type, %s, have different Class objects for that type";
coleenp@2497 659 char* field_name = field->as_C_string();
duke@435 660 const char* loader1 = SystemDictionary::loader_name(ref_loader());
duke@435 661 char* sel = instanceKlass::cast(sel_klass())->name()->as_C_string();
duke@435 662 const char* loader2 = SystemDictionary::loader_name(sel_loader());
duke@435 663 size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1) +
duke@435 664 strlen(sel) + strlen(loader2) + strlen(failed_type_name);
duke@435 665 char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
duke@435 666 jio_snprintf(buf, buflen, msg, field_name, loader1, sel, loader2,
duke@435 667 failed_type_name);
duke@435 668 THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
duke@435 669 }
duke@435 670 }
duke@435 671 }
duke@435 672
duke@435 673 // return information. note that the klass is set to the actual klass containing the
duke@435 674 // field, otherwise access of static fields in superclasses will not work.
duke@435 675 KlassHandle holder (THREAD, fd.field_holder());
coleenp@2497 676 Symbol* name = fd.name();
duke@435 677 result.set(holder, name, fd.index(), fd.offset(), fd.field_type(), fd.access_flags());
duke@435 678 }
duke@435 679
duke@435 680
duke@435 681 //------------------------------------------------------------------------------------------------------------------------
duke@435 682 // Invoke resolution
duke@435 683 //
duke@435 684 // Naming conventions:
duke@435 685 //
duke@435 686 // resolved_method the specified method (i.e., static receiver specified via constant pool index)
duke@435 687 // sel_method the selected method (selected via run-time lookup; e.g., based on dynamic receiver class)
duke@435 688 // resolved_klass the specified klass (i.e., specified via constant pool index)
duke@435 689 // recv_klass the receiver klass
duke@435 690
duke@435 691
coleenp@2497 692 void LinkResolver::resolve_static_call(CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name,
coleenp@2497 693 Symbol* method_signature, KlassHandle current_klass,
duke@435 694 bool check_access, bool initialize_class, TRAPS) {
duke@435 695 methodHandle resolved_method;
duke@435 696 linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
duke@435 697 resolved_klass = KlassHandle(THREAD, Klass::cast(resolved_method->method_holder()));
duke@435 698
duke@435 699 // Initialize klass (this should only happen if everything is ok)
duke@435 700 if (initialize_class && resolved_klass->should_be_initialized()) {
duke@435 701 resolved_klass->initialize(CHECK);
duke@435 702 linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
duke@435 703 }
duke@435 704
duke@435 705 // setup result
duke@435 706 result.set_static(resolved_klass, resolved_method, CHECK);
duke@435 707 }
duke@435 708
duke@435 709 // throws linktime exceptions
duke@435 710 void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, KlassHandle resolved_klass,
coleenp@2497 711 Symbol* method_name, Symbol* method_signature,
duke@435 712 KlassHandle current_klass, bool check_access, TRAPS) {
duke@435 713
duke@435 714 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
duke@435 715 assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier");
duke@435 716
duke@435 717 // check if static
duke@435 718 if (!resolved_method->is_static()) {
jcoomes@2856 719 ResourceMark rm(THREAD);
duke@435 720 char buf[200];
duke@435 721 jio_snprintf(buf, sizeof(buf), "Expected static method %s", methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
duke@435 722 resolved_method->name(),
duke@435 723 resolved_method->signature()));
duke@435 724 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
duke@435 725 }
duke@435 726 }
duke@435 727
duke@435 728
coleenp@2497 729 void LinkResolver::resolve_special_call(CallInfo& result, KlassHandle resolved_klass, Symbol* method_name,
coleenp@2497 730 Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
duke@435 731 methodHandle resolved_method;
duke@435 732 linktime_resolve_special_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
duke@435 733 runtime_resolve_special_method(result, resolved_method, resolved_klass, current_klass, check_access, CHECK);
duke@435 734 }
duke@435 735
duke@435 736 // throws linktime exceptions
duke@435 737 void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass,
coleenp@2497 738 Symbol* method_name, Symbol* method_signature,
duke@435 739 KlassHandle current_klass, bool check_access, TRAPS) {
duke@435 740
duke@435 741 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
duke@435 742
duke@435 743 // check if method name is <init>, that it is found in same klass as static type
duke@435 744 if (resolved_method->name() == vmSymbols::object_initializer_name() &&
duke@435 745 resolved_method->method_holder() != resolved_klass()) {
duke@435 746 ResourceMark rm(THREAD);
duke@435 747 Exceptions::fthrow(
duke@435 748 THREAD_AND_LOCATION,
coleenp@2497 749 vmSymbols::java_lang_NoSuchMethodError(),
duke@435 750 "%s: method %s%s not found",
duke@435 751 resolved_klass->external_name(),
duke@435 752 resolved_method->name()->as_C_string(),
duke@435 753 resolved_method->signature()->as_C_string()
duke@435 754 );
duke@435 755 return;
duke@435 756 }
duke@435 757
duke@435 758 // check if not static
duke@435 759 if (resolved_method->is_static()) {
jcoomes@2856 760 ResourceMark rm(THREAD);
duke@435 761 char buf[200];
duke@435 762 jio_snprintf(buf, sizeof(buf),
duke@435 763 "Expecting non-static method %s",
duke@435 764 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
duke@435 765 resolved_method->name(),
duke@435 766 resolved_method->signature()));
duke@435 767 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
duke@435 768 }
duke@435 769 }
duke@435 770
duke@435 771 // throws runtime exceptions
duke@435 772 void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass,
duke@435 773 KlassHandle current_klass, bool check_access, TRAPS) {
duke@435 774
duke@435 775 // resolved method is selected method unless we have an old-style lookup
duke@435 776 methodHandle sel_method(THREAD, resolved_method());
duke@435 777
duke@435 778 // check if this is an old-style super call and do a new lookup if so
duke@435 779 { KlassHandle method_klass = KlassHandle(THREAD,
duke@435 780 resolved_method->method_holder());
duke@435 781
duke@435 782 if (check_access &&
duke@435 783 // a) check if ACC_SUPER flag is set for the current class
duke@435 784 current_klass->is_super() &&
duke@435 785 // b) check if the method class is a superclass of the current class (superclass relation is not reflexive!)
duke@435 786 current_klass->is_subtype_of(method_klass()) && current_klass() != method_klass() &&
duke@435 787 // c) check if the method is not <init>
duke@435 788 resolved_method->name() != vmSymbols::object_initializer_name()) {
duke@435 789 // Lookup super method
duke@435 790 KlassHandle super_klass(THREAD, current_klass->super());
duke@435 791 lookup_instance_method_in_klasses(sel_method, super_klass,
coleenp@2497 792 resolved_method->name(),
coleenp@2497 793 resolved_method->signature(), CHECK);
duke@435 794 // check if found
duke@435 795 if (sel_method.is_null()) {
duke@435 796 ResourceMark rm(THREAD);
duke@435 797 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
duke@435 798 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
duke@435 799 resolved_method->name(),
duke@435 800 resolved_method->signature()));
duke@435 801 }
duke@435 802 }
duke@435 803 }
duke@435 804
duke@435 805 // check if not static
duke@435 806 if (sel_method->is_static()) {
jcoomes@2856 807 ResourceMark rm(THREAD);
duke@435 808 char buf[200];
duke@435 809 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
duke@435 810 resolved_method->name(),
duke@435 811 resolved_method->signature()));
duke@435 812 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
duke@435 813 }
duke@435 814
duke@435 815 // check if abstract
duke@435 816 if (sel_method->is_abstract()) {
duke@435 817 ResourceMark rm(THREAD);
duke@435 818 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
duke@435 819 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
duke@435 820 sel_method->name(),
duke@435 821 sel_method->signature()));
duke@435 822 }
duke@435 823
duke@435 824 // setup result
duke@435 825 result.set_static(resolved_klass, sel_method, CHECK);
duke@435 826 }
duke@435 827
duke@435 828 void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, KlassHandle resolved_klass,
coleenp@2497 829 Symbol* method_name, Symbol* method_signature, KlassHandle current_klass,
duke@435 830 bool check_access, bool check_null_and_abstract, TRAPS) {
duke@435 831 methodHandle resolved_method;
duke@435 832 linktime_resolve_virtual_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
duke@435 833 runtime_resolve_virtual_method(result, resolved_method, resolved_klass, recv, receiver_klass, check_null_and_abstract, CHECK);
duke@435 834 }
duke@435 835
duke@435 836 // throws linktime exceptions
duke@435 837 void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method, KlassHandle resolved_klass,
coleenp@2497 838 Symbol* method_name, Symbol* method_signature,
duke@435 839 KlassHandle current_klass, bool check_access, TRAPS) {
duke@435 840 // normal method resolution
duke@435 841 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
duke@435 842
duke@435 843 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier");
duke@435 844 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier");
duke@435 845
duke@435 846 // check if not static
duke@435 847 if (resolved_method->is_static()) {
jcoomes@2856 848 ResourceMark rm(THREAD);
duke@435 849 char buf[200];
duke@435 850 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
duke@435 851 resolved_method->name(),
duke@435 852 resolved_method->signature()));
duke@435 853 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
duke@435 854 }
duke@435 855 }
duke@435 856
duke@435 857 // throws runtime exceptions
duke@435 858 void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
duke@435 859 methodHandle resolved_method,
duke@435 860 KlassHandle resolved_klass,
duke@435 861 Handle recv,
duke@435 862 KlassHandle recv_klass,
duke@435 863 bool check_null_and_abstract,
duke@435 864 TRAPS) {
duke@435 865
duke@435 866 // setup default return values
duke@435 867 int vtable_index = methodOopDesc::invalid_vtable_index;
duke@435 868 methodHandle selected_method;
duke@435 869
duke@435 870 assert(recv.is_null() || recv->is_oop(), "receiver is not an oop");
duke@435 871
duke@435 872 // runtime method resolution
duke@435 873 if (check_null_and_abstract && recv.is_null()) { // check if receiver exists
duke@435 874 THROW(vmSymbols::java_lang_NullPointerException());
duke@435 875 }
duke@435 876
duke@435 877 // Virtual methods cannot be resolved before its klass has been linked, for otherwise the methodOop's
duke@435 878 // has not been rewritten, and the vtable initialized.
duke@435 879 assert(instanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked");
duke@435 880
duke@435 881 // Virtual methods cannot be resolved before its klass has been linked, for otherwise the methodOop's
duke@435 882 // has not been rewritten, and the vtable initialized. Make sure to do this after the nullcheck, since
duke@435 883 // a missing receiver might result in a bogus lookup.
duke@435 884 assert(instanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked");
duke@435 885
duke@435 886 // do lookup based on receiver klass using the vtable index
duke@435 887 if (resolved_method->method_holder()->klass_part()->is_interface()) { // miranda method
duke@435 888 vtable_index = vtable_index_of_miranda_method(resolved_klass,
coleenp@2497 889 resolved_method->name(),
coleenp@2497 890 resolved_method->signature(), CHECK);
duke@435 891 assert(vtable_index >= 0 , "we should have valid vtable index at this point");
duke@435 892
duke@435 893 instanceKlass* inst = instanceKlass::cast(recv_klass());
duke@435 894 selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index));
duke@435 895 } else {
duke@435 896 // at this point we are sure that resolved_method is virtual and not
duke@435 897 // a miranda method; therefore, it must have a valid vtable index.
duke@435 898 vtable_index = resolved_method->vtable_index();
duke@435 899 // We could get a negative vtable_index for final methods,
duke@435 900 // because as an optimization they are they are never put in the vtable,
duke@435 901 // unless they override an existing method.
duke@435 902 // If we do get a negative, it means the resolved method is the the selected
duke@435 903 // method, and it can never be changed by an override.
duke@435 904 if (vtable_index == methodOopDesc::nonvirtual_vtable_index) {
duke@435 905 assert(resolved_method->can_be_statically_bound(), "cannot override this method");
duke@435 906 selected_method = resolved_method;
duke@435 907 } else {
duke@435 908 // recv_klass might be an arrayKlassOop but all vtables start at
duke@435 909 // the same place. The cast is to avoid virtual call and assertion.
duke@435 910 instanceKlass* inst = (instanceKlass*)recv_klass()->klass_part();
duke@435 911 selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index));
duke@435 912 }
duke@435 913 }
duke@435 914
duke@435 915 // check if method exists
duke@435 916 if (selected_method.is_null()) {
duke@435 917 ResourceMark rm(THREAD);
duke@435 918 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
duke@435 919 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
duke@435 920 resolved_method->name(),
duke@435 921 resolved_method->signature()));
duke@435 922 }
duke@435 923
duke@435 924 // check if abstract
duke@435 925 if (check_null_and_abstract && selected_method->is_abstract()) {
duke@435 926 ResourceMark rm(THREAD);
duke@435 927 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
duke@435 928 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
duke@435 929 selected_method->name(),
duke@435 930 selected_method->signature()));
duke@435 931 }
duke@435 932
duke@435 933 // setup result
duke@435 934 result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
duke@435 935 }
duke@435 936
duke@435 937 void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass,
coleenp@2497 938 Symbol* method_name, Symbol* method_signature, KlassHandle current_klass,
duke@435 939 bool check_access, bool check_null_and_abstract, TRAPS) {
duke@435 940 methodHandle resolved_method;
duke@435 941 linktime_resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
duke@435 942 runtime_resolve_interface_method(result, resolved_method, resolved_klass, recv, recv_klass, check_null_and_abstract, CHECK);
duke@435 943 }
duke@435 944
duke@435 945 // throws linktime exceptions
coleenp@2497 946 void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name,
coleenp@2497 947 Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
duke@435 948 // normal interface method resolution
duke@435 949 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
duke@435 950
duke@435 951 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier");
duke@435 952 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier");
duke@435 953 }
duke@435 954
duke@435 955 // throws runtime exceptions
duke@435 956 void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass,
duke@435 957 Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS) {
duke@435 958 // check if receiver exists
duke@435 959 if (check_null_and_abstract && recv.is_null()) {
duke@435 960 THROW(vmSymbols::java_lang_NullPointerException());
duke@435 961 }
duke@435 962
duke@435 963 // check if receiver klass implements the resolved interface
duke@435 964 if (!recv_klass->is_subtype_of(resolved_klass())) {
jcoomes@2856 965 ResourceMark rm(THREAD);
duke@435 966 char buf[200];
duke@435 967 jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s",
duke@435 968 (Klass::cast(recv_klass()))->external_name(),
duke@435 969 (Klass::cast(resolved_klass()))->external_name());
duke@435 970 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
duke@435 971 }
duke@435 972 // do lookup based on receiver klass
duke@435 973 methodHandle sel_method;
duke@435 974 lookup_instance_method_in_klasses(sel_method, recv_klass,
coleenp@2497 975 resolved_method->name(),
coleenp@2497 976 resolved_method->signature(), CHECK);
duke@435 977 // check if method exists
duke@435 978 if (sel_method.is_null()) {
duke@435 979 ResourceMark rm(THREAD);
duke@435 980 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
duke@435 981 methodOopDesc::name_and_sig_as_C_string(Klass::cast(recv_klass()),
duke@435 982 resolved_method->name(),
duke@435 983 resolved_method->signature()));
duke@435 984 }
duke@435 985 // check if public
duke@435 986 if (!sel_method->is_public()) {
duke@435 987 ResourceMark rm(THREAD);
duke@435 988 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
duke@435 989 methodOopDesc::name_and_sig_as_C_string(Klass::cast(recv_klass()),
duke@435 990 sel_method->name(),
duke@435 991 sel_method->signature()));
duke@435 992 }
duke@435 993 // check if abstract
duke@435 994 if (check_null_and_abstract && sel_method->is_abstract()) {
duke@435 995 ResourceMark rm(THREAD);
duke@435 996 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
duke@435 997 methodOopDesc::name_and_sig_as_C_string(Klass::cast(recv_klass()),
duke@435 998 sel_method->name(),
duke@435 999 sel_method->signature()));
duke@435 1000 }
duke@435 1001 // setup result
duke@435 1002 result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, CHECK);
duke@435 1003 }
duke@435 1004
duke@435 1005
duke@435 1006 methodHandle LinkResolver::linktime_resolve_interface_method_or_null(
duke@435 1007 KlassHandle resolved_klass,
coleenp@2497 1008 Symbol* method_name,
coleenp@2497 1009 Symbol* method_signature,
duke@435 1010 KlassHandle current_klass,
duke@435 1011 bool check_access) {
duke@435 1012 EXCEPTION_MARK;
duke@435 1013 methodHandle method_result;
duke@435 1014 linktime_resolve_interface_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD);
duke@435 1015 if (HAS_PENDING_EXCEPTION) {
duke@435 1016 CLEAR_PENDING_EXCEPTION;
duke@435 1017 return methodHandle();
duke@435 1018 } else {
duke@435 1019 return method_result;
duke@435 1020 }
duke@435 1021 }
duke@435 1022
duke@435 1023 methodHandle LinkResolver::linktime_resolve_virtual_method_or_null(
duke@435 1024 KlassHandle resolved_klass,
coleenp@2497 1025 Symbol* method_name,
coleenp@2497 1026 Symbol* method_signature,
duke@435 1027 KlassHandle current_klass,
duke@435 1028 bool check_access) {
duke@435 1029 EXCEPTION_MARK;
duke@435 1030 methodHandle method_result;
duke@435 1031 linktime_resolve_virtual_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD);
duke@435 1032 if (HAS_PENDING_EXCEPTION) {
duke@435 1033 CLEAR_PENDING_EXCEPTION;
duke@435 1034 return methodHandle();
duke@435 1035 } else {
duke@435 1036 return method_result;
duke@435 1037 }
duke@435 1038 }
duke@435 1039
duke@435 1040 methodHandle LinkResolver::resolve_virtual_call_or_null(
duke@435 1041 KlassHandle receiver_klass,
duke@435 1042 KlassHandle resolved_klass,
coleenp@2497 1043 Symbol* name,
coleenp@2497 1044 Symbol* signature,
duke@435 1045 KlassHandle current_klass) {
duke@435 1046 EXCEPTION_MARK;
duke@435 1047 CallInfo info;
duke@435 1048 resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD);
duke@435 1049 if (HAS_PENDING_EXCEPTION) {
duke@435 1050 CLEAR_PENDING_EXCEPTION;
duke@435 1051 return methodHandle();
duke@435 1052 }
duke@435 1053 return info.selected_method();
duke@435 1054 }
duke@435 1055
duke@435 1056 methodHandle LinkResolver::resolve_interface_call_or_null(
duke@435 1057 KlassHandle receiver_klass,
duke@435 1058 KlassHandle resolved_klass,
coleenp@2497 1059 Symbol* name,
coleenp@2497 1060 Symbol* signature,
duke@435 1061 KlassHandle current_klass) {
duke@435 1062 EXCEPTION_MARK;
duke@435 1063 CallInfo info;
duke@435 1064 resolve_interface_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD);
duke@435 1065 if (HAS_PENDING_EXCEPTION) {
duke@435 1066 CLEAR_PENDING_EXCEPTION;
duke@435 1067 return methodHandle();
duke@435 1068 }
duke@435 1069 return info.selected_method();
duke@435 1070 }
duke@435 1071
duke@435 1072 int LinkResolver::resolve_virtual_vtable_index(
duke@435 1073 KlassHandle receiver_klass,
duke@435 1074 KlassHandle resolved_klass,
coleenp@2497 1075 Symbol* name,
coleenp@2497 1076 Symbol* signature,
duke@435 1077 KlassHandle current_klass) {
duke@435 1078 EXCEPTION_MARK;
duke@435 1079 CallInfo info;
duke@435 1080 resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD);
duke@435 1081 if (HAS_PENDING_EXCEPTION) {
duke@435 1082 CLEAR_PENDING_EXCEPTION;
duke@435 1083 return methodOopDesc::invalid_vtable_index;
duke@435 1084 }
duke@435 1085 return info.vtable_index();
duke@435 1086 }
duke@435 1087
duke@435 1088 methodHandle LinkResolver::resolve_static_call_or_null(
duke@435 1089 KlassHandle resolved_klass,
coleenp@2497 1090 Symbol* name,
coleenp@2497 1091 Symbol* signature,
duke@435 1092 KlassHandle current_klass) {
duke@435 1093 EXCEPTION_MARK;
duke@435 1094 CallInfo info;
duke@435 1095 resolve_static_call(info, resolved_klass, name, signature, current_klass, true, false, THREAD);
duke@435 1096 if (HAS_PENDING_EXCEPTION) {
duke@435 1097 CLEAR_PENDING_EXCEPTION;
duke@435 1098 return methodHandle();
duke@435 1099 }
duke@435 1100 return info.selected_method();
duke@435 1101 }
duke@435 1102
coleenp@2497 1103 methodHandle LinkResolver::resolve_special_call_or_null(KlassHandle resolved_klass, Symbol* name, Symbol* signature,
duke@435 1104 KlassHandle current_klass) {
duke@435 1105 EXCEPTION_MARK;
duke@435 1106 CallInfo info;
duke@435 1107 resolve_special_call(info, resolved_klass, name, signature, current_klass, true, THREAD);
duke@435 1108 if (HAS_PENDING_EXCEPTION) {
duke@435 1109 CLEAR_PENDING_EXCEPTION;
duke@435 1110 return methodHandle();
duke@435 1111 }
duke@435 1112 return info.selected_method();
duke@435 1113 }
duke@435 1114
duke@435 1115
duke@435 1116
duke@435 1117 //------------------------------------------------------------------------------------------------------------------------
duke@435 1118 // ConstantPool entries
duke@435 1119
duke@435 1120 void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) {
duke@435 1121 switch (byte) {
duke@435 1122 case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break;
duke@435 1123 case Bytecodes::_invokespecial : resolve_invokespecial (result, pool, index, CHECK); break;
duke@435 1124 case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, CHECK); break;
twisti@3969 1125 case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break;
jrose@1161 1126 case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break;
duke@435 1127 case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break;
duke@435 1128 }
duke@435 1129 return;
duke@435 1130 }
duke@435 1131
coleenp@2497 1132 void LinkResolver::resolve_pool(KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature,
duke@435 1133 KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS) {
duke@435 1134 // resolve klass
duke@435 1135 resolve_klass(resolved_klass, pool, index, CHECK);
duke@435 1136
duke@435 1137 // Get name, signature, and static klass
coleenp@2497 1138 method_name = pool->name_ref_at(index);
coleenp@2497 1139 method_signature = pool->signature_ref_at(index);
duke@435 1140 current_klass = KlassHandle(THREAD, pool->pool_holder());
duke@435 1141 }
duke@435 1142
duke@435 1143
duke@435 1144 void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
duke@435 1145 KlassHandle resolved_klass;
coleenp@2497 1146 Symbol* method_name = NULL;
coleenp@2497 1147 Symbol* method_signature = NULL;
duke@435 1148 KlassHandle current_klass;
duke@435 1149 resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
duke@435 1150 resolve_static_call(result, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
duke@435 1151 }
duke@435 1152
duke@435 1153
duke@435 1154 void LinkResolver::resolve_invokespecial(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
duke@435 1155 KlassHandle resolved_klass;
coleenp@2497 1156 Symbol* method_name = NULL;
coleenp@2497 1157 Symbol* method_signature = NULL;
duke@435 1158 KlassHandle current_klass;
duke@435 1159 resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
duke@435 1160 resolve_special_call(result, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
duke@435 1161 }
duke@435 1162
duke@435 1163
duke@435 1164 void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv,
duke@435 1165 constantPoolHandle pool, int index,
duke@435 1166 TRAPS) {
duke@435 1167
duke@435 1168 KlassHandle resolved_klass;
coleenp@2497 1169 Symbol* method_name = NULL;
coleenp@2497 1170 Symbol* method_signature = NULL;
duke@435 1171 KlassHandle current_klass;
duke@435 1172 resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
duke@435 1173 KlassHandle recvrKlass (THREAD, recv.is_null() ? (klassOop)NULL : recv->klass());
duke@435 1174 resolve_virtual_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
duke@435 1175 }
duke@435 1176
duke@435 1177
duke@435 1178 void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) {
duke@435 1179 KlassHandle resolved_klass;
coleenp@2497 1180 Symbol* method_name = NULL;
coleenp@2497 1181 Symbol* method_signature = NULL;
duke@435 1182 KlassHandle current_klass;
duke@435 1183 resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
duke@435 1184 KlassHandle recvrKlass (THREAD, recv.is_null() ? (klassOop)NULL : recv->klass());
duke@435 1185 resolve_interface_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
duke@435 1186 }
duke@435 1187
jrose@1161 1188
twisti@3969 1189 void LinkResolver::resolve_invokehandle(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
jrose@1161 1190 assert(EnableInvokeDynamic, "");
twisti@3969 1191 // This guy is reached from InterpreterRuntime::resolve_invokehandle.
twisti@3969 1192 KlassHandle resolved_klass;
twisti@3969 1193 Symbol* method_name = NULL;
twisti@3969 1194 Symbol* method_signature = NULL;
twisti@3969 1195 KlassHandle current_klass;
twisti@3969 1196 resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
twisti@3969 1197 if (TraceMethodHandles)
twisti@3969 1198 tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string());
twisti@3969 1199 resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK);
twisti@3969 1200 }
jrose@1161 1201
twisti@3969 1202 void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_klass,
twisti@3969 1203 Symbol* method_name, Symbol* method_signature,
twisti@3969 1204 KlassHandle current_klass,
twisti@3969 1205 TRAPS) {
twisti@3969 1206 // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar
twisti@3969 1207 assert(resolved_klass() == SystemDictionary::MethodHandle_klass(), "");
twisti@3969 1208 assert(MethodHandles::is_signature_polymorphic_name(method_name), "");
twisti@3969 1209 methodHandle resolved_method;
twisti@3969 1210 Handle resolved_appendix;
twisti@3969 1211 lookup_polymorphic_method(resolved_method, resolved_klass,
twisti@3969 1212 method_name, method_signature,
twisti@3969 1213 current_klass, &resolved_appendix, CHECK);
twisti@3969 1214 result.set_handle(resolved_method, resolved_appendix, CHECK);
twisti@3969 1215 }
jrose@1161 1216
jrose@1161 1217
twisti@3969 1218 void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
twisti@3969 1219 assert(EnableInvokeDynamic, "");
twisti@3969 1220 pool->set_invokedynamic(); // mark header to flag active call sites
twisti@3969 1221
twisti@3969 1222 //resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK);
twisti@3969 1223 Symbol* method_name = pool->name_ref_at(index);
twisti@3969 1224 Symbol* method_signature = pool->signature_ref_at(index);
twisti@3969 1225 KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder());
twisti@3969 1226
twisti@3969 1227 // Resolve the bootstrap specifier (BSM + optional arguments).
twisti@3969 1228 Handle bootstrap_specifier;
twisti@3969 1229 // Check if CallSite has been bound already:
twisti@3969 1230 ConstantPoolCacheEntry* cpce = pool->cache()->secondary_entry_at(index);
twisti@3969 1231 if (cpce->is_f1_null()) {
twisti@3969 1232 int pool_index = pool->cache()->main_entry_at(index)->constant_pool_index();
twisti@3969 1233 oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, CHECK);
twisti@3969 1234 assert(bsm_info != NULL, "");
twisti@3969 1235 // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic.
twisti@3969 1236 bootstrap_specifier = Handle(THREAD, bsm_info);
twisti@3969 1237 }
twisti@3969 1238 if (!cpce->is_f1_null()) {
twisti@3969 1239 methodHandle method(THREAD, cpce->f2_as_vfinal_method());
twisti@3969 1240 Handle appendix(THREAD, cpce->has_appendix() ? cpce->f1_appendix() : (oop)NULL);
twisti@3969 1241 result.set_handle(method, appendix, CHECK);
twisti@3969 1242 return;
twisti@3969 1243 }
twisti@3969 1244
twisti@3969 1245 if (TraceMethodHandles) {
twisti@3969 1246 tty->print_cr("resolve_invokedynamic #%d %s %s",
twisti@3969 1247 constantPoolCacheOopDesc::decode_secondary_index(index),
twisti@3969 1248 method_name->as_C_string(), method_signature->as_C_string());
twisti@3969 1249 tty->print(" BSM info: "); bootstrap_specifier->print();
twisti@3969 1250 }
twisti@3969 1251
twisti@3969 1252 resolve_dynamic_call(result, bootstrap_specifier, method_name, method_signature, current_klass, CHECK);
twisti@3969 1253 }
twisti@3969 1254
twisti@3969 1255 void LinkResolver::resolve_dynamic_call(CallInfo& result,
twisti@3969 1256 Handle bootstrap_specifier,
twisti@3969 1257 Symbol* method_name, Symbol* method_signature,
twisti@3969 1258 KlassHandle current_klass,
twisti@3969 1259 TRAPS) {
twisti@3969 1260 // JSR 292: this must resolve to an implicitly generated method MH.linkToCallSite(*...)
twisti@3969 1261 // The appendix argument is likely to be a freshly-created CallSite.
twisti@3969 1262 Handle resolved_appendix;
twisti@3969 1263 methodHandle resolved_method =
twisti@3969 1264 SystemDictionary::find_dynamic_call_site_invoker(current_klass,
twisti@3969 1265 bootstrap_specifier,
twisti@3969 1266 method_name, method_signature,
twisti@3969 1267 &resolved_appendix,
twisti@3974 1268 THREAD);
jrose@2941 1269 if (HAS_PENDING_EXCEPTION) {
twisti@3969 1270 if (TraceMethodHandles) {
twisti@3969 1271 tty->print_cr("invokedynamic throws BSME for "INTPTR_FORMAT, PENDING_EXCEPTION);
twisti@3969 1272 PENDING_EXCEPTION->print();
twisti@3969 1273 }
jrose@2941 1274 if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) {
jrose@2941 1275 // throw these guys, since they are already wrapped
jrose@2941 1276 return;
jrose@2941 1277 }
jrose@2941 1278 if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
jrose@2941 1279 // intercept only LinkageErrors which might have failed to wrap
jrose@2941 1280 return;
jrose@2941 1281 }
jrose@2941 1282 // See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS.
twisti@3969 1283 Handle nested_exception(THREAD, PENDING_EXCEPTION);
jrose@2941 1284 CLEAR_PENDING_EXCEPTION;
twisti@3974 1285 THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception)
jrose@2941 1286 }
twisti@3969 1287 result.set_handle(resolved_method, resolved_appendix, CHECK);
jrose@1161 1288 }
jrose@1161 1289
duke@435 1290 //------------------------------------------------------------------------------------------------------------------------
duke@435 1291 #ifndef PRODUCT
duke@435 1292
duke@435 1293 void FieldAccessInfo::print() {
duke@435 1294 ResourceMark rm;
duke@435 1295 tty->print_cr("Field %s@%d", name()->as_C_string(), field_offset());
duke@435 1296 }
duke@435 1297
duke@435 1298 #endif

mercurial