1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/interpreter/linkResolver.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,1000 @@ 1.4 +/* 1.5 + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "incls/_precompiled.incl" 1.29 +#include "incls/_linkResolver.cpp.incl" 1.30 + 1.31 +//------------------------------------------------------------------------------------------------------------------------ 1.32 +// Implementation of FieldAccessInfo 1.33 + 1.34 +void FieldAccessInfo::set(KlassHandle klass, symbolHandle name, int field_index, int field_offset, 1.35 +BasicType field_type, AccessFlags access_flags) { 1.36 + _klass = klass; 1.37 + _name = name; 1.38 + _field_index = field_index; 1.39 + _field_offset = field_offset; 1.40 + _field_type = field_type; 1.41 + _access_flags = access_flags; 1.42 +} 1.43 + 1.44 + 1.45 +//------------------------------------------------------------------------------------------------------------------------ 1.46 +// Implementation of CallInfo 1.47 + 1.48 + 1.49 +void CallInfo::set_static(KlassHandle resolved_klass, methodHandle resolved_method, TRAPS) { 1.50 + int vtable_index = methodOopDesc::nonvirtual_vtable_index; 1.51 + set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, vtable_index, CHECK); 1.52 +} 1.53 + 1.54 + 1.55 +void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, TRAPS) { 1.56 + // This is only called for interface methods. If the resolved_method 1.57 + // comes from java/lang/Object, it can be the subject of a virtual call, so 1.58 + // we should pick the vtable index from the resolved method. 1.59 + // Other than that case, there is no valid vtable index to specify. 1.60 + int vtable_index = methodOopDesc::invalid_vtable_index; 1.61 + if (resolved_method->method_holder() == SystemDictionary::object_klass()) { 1.62 + assert(resolved_method->vtable_index() == selected_method->vtable_index(), "sanity check"); 1.63 + vtable_index = resolved_method->vtable_index(); 1.64 + } 1.65 + set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK); 1.66 +} 1.67 + 1.68 +void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { 1.69 + assert(vtable_index >= 0 || vtable_index == methodOopDesc::nonvirtual_vtable_index, "valid index"); 1.70 + set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK); 1.71 +} 1.72 + 1.73 +void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { 1.74 + assert(resolved_method->signature() == selected_method->signature(), "signatures must correspond"); 1.75 + _resolved_klass = resolved_klass; 1.76 + _selected_klass = selected_klass; 1.77 + _resolved_method = resolved_method; 1.78 + _selected_method = selected_method; 1.79 + _vtable_index = vtable_index; 1.80 + if (CompilationPolicy::mustBeCompiled(selected_method)) { 1.81 + // Note: with several active threads, the mustBeCompiled may be true 1.82 + // while canBeCompiled is false; remove assert 1.83 + // assert(CompilationPolicy::canBeCompiled(selected_method), "cannot compile"); 1.84 + if (THREAD->is_Compiler_thread()) { 1.85 + // don't force compilation, resolve was on behalf of compiler 1.86 + return; 1.87 + } 1.88 + CompileBroker::compile_method(selected_method, InvocationEntryBci, 1.89 + methodHandle(), 0, "mustBeCompiled", CHECK); 1.90 + } 1.91 +} 1.92 + 1.93 + 1.94 +//------------------------------------------------------------------------------------------------------------------------ 1.95 +// Klass resolution 1.96 + 1.97 +void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) { 1.98 + if (!Reflection::verify_class_access(ref_klass->as_klassOop(), 1.99 + sel_klass->as_klassOop(), 1.100 + true)) { 1.101 + ResourceMark rm(THREAD); 1.102 + Exceptions::fthrow( 1.103 + THREAD_AND_LOCATION, 1.104 + vmSymbolHandles::java_lang_IllegalAccessError(), 1.105 + "tried to access class %s from class %s", 1.106 + sel_klass->external_name(), 1.107 + ref_klass->external_name() 1.108 + ); 1.109 + return; 1.110 + } 1.111 +} 1.112 + 1.113 +void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, int index, TRAPS) { 1.114 + klassOop result_oop = pool->klass_ref_at(index, CHECK); 1.115 + result = KlassHandle(THREAD, result_oop); 1.116 +} 1.117 + 1.118 +void LinkResolver::resolve_klass_no_update(KlassHandle& result, constantPoolHandle pool, int index, TRAPS) { 1.119 + klassOop result_oop = 1.120 + constantPoolOopDesc::klass_ref_at_if_loaded_check(pool, index, CHECK); 1.121 + result = KlassHandle(THREAD, result_oop); 1.122 +} 1.123 + 1.124 + 1.125 +//------------------------------------------------------------------------------------------------------------------------ 1.126 +// Method resolution 1.127 +// 1.128 +// According to JVM spec. $5.4.3c & $5.4.3d 1.129 + 1.130 +void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { 1.131 + methodOop result_oop = klass->uncached_lookup_method(name(), signature()); 1.132 + result = methodHandle(THREAD, result_oop); 1.133 +} 1.134 + 1.135 +// returns first instance method 1.136 +void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { 1.137 + methodOop result_oop = klass->uncached_lookup_method(name(), signature()); 1.138 + result = methodHandle(THREAD, result_oop); 1.139 + while (!result.is_null() && result->is_static()) { 1.140 + klass = KlassHandle(THREAD, Klass::cast(result->method_holder())->super()); 1.141 + result = methodHandle(THREAD, klass->uncached_lookup_method(name(), signature())); 1.142 + } 1.143 +} 1.144 + 1.145 + 1.146 +int LinkResolver::vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { 1.147 + ResourceMark rm(THREAD); 1.148 + klassVtable *vt = instanceKlass::cast(klass())->vtable(); 1.149 + return vt->index_of_miranda(name(), signature()); 1.150 +} 1.151 + 1.152 +void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { 1.153 + instanceKlass *ik = instanceKlass::cast(klass()); 1.154 + result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature())); 1.155 +} 1.156 + 1.157 +void LinkResolver::check_method_accessability(KlassHandle ref_klass, 1.158 + KlassHandle resolved_klass, 1.159 + KlassHandle sel_klass, 1.160 + methodHandle sel_method, 1.161 + TRAPS) { 1.162 + 1.163 + AccessFlags flags = sel_method->access_flags(); 1.164 + 1.165 + // Special case: arrays always override "clone". JVMS 2.15. 1.166 + // If the resolved klass is an array class, and the declaring class 1.167 + // is java.lang.Object and the method is "clone", set the flags 1.168 + // to public. 1.169 + // 1.170 + // We'll check for the method name first, as that's most likely 1.171 + // to be false (so we'll short-circuit out of these tests). 1.172 + if (sel_method->name() == vmSymbols::clone_name() && 1.173 + sel_klass() == SystemDictionary::object_klass() && 1.174 + resolved_klass->oop_is_array()) { 1.175 + // We need to change "protected" to "public". 1.176 + assert(flags.is_protected(), "clone not protected?"); 1.177 + jint new_flags = flags.as_int(); 1.178 + new_flags = new_flags & (~JVM_ACC_PROTECTED); 1.179 + new_flags = new_flags | JVM_ACC_PUBLIC; 1.180 + flags.set_flags(new_flags); 1.181 + } 1.182 + 1.183 + if (!Reflection::verify_field_access(ref_klass->as_klassOop(), 1.184 + resolved_klass->as_klassOop(), 1.185 + sel_klass->as_klassOop(), 1.186 + flags, 1.187 + true)) { 1.188 + ResourceMark rm(THREAD); 1.189 + Exceptions::fthrow( 1.190 + THREAD_AND_LOCATION, 1.191 + vmSymbolHandles::java_lang_IllegalAccessError(), 1.192 + "tried to access method %s.%s%s from class %s", 1.193 + sel_klass->external_name(), 1.194 + sel_method->name()->as_C_string(), 1.195 + sel_method->signature()->as_C_string(), 1.196 + ref_klass->external_name() 1.197 + ); 1.198 + return; 1.199 + } 1.200 +} 1.201 + 1.202 +void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle& resolved_klass, 1.203 + constantPoolHandle pool, int index, TRAPS) { 1.204 + 1.205 + // resolve klass 1.206 + resolve_klass(resolved_klass, pool, index, CHECK); 1.207 + 1.208 + symbolHandle method_name (THREAD, pool->name_ref_at(index)); 1.209 + symbolHandle method_signature (THREAD, pool->signature_ref_at(index)); 1.210 + KlassHandle current_klass(THREAD, pool->pool_holder()); 1.211 + 1.212 + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); 1.213 +} 1.214 + 1.215 +void LinkResolver::resolve_interface_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) { 1.216 + 1.217 + // resolve klass 1.218 + resolve_klass(resolved_klass, pool, index, CHECK); 1.219 + symbolHandle method_name (THREAD, pool->name_ref_at(index)); 1.220 + symbolHandle method_signature (THREAD, pool->signature_ref_at(index)); 1.221 + KlassHandle current_klass(THREAD, pool->pool_holder()); 1.222 + 1.223 + resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); 1.224 +} 1.225 + 1.226 + 1.227 +void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass, 1.228 + symbolHandle method_name, symbolHandle method_signature, 1.229 + KlassHandle current_klass, bool check_access, TRAPS) { 1.230 + 1.231 + // 1. check if klass is not interface 1.232 + if (resolved_klass->is_interface()) { 1.233 + char buf[200]; 1.234 + jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name()); 1.235 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 1.236 + } 1.237 + 1.238 + // 2. lookup method in resolved klass and its super klasses 1.239 + lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); 1.240 + 1.241 + if (resolved_method.is_null()) { // not found in the class hierarchy 1.242 + // 3. lookup method in all the interfaces implemented by the resolved klass 1.243 + lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); 1.244 + 1.245 + if (resolved_method.is_null()) { 1.246 + // 4. method lookup failed 1.247 + ResourceMark rm(THREAD); 1.248 + THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), 1.249 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.250 + method_name(), 1.251 + method_signature())); 1.252 + } 1.253 + } 1.254 + 1.255 + // 5. check if method is concrete 1.256 + if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { 1.257 + ResourceMark rm(THREAD); 1.258 + THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), 1.259 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.260 + method_name(), 1.261 + method_signature())); 1.262 + } 1.263 + 1.264 + // 6. access checks, access checking may be turned off when calling from within the VM. 1.265 + if (check_access) { 1.266 + assert(current_klass.not_null() , "current_klass should not be null"); 1.267 + 1.268 + // check if method can be accessed by the referring class 1.269 + check_method_accessability(current_klass, 1.270 + resolved_klass, 1.271 + KlassHandle(THREAD, resolved_method->method_holder()), 1.272 + resolved_method, 1.273 + CHECK); 1.274 + 1.275 + // check loader constraints 1.276 + Handle loader (THREAD, instanceKlass::cast(current_klass())->class_loader()); 1.277 + Handle class_loader (THREAD, instanceKlass::cast(resolved_method->method_holder())->class_loader()); 1.278 + { 1.279 + ResourceMark rm(THREAD); 1.280 + char* failed_type_name = 1.281 + SystemDictionary::check_signature_loaders(method_signature, loader, 1.282 + class_loader, true, CHECK); 1.283 + if (failed_type_name != NULL) { 1.284 + const char* msg = "loader constraint violation: when resolving method" 1.285 + " \"%s\" the class loader (instance of %s) of the current class, %s," 1.286 + " and the class loader (instance of %s) for resolved class, %s, have" 1.287 + " different Class objects for the type %s used in the signature"; 1.288 + char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name(),method_signature()); 1.289 + const char* loader1 = SystemDictionary::loader_name(loader()); 1.290 + char* current = instanceKlass::cast(current_klass())->name()->as_C_string(); 1.291 + const char* loader2 = SystemDictionary::loader_name(class_loader()); 1.292 + char* resolved = instanceKlass::cast(resolved_klass())->name()->as_C_string(); 1.293 + size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + 1.294 + strlen(current) + strlen(loader2) + strlen(resolved) + 1.295 + strlen(failed_type_name); 1.296 + char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); 1.297 + jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2, 1.298 + resolved, failed_type_name); 1.299 + THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); 1.300 + } 1.301 + } 1.302 + } 1.303 +} 1.304 + 1.305 +void LinkResolver::resolve_interface_method(methodHandle& resolved_method, 1.306 + KlassHandle resolved_klass, 1.307 + symbolHandle method_name, 1.308 + symbolHandle method_signature, 1.309 + KlassHandle current_klass, 1.310 + bool check_access, TRAPS) { 1.311 + 1.312 + // check if klass is interface 1.313 + if (!resolved_klass->is_interface()) { 1.314 + char buf[200]; 1.315 + jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", Klass::cast(resolved_klass())->external_name()); 1.316 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 1.317 + } 1.318 + 1.319 + // lookup method in this interface or its super, java.lang.Object 1.320 + lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); 1.321 + 1.322 + if (resolved_method.is_null()) { 1.323 + // lookup method in all the super-interfaces 1.324 + lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); 1.325 + if (resolved_method.is_null()) { 1.326 + // no method found 1.327 + ResourceMark rm(THREAD); 1.328 + THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), 1.329 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.330 + method_name(), 1.331 + method_signature())); 1.332 + } 1.333 + } 1.334 + 1.335 + if (check_access) { 1.336 + HandleMark hm(THREAD); 1.337 + Handle loader (THREAD, instanceKlass::cast(current_klass())->class_loader()); 1.338 + Handle class_loader (THREAD, instanceKlass::cast(resolved_method->method_holder())->class_loader()); 1.339 + { 1.340 + ResourceMark rm(THREAD); 1.341 + char* failed_type_name = 1.342 + SystemDictionary::check_signature_loaders(method_signature, loader, 1.343 + class_loader, true, CHECK); 1.344 + if (failed_type_name != NULL) { 1.345 + const char* msg = "loader constraint violation: when resolving " 1.346 + "interface method \"%s\" the class loader (instance of %s) of the " 1.347 + "current class, %s, and the class loader (instance of %s) for " 1.348 + "resolved class, %s, have different Class objects for the type %s " 1.349 + "used in the signature"; 1.350 + char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name(),method_signature()); 1.351 + const char* loader1 = SystemDictionary::loader_name(loader()); 1.352 + char* current = instanceKlass::cast(current_klass())->name()->as_C_string(); 1.353 + const char* loader2 = SystemDictionary::loader_name(class_loader()); 1.354 + char* resolved = instanceKlass::cast(resolved_klass())->name()->as_C_string(); 1.355 + size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + 1.356 + strlen(current) + strlen(loader2) + strlen(resolved) + 1.357 + strlen(failed_type_name); 1.358 + char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); 1.359 + jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2, 1.360 + resolved, failed_type_name); 1.361 + THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); 1.362 + } 1.363 + } 1.364 + } 1.365 +} 1.366 + 1.367 +//------------------------------------------------------------------------------------------------------------------------ 1.368 +// Field resolution 1.369 + 1.370 +void LinkResolver::check_field_accessability(KlassHandle ref_klass, 1.371 + KlassHandle resolved_klass, 1.372 + KlassHandle sel_klass, 1.373 + fieldDescriptor& fd, 1.374 + TRAPS) { 1.375 + if (!Reflection::verify_field_access(ref_klass->as_klassOop(), 1.376 + resolved_klass->as_klassOop(), 1.377 + sel_klass->as_klassOop(), 1.378 + fd.access_flags(), 1.379 + true)) { 1.380 + ResourceMark rm(THREAD); 1.381 + Exceptions::fthrow( 1.382 + THREAD_AND_LOCATION, 1.383 + vmSymbolHandles::java_lang_IllegalAccessError(), 1.384 + "tried to access field %s.%s from class %s", 1.385 + sel_klass->external_name(), 1.386 + fd.name()->as_C_string(), 1.387 + ref_klass->external_name() 1.388 + ); 1.389 + return; 1.390 + } 1.391 +} 1.392 + 1.393 +void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, TRAPS) { 1.394 + resolve_field(result, pool, index, byte, check_only, true, CHECK); 1.395 +} 1.396 + 1.397 +void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, bool update_pool, TRAPS) { 1.398 + assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic || 1.399 + byte == Bytecodes::_getfield || byte == Bytecodes::_putfield, "bad bytecode"); 1.400 + 1.401 + bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic); 1.402 + bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic); 1.403 + 1.404 + // resolve specified klass 1.405 + KlassHandle resolved_klass; 1.406 + if (update_pool) { 1.407 + resolve_klass(resolved_klass, pool, index, CHECK); 1.408 + } else { 1.409 + resolve_klass_no_update(resolved_klass, pool, index, CHECK); 1.410 + } 1.411 + // Load these early in case the resolve of the containing klass fails 1.412 + symbolOop field = pool->name_ref_at(index); 1.413 + symbolHandle field_h (THREAD, field); // preserve in case we need the name 1.414 + symbolOop sig = pool->signature_ref_at(index); 1.415 + // Check if there's a resolved klass containing the field 1.416 + if( resolved_klass.is_null() ) { 1.417 + ResourceMark rm(THREAD); 1.418 + THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); 1.419 + } 1.420 + 1.421 + // Resolve instance field 1.422 + fieldDescriptor fd; // find_field initializes fd if found 1.423 + KlassHandle sel_klass(THREAD, instanceKlass::cast(resolved_klass())->find_field(field, sig, &fd)); 1.424 + // check if field exists; i.e., if a klass containing the field def has been selected 1.425 + if (sel_klass.is_null()){ 1.426 + ResourceMark rm(THREAD); 1.427 + THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); 1.428 + } 1.429 + 1.430 + // check access 1.431 + KlassHandle ref_klass(THREAD, pool->pool_holder()); 1.432 + check_field_accessability(ref_klass, resolved_klass, sel_klass, fd, CHECK); 1.433 + 1.434 + // check for errors 1.435 + if (is_static != fd.is_static()) { 1.436 + char msg[200]; 1.437 + 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()); 1.438 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg); 1.439 + } 1.440 + 1.441 + // Final fields can only be accessed from its own class. 1.442 + if (is_put && fd.access_flags().is_final() && sel_klass() != pool->pool_holder()) { 1.443 + THROW(vmSymbols::java_lang_IllegalAccessError()); 1.444 + } 1.445 + 1.446 + // initialize resolved_klass if necessary 1.447 + // note 1: the klass which declared the field must be initialized (i.e, sel_klass) 1.448 + // according to the newest JVM spec (5.5, p.170) - was bug (gri 7/28/99) 1.449 + // 1.450 + // note 2: we don't want to force initialization if we are just checking 1.451 + // if the field access is legal; e.g., during compilation 1.452 + if (is_static && !check_only) { 1.453 + sel_klass->initialize(CHECK); 1.454 + } 1.455 + 1.456 + { 1.457 + HandleMark hm(THREAD); 1.458 + Handle ref_loader (THREAD, instanceKlass::cast(ref_klass())->class_loader()); 1.459 + Handle sel_loader (THREAD, instanceKlass::cast(sel_klass())->class_loader()); 1.460 + symbolHandle signature_ref (THREAD, pool->signature_ref_at(index)); 1.461 + { 1.462 + ResourceMark rm(THREAD); 1.463 + char* failed_type_name = 1.464 + SystemDictionary::check_signature_loaders(signature_ref, 1.465 + ref_loader, sel_loader, 1.466 + false, 1.467 + CHECK); 1.468 + if (failed_type_name != NULL) { 1.469 + const char* msg = "loader constraint violation: when resolving field" 1.470 + " \"%s\" the class loader (instance of %s) of the referring class, " 1.471 + "%s, and the class loader (instance of %s) for the field's resolved " 1.472 + "type, %s, have different Class objects for that type"; 1.473 + char* field_name = field_h()->as_C_string(); 1.474 + const char* loader1 = SystemDictionary::loader_name(ref_loader()); 1.475 + char* sel = instanceKlass::cast(sel_klass())->name()->as_C_string(); 1.476 + const char* loader2 = SystemDictionary::loader_name(sel_loader()); 1.477 + size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1) + 1.478 + strlen(sel) + strlen(loader2) + strlen(failed_type_name); 1.479 + char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); 1.480 + jio_snprintf(buf, buflen, msg, field_name, loader1, sel, loader2, 1.481 + failed_type_name); 1.482 + THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); 1.483 + } 1.484 + } 1.485 + } 1.486 + 1.487 + // return information. note that the klass is set to the actual klass containing the 1.488 + // field, otherwise access of static fields in superclasses will not work. 1.489 + KlassHandle holder (THREAD, fd.field_holder()); 1.490 + symbolHandle name (THREAD, fd.name()); 1.491 + result.set(holder, name, fd.index(), fd.offset(), fd.field_type(), fd.access_flags()); 1.492 +} 1.493 + 1.494 + 1.495 +//------------------------------------------------------------------------------------------------------------------------ 1.496 +// Invoke resolution 1.497 +// 1.498 +// Naming conventions: 1.499 +// 1.500 +// resolved_method the specified method (i.e., static receiver specified via constant pool index) 1.501 +// sel_method the selected method (selected via run-time lookup; e.g., based on dynamic receiver class) 1.502 +// resolved_klass the specified klass (i.e., specified via constant pool index) 1.503 +// recv_klass the receiver klass 1.504 + 1.505 + 1.506 +void LinkResolver::resolve_static_call(CallInfo& result, KlassHandle& resolved_klass, symbolHandle method_name, 1.507 + symbolHandle method_signature, KlassHandle current_klass, 1.508 + bool check_access, bool initialize_class, TRAPS) { 1.509 + methodHandle resolved_method; 1.510 + linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); 1.511 + resolved_klass = KlassHandle(THREAD, Klass::cast(resolved_method->method_holder())); 1.512 + 1.513 + // Initialize klass (this should only happen if everything is ok) 1.514 + if (initialize_class && resolved_klass->should_be_initialized()) { 1.515 + resolved_klass->initialize(CHECK); 1.516 + linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); 1.517 + } 1.518 + 1.519 + // setup result 1.520 + result.set_static(resolved_klass, resolved_method, CHECK); 1.521 +} 1.522 + 1.523 +// throws linktime exceptions 1.524 +void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, KlassHandle resolved_klass, 1.525 + symbolHandle method_name, symbolHandle method_signature, 1.526 + KlassHandle current_klass, bool check_access, TRAPS) { 1.527 + 1.528 + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); 1.529 + assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); 1.530 + 1.531 + // check if static 1.532 + if (!resolved_method->is_static()) { 1.533 + char buf[200]; 1.534 + jio_snprintf(buf, sizeof(buf), "Expected static method %s", methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.535 + resolved_method->name(), 1.536 + resolved_method->signature())); 1.537 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 1.538 + } 1.539 +} 1.540 + 1.541 + 1.542 +void LinkResolver::resolve_special_call(CallInfo& result, KlassHandle resolved_klass, symbolHandle method_name, 1.543 + symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS) { 1.544 + methodHandle resolved_method; 1.545 + linktime_resolve_special_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); 1.546 + runtime_resolve_special_method(result, resolved_method, resolved_klass, current_klass, check_access, CHECK); 1.547 +} 1.548 + 1.549 +// throws linktime exceptions 1.550 +void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass, 1.551 + symbolHandle method_name, symbolHandle method_signature, 1.552 + KlassHandle current_klass, bool check_access, TRAPS) { 1.553 + 1.554 + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); 1.555 + 1.556 + // check if method name is <init>, that it is found in same klass as static type 1.557 + if (resolved_method->name() == vmSymbols::object_initializer_name() && 1.558 + resolved_method->method_holder() != resolved_klass()) { 1.559 + ResourceMark rm(THREAD); 1.560 + Exceptions::fthrow( 1.561 + THREAD_AND_LOCATION, 1.562 + vmSymbolHandles::java_lang_NoSuchMethodError(), 1.563 + "%s: method %s%s not found", 1.564 + resolved_klass->external_name(), 1.565 + resolved_method->name()->as_C_string(), 1.566 + resolved_method->signature()->as_C_string() 1.567 + ); 1.568 + return; 1.569 + } 1.570 + 1.571 + // check if not static 1.572 + if (resolved_method->is_static()) { 1.573 + char buf[200]; 1.574 + jio_snprintf(buf, sizeof(buf), 1.575 + "Expecting non-static method %s", 1.576 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.577 + resolved_method->name(), 1.578 + resolved_method->signature())); 1.579 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 1.580 + } 1.581 +} 1.582 + 1.583 +// throws runtime exceptions 1.584 +void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, 1.585 + KlassHandle current_klass, bool check_access, TRAPS) { 1.586 + 1.587 + // resolved method is selected method unless we have an old-style lookup 1.588 + methodHandle sel_method(THREAD, resolved_method()); 1.589 + 1.590 + // check if this is an old-style super call and do a new lookup if so 1.591 + { KlassHandle method_klass = KlassHandle(THREAD, 1.592 + resolved_method->method_holder()); 1.593 + 1.594 + if (check_access && 1.595 + // a) check if ACC_SUPER flag is set for the current class 1.596 + current_klass->is_super() && 1.597 + // b) check if the method class is a superclass of the current class (superclass relation is not reflexive!) 1.598 + current_klass->is_subtype_of(method_klass()) && current_klass() != method_klass() && 1.599 + // c) check if the method is not <init> 1.600 + resolved_method->name() != vmSymbols::object_initializer_name()) { 1.601 + // Lookup super method 1.602 + KlassHandle super_klass(THREAD, current_klass->super()); 1.603 + lookup_instance_method_in_klasses(sel_method, super_klass, 1.604 + symbolHandle(THREAD, resolved_method->name()), 1.605 + symbolHandle(THREAD, resolved_method->signature()), CHECK); 1.606 + // check if found 1.607 + if (sel_method.is_null()) { 1.608 + ResourceMark rm(THREAD); 1.609 + THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), 1.610 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.611 + resolved_method->name(), 1.612 + resolved_method->signature())); 1.613 + } 1.614 + } 1.615 + } 1.616 + 1.617 + // check if not static 1.618 + if (sel_method->is_static()) { 1.619 + char buf[200]; 1.620 + jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.621 + resolved_method->name(), 1.622 + resolved_method->signature())); 1.623 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 1.624 + } 1.625 + 1.626 + // check if abstract 1.627 + if (sel_method->is_abstract()) { 1.628 + ResourceMark rm(THREAD); 1.629 + THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), 1.630 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.631 + sel_method->name(), 1.632 + sel_method->signature())); 1.633 + } 1.634 + 1.635 + // setup result 1.636 + result.set_static(resolved_klass, sel_method, CHECK); 1.637 +} 1.638 + 1.639 +void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, KlassHandle resolved_klass, 1.640 + symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, 1.641 + bool check_access, bool check_null_and_abstract, TRAPS) { 1.642 + methodHandle resolved_method; 1.643 + linktime_resolve_virtual_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); 1.644 + runtime_resolve_virtual_method(result, resolved_method, resolved_klass, recv, receiver_klass, check_null_and_abstract, CHECK); 1.645 +} 1.646 + 1.647 +// throws linktime exceptions 1.648 +void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method, KlassHandle resolved_klass, 1.649 + symbolHandle method_name, symbolHandle method_signature, 1.650 + KlassHandle current_klass, bool check_access, TRAPS) { 1.651 + // normal method resolution 1.652 + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); 1.653 + 1.654 + assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); 1.655 + assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); 1.656 + 1.657 + // check if not static 1.658 + if (resolved_method->is_static()) { 1.659 + char buf[200]; 1.660 + jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.661 + resolved_method->name(), 1.662 + resolved_method->signature())); 1.663 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 1.664 + } 1.665 +} 1.666 + 1.667 +// throws runtime exceptions 1.668 +void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, 1.669 + methodHandle resolved_method, 1.670 + KlassHandle resolved_klass, 1.671 + Handle recv, 1.672 + KlassHandle recv_klass, 1.673 + bool check_null_and_abstract, 1.674 + TRAPS) { 1.675 + 1.676 + // setup default return values 1.677 + int vtable_index = methodOopDesc::invalid_vtable_index; 1.678 + methodHandle selected_method; 1.679 + 1.680 + assert(recv.is_null() || recv->is_oop(), "receiver is not an oop"); 1.681 + 1.682 + // runtime method resolution 1.683 + if (check_null_and_abstract && recv.is_null()) { // check if receiver exists 1.684 + THROW(vmSymbols::java_lang_NullPointerException()); 1.685 + } 1.686 + 1.687 + // Virtual methods cannot be resolved before its klass has been linked, for otherwise the methodOop's 1.688 + // has not been rewritten, and the vtable initialized. 1.689 + assert(instanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked"); 1.690 + 1.691 + // Virtual methods cannot be resolved before its klass has been linked, for otherwise the methodOop's 1.692 + // has not been rewritten, and the vtable initialized. Make sure to do this after the nullcheck, since 1.693 + // a missing receiver might result in a bogus lookup. 1.694 + assert(instanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked"); 1.695 + 1.696 + // do lookup based on receiver klass using the vtable index 1.697 + if (resolved_method->method_holder()->klass_part()->is_interface()) { // miranda method 1.698 + vtable_index = vtable_index_of_miranda_method(resolved_klass, 1.699 + symbolHandle(THREAD, resolved_method->name()), 1.700 + symbolHandle(THREAD, resolved_method->signature()), CHECK); 1.701 + assert(vtable_index >= 0 , "we should have valid vtable index at this point"); 1.702 + 1.703 + instanceKlass* inst = instanceKlass::cast(recv_klass()); 1.704 + selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index)); 1.705 + } else { 1.706 + // at this point we are sure that resolved_method is virtual and not 1.707 + // a miranda method; therefore, it must have a valid vtable index. 1.708 + vtable_index = resolved_method->vtable_index(); 1.709 + // We could get a negative vtable_index for final methods, 1.710 + // because as an optimization they are they are never put in the vtable, 1.711 + // unless they override an existing method. 1.712 + // If we do get a negative, it means the resolved method is the the selected 1.713 + // method, and it can never be changed by an override. 1.714 + if (vtable_index == methodOopDesc::nonvirtual_vtable_index) { 1.715 + assert(resolved_method->can_be_statically_bound(), "cannot override this method"); 1.716 + selected_method = resolved_method; 1.717 + } else { 1.718 + // recv_klass might be an arrayKlassOop but all vtables start at 1.719 + // the same place. The cast is to avoid virtual call and assertion. 1.720 + instanceKlass* inst = (instanceKlass*)recv_klass()->klass_part(); 1.721 + selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index)); 1.722 + } 1.723 + } 1.724 + 1.725 + // check if method exists 1.726 + if (selected_method.is_null()) { 1.727 + ResourceMark rm(THREAD); 1.728 + THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), 1.729 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.730 + resolved_method->name(), 1.731 + resolved_method->signature())); 1.732 + } 1.733 + 1.734 + // check if abstract 1.735 + if (check_null_and_abstract && selected_method->is_abstract()) { 1.736 + ResourceMark rm(THREAD); 1.737 + THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), 1.738 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), 1.739 + selected_method->name(), 1.740 + selected_method->signature())); 1.741 + } 1.742 + 1.743 + // setup result 1.744 + result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK); 1.745 +} 1.746 + 1.747 +void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, 1.748 + symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, 1.749 + bool check_access, bool check_null_and_abstract, TRAPS) { 1.750 + methodHandle resolved_method; 1.751 + linktime_resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); 1.752 + runtime_resolve_interface_method(result, resolved_method, resolved_klass, recv, recv_klass, check_null_and_abstract, CHECK); 1.753 +} 1.754 + 1.755 +// throws linktime exceptions 1.756 +void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, symbolHandle method_name, 1.757 + symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS) { 1.758 + // normal interface method resolution 1.759 + resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); 1.760 + 1.761 + assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); 1.762 + assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); 1.763 +} 1.764 + 1.765 +// throws runtime exceptions 1.766 +void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, 1.767 + Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS) { 1.768 + // check if receiver exists 1.769 + if (check_null_and_abstract && recv.is_null()) { 1.770 + THROW(vmSymbols::java_lang_NullPointerException()); 1.771 + } 1.772 + 1.773 + // check if receiver klass implements the resolved interface 1.774 + if (!recv_klass->is_subtype_of(resolved_klass())) { 1.775 + char buf[200]; 1.776 + jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s", 1.777 + (Klass::cast(recv_klass()))->external_name(), 1.778 + (Klass::cast(resolved_klass()))->external_name()); 1.779 + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 1.780 + } 1.781 + // do lookup based on receiver klass 1.782 + methodHandle sel_method; 1.783 + lookup_instance_method_in_klasses(sel_method, recv_klass, 1.784 + symbolHandle(THREAD, resolved_method->name()), 1.785 + symbolHandle(THREAD, resolved_method->signature()), CHECK); 1.786 + // check if method exists 1.787 + if (sel_method.is_null()) { 1.788 + ResourceMark rm(THREAD); 1.789 + THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), 1.790 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(recv_klass()), 1.791 + resolved_method->name(), 1.792 + resolved_method->signature())); 1.793 + } 1.794 + // check if public 1.795 + if (!sel_method->is_public()) { 1.796 + ResourceMark rm(THREAD); 1.797 + THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), 1.798 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(recv_klass()), 1.799 + sel_method->name(), 1.800 + sel_method->signature())); 1.801 + } 1.802 + // check if abstract 1.803 + if (check_null_and_abstract && sel_method->is_abstract()) { 1.804 + ResourceMark rm(THREAD); 1.805 + THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), 1.806 + methodOopDesc::name_and_sig_as_C_string(Klass::cast(recv_klass()), 1.807 + sel_method->name(), 1.808 + sel_method->signature())); 1.809 + } 1.810 + // setup result 1.811 + result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, CHECK); 1.812 +} 1.813 + 1.814 + 1.815 +methodHandle LinkResolver::linktime_resolve_interface_method_or_null( 1.816 + KlassHandle resolved_klass, 1.817 + symbolHandle method_name, 1.818 + symbolHandle method_signature, 1.819 + KlassHandle current_klass, 1.820 + bool check_access) { 1.821 + EXCEPTION_MARK; 1.822 + methodHandle method_result; 1.823 + linktime_resolve_interface_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD); 1.824 + if (HAS_PENDING_EXCEPTION) { 1.825 + CLEAR_PENDING_EXCEPTION; 1.826 + return methodHandle(); 1.827 + } else { 1.828 + return method_result; 1.829 + } 1.830 +} 1.831 + 1.832 +methodHandle LinkResolver::linktime_resolve_virtual_method_or_null( 1.833 + KlassHandle resolved_klass, 1.834 + symbolHandle method_name, 1.835 + symbolHandle method_signature, 1.836 + KlassHandle current_klass, 1.837 + bool check_access) { 1.838 + EXCEPTION_MARK; 1.839 + methodHandle method_result; 1.840 + linktime_resolve_virtual_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD); 1.841 + if (HAS_PENDING_EXCEPTION) { 1.842 + CLEAR_PENDING_EXCEPTION; 1.843 + return methodHandle(); 1.844 + } else { 1.845 + return method_result; 1.846 + } 1.847 +} 1.848 + 1.849 +methodHandle LinkResolver::resolve_virtual_call_or_null( 1.850 + KlassHandle receiver_klass, 1.851 + KlassHandle resolved_klass, 1.852 + symbolHandle name, 1.853 + symbolHandle signature, 1.854 + KlassHandle current_klass) { 1.855 + EXCEPTION_MARK; 1.856 + CallInfo info; 1.857 + resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD); 1.858 + if (HAS_PENDING_EXCEPTION) { 1.859 + CLEAR_PENDING_EXCEPTION; 1.860 + return methodHandle(); 1.861 + } 1.862 + return info.selected_method(); 1.863 +} 1.864 + 1.865 +methodHandle LinkResolver::resolve_interface_call_or_null( 1.866 + KlassHandle receiver_klass, 1.867 + KlassHandle resolved_klass, 1.868 + symbolHandle name, 1.869 + symbolHandle signature, 1.870 + KlassHandle current_klass) { 1.871 + EXCEPTION_MARK; 1.872 + CallInfo info; 1.873 + resolve_interface_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD); 1.874 + if (HAS_PENDING_EXCEPTION) { 1.875 + CLEAR_PENDING_EXCEPTION; 1.876 + return methodHandle(); 1.877 + } 1.878 + return info.selected_method(); 1.879 +} 1.880 + 1.881 +int LinkResolver::resolve_virtual_vtable_index( 1.882 + KlassHandle receiver_klass, 1.883 + KlassHandle resolved_klass, 1.884 + symbolHandle name, 1.885 + symbolHandle signature, 1.886 + KlassHandle current_klass) { 1.887 + EXCEPTION_MARK; 1.888 + CallInfo info; 1.889 + resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD); 1.890 + if (HAS_PENDING_EXCEPTION) { 1.891 + CLEAR_PENDING_EXCEPTION; 1.892 + return methodOopDesc::invalid_vtable_index; 1.893 + } 1.894 + return info.vtable_index(); 1.895 +} 1.896 + 1.897 +methodHandle LinkResolver::resolve_static_call_or_null( 1.898 + KlassHandle resolved_klass, 1.899 + symbolHandle name, 1.900 + symbolHandle signature, 1.901 + KlassHandle current_klass) { 1.902 + EXCEPTION_MARK; 1.903 + CallInfo info; 1.904 + resolve_static_call(info, resolved_klass, name, signature, current_klass, true, false, THREAD); 1.905 + if (HAS_PENDING_EXCEPTION) { 1.906 + CLEAR_PENDING_EXCEPTION; 1.907 + return methodHandle(); 1.908 + } 1.909 + return info.selected_method(); 1.910 +} 1.911 + 1.912 +methodHandle LinkResolver::resolve_special_call_or_null(KlassHandle resolved_klass, symbolHandle name, symbolHandle signature, 1.913 + KlassHandle current_klass) { 1.914 + EXCEPTION_MARK; 1.915 + CallInfo info; 1.916 + resolve_special_call(info, resolved_klass, name, signature, current_klass, true, THREAD); 1.917 + if (HAS_PENDING_EXCEPTION) { 1.918 + CLEAR_PENDING_EXCEPTION; 1.919 + return methodHandle(); 1.920 + } 1.921 + return info.selected_method(); 1.922 +} 1.923 + 1.924 + 1.925 + 1.926 +//------------------------------------------------------------------------------------------------------------------------ 1.927 +// ConstantPool entries 1.928 + 1.929 +void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) { 1.930 + switch (byte) { 1.931 + case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break; 1.932 + case Bytecodes::_invokespecial : resolve_invokespecial (result, pool, index, CHECK); break; 1.933 + case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, CHECK); break; 1.934 + case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break; 1.935 + } 1.936 + return; 1.937 +} 1.938 + 1.939 +void LinkResolver::resolve_pool(KlassHandle& resolved_klass, symbolHandle& method_name, symbolHandle& method_signature, 1.940 + KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS) { 1.941 + // resolve klass 1.942 + resolve_klass(resolved_klass, pool, index, CHECK); 1.943 + 1.944 + // Get name, signature, and static klass 1.945 + method_name = symbolHandle(THREAD, pool->name_ref_at(index)); 1.946 + method_signature = symbolHandle(THREAD, pool->signature_ref_at(index)); 1.947 + current_klass = KlassHandle(THREAD, pool->pool_holder()); 1.948 +} 1.949 + 1.950 + 1.951 +void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { 1.952 + KlassHandle resolved_klass; 1.953 + symbolHandle method_name; 1.954 + symbolHandle method_signature; 1.955 + KlassHandle current_klass; 1.956 + resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); 1.957 + resolve_static_call(result, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); 1.958 +} 1.959 + 1.960 + 1.961 +void LinkResolver::resolve_invokespecial(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { 1.962 + KlassHandle resolved_klass; 1.963 + symbolHandle method_name; 1.964 + symbolHandle method_signature; 1.965 + KlassHandle current_klass; 1.966 + resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); 1.967 + resolve_special_call(result, resolved_klass, method_name, method_signature, current_klass, true, CHECK); 1.968 +} 1.969 + 1.970 + 1.971 +void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, 1.972 + constantPoolHandle pool, int index, 1.973 + TRAPS) { 1.974 + 1.975 + KlassHandle resolved_klass; 1.976 + symbolHandle method_name; 1.977 + symbolHandle method_signature; 1.978 + KlassHandle current_klass; 1.979 + resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); 1.980 + KlassHandle recvrKlass (THREAD, recv.is_null() ? (klassOop)NULL : recv->klass()); 1.981 + resolve_virtual_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); 1.982 +} 1.983 + 1.984 + 1.985 +void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) { 1.986 + KlassHandle resolved_klass; 1.987 + symbolHandle method_name; 1.988 + symbolHandle method_signature; 1.989 + KlassHandle current_klass; 1.990 + resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); 1.991 + KlassHandle recvrKlass (THREAD, recv.is_null() ? (klassOop)NULL : recv->klass()); 1.992 + resolve_interface_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); 1.993 +} 1.994 + 1.995 +//------------------------------------------------------------------------------------------------------------------------ 1.996 +#ifndef PRODUCT 1.997 + 1.998 +void FieldAccessInfo::print() { 1.999 + ResourceMark rm; 1.1000 + tty->print_cr("Field %s@%d", name()->as_C_string(), field_offset()); 1.1001 +} 1.1002 + 1.1003 +#endif