Mercurial > hg > graal-jvmci-8
diff src/share/vm/classfile/javaClasses.cpp @ 710:e5b0439ef4ae
6655638: dynamic languages need method handles
Summary: initial implementation, with known omissions (x86/64, sparc, compiler optim., c-oops, C++ interp.)
Reviewed-by: kvn, twisti, never
author | jrose |
---|---|
date | Wed, 08 Apr 2009 10:56:49 -0700 |
parents | c89f86385056 |
children | be93aad57795 |
line wrap: on
line diff
--- a/src/share/vm/classfile/javaClasses.cpp Wed Apr 08 00:12:59 2009 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Wed Apr 08 10:56:49 2009 -0700 @@ -25,13 +25,24 @@ # include "incls/_precompiled.incl" # include "incls/_javaClasses.cpp.incl" +static bool find_field(instanceKlass* ik, + symbolOop name_symbol, symbolOop signature_symbol, + fieldDescriptor* fd, + bool allow_super = false) { + if (allow_super) + return ik->find_field(name_symbol, signature_symbol, fd) != NULL; + else + return ik->find_local_field(name_symbol, signature_symbol, fd); +} + // Helpful routine for computing field offsets at run time rather than hardcoding them static void compute_offset(int &dest_offset, - klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) { + klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol, + bool allow_super = false) { fieldDescriptor fd; instanceKlass* ik = instanceKlass::cast(klass_oop); - if (!ik->find_local_field(name_symbol, signature_symbol, &fd)) { + if (!find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) { ResourceMark rm; tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); fatal("Invalid layout of preloaded class"); @@ -42,14 +53,16 @@ // Same as above but for "optional" offsets that might not be present in certain JDK versions static void compute_optional_offset(int& dest_offset, - klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) { + klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol, + bool allow_super = false) { fieldDescriptor fd; instanceKlass* ik = instanceKlass::cast(klass_oop); - if (ik->find_local_field(name_symbol, signature_symbol, &fd)) { + if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) { dest_offset = fd.offset(); } } + Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) { // Create the String object first, so there's a chance that the String // and the char array it points to end up in the same cache line. @@ -2107,13 +2120,324 @@ } +// Support for java_dyn_MethodHandle + +int java_dyn_MethodHandle::_type_offset; +int java_dyn_MethodHandle::_vmtarget_offset; +int java_dyn_MethodHandle::_vmentry_offset; +int java_dyn_MethodHandle::_vmslots_offset; + +int sun_dyn_MemberName::_clazz_offset; +int sun_dyn_MemberName::_name_offset; +int sun_dyn_MemberName::_type_offset; +int sun_dyn_MemberName::_flags_offset; +int sun_dyn_MemberName::_vmtarget_offset; +int sun_dyn_MemberName::_vmindex_offset; + +int sun_dyn_DirectMethodHandle::_vmindex_offset; + +int sun_dyn_BoundMethodHandle::_argument_offset; +int sun_dyn_BoundMethodHandle::_vmargslot_offset; + +int sun_dyn_AdapterMethodHandle::_conversion_offset; + +void java_dyn_MethodHandle::compute_offsets() { + klassOop k = SystemDictionary::MethodHandle_klass(); + if (k != NULL && EnableMethodHandles) { + compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true); + compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), true); + compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), true); + + // Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots. + // It is optional pending experiments to keep or toss. + compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true); + } +} + +void sun_dyn_MemberName::compute_offsets() { + klassOop k = SystemDictionary::MemberName_klass(); + if (k != NULL && EnableMethodHandles) { + compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); + compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); + compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature()); + compute_offset(_flags_offset, k, vmSymbols::flags_name(), vmSymbols::int_signature()); + compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature()); + compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature()); + } +} + +void sun_dyn_DirectMethodHandle::compute_offsets() { + klassOop k = SystemDictionary::DirectMethodHandle_klass(); + if (k != NULL && EnableMethodHandles) { + compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true); + } +} + +void sun_dyn_BoundMethodHandle::compute_offsets() { + klassOop k = SystemDictionary::BoundMethodHandle_klass(); + if (k != NULL && EnableMethodHandles) { + compute_offset(_vmargslot_offset, k, vmSymbols::vmargslot_name(), vmSymbols::int_signature(), true); + compute_offset(_argument_offset, k, vmSymbols::argument_name(), vmSymbols::object_signature(), true); + } +} + +void sun_dyn_AdapterMethodHandle::compute_offsets() { + klassOop k = SystemDictionary::AdapterMethodHandle_klass(); + if (k != NULL && EnableMethodHandles) { + compute_offset(_conversion_offset, k, vmSymbols::conversion_name(), vmSymbols::int_signature(), true); + } +} + +oop java_dyn_MethodHandle::type(oop mh) { + return mh->obj_field(_type_offset); +} + +void java_dyn_MethodHandle::set_type(oop mh, oop mtype) { + mh->obj_field_put(_type_offset, mtype); +} + +int java_dyn_MethodHandle::vmslots(oop mh) { + int vmslots_offset = _vmslots_offset; + if (vmslots_offset != 0) { +#ifdef ASSERT + int x = mh->int_field(vmslots_offset); + int y = compute_vmslots(mh); + assert(x == y, "correct hoisted value"); +#endif + return mh->int_field(vmslots_offset); + } else { + return compute_vmslots(mh); + } +} + +// if MH.vmslots exists, hoist into it the value of type.form.vmslots +void java_dyn_MethodHandle::init_vmslots(oop mh) { + int vmslots_offset = _vmslots_offset; + if (vmslots_offset != 0) { + mh->int_field_put(vmslots_offset, compute_vmslots(mh)); + } +} + +// fetch type.form.vmslots, which is the number of JVM stack slots +// required to carry the arguments of this MH +int java_dyn_MethodHandle::compute_vmslots(oop mh) { + oop mtype = type(mh); + if (mtype == NULL) return 0; // Java code would get NPE + oop form = java_dyn_MethodType::form(mtype); + if (form == NULL) return 0; // Java code would get NPE + return java_dyn_MethodTypeForm::vmslots(form); +} + +// fetch the low-level entry point for this mh +MethodHandleEntry* java_dyn_MethodHandle::vmentry(oop mh) { + return (MethodHandleEntry*) mh->address_field(_vmentry_offset); +} + +void java_dyn_MethodHandle::set_vmentry(oop mh, MethodHandleEntry* me) { + assert(_vmentry_offset != 0, "must be present"); + + // This is always the final step that initializes a valid method handle: + mh->release_address_field_put(_vmentry_offset, (address) me); + + // There should be enough memory barriers on exit from native methods + // to ensure that the MH is fully initialized to all threads before + // Java code can publish it in global data structures. + // But just in case, we use release_address_field_put. +} + +/// MemberName accessors + +oop sun_dyn_MemberName::clazz(oop mname) { + assert(is_instance(mname), "wrong type"); + return mname->obj_field(_clazz_offset); +} + +void sun_dyn_MemberName::set_clazz(oop mname, oop clazz) { + assert(is_instance(mname), "wrong type"); + mname->obj_field_put(_clazz_offset, clazz); +} + +oop sun_dyn_MemberName::name(oop mname) { + assert(is_instance(mname), "wrong type"); + return mname->obj_field(_name_offset); +} + +void sun_dyn_MemberName::set_name(oop mname, oop name) { + assert(is_instance(mname), "wrong type"); + mname->obj_field_put(_name_offset, name); +} + +oop sun_dyn_MemberName::type(oop mname) { + assert(is_instance(mname), "wrong type"); + return mname->obj_field(_type_offset); +} + +void sun_dyn_MemberName::set_type(oop mname, oop type) { + assert(is_instance(mname), "wrong type"); + mname->obj_field_put(_type_offset, type); +} + +int sun_dyn_MemberName::flags(oop mname) { + assert(is_instance(mname), "wrong type"); + return mname->int_field(_flags_offset); +} + +void sun_dyn_MemberName::set_flags(oop mname, int flags) { + assert(is_instance(mname), "wrong type"); + mname->int_field_put(_flags_offset, flags); +} + +oop sun_dyn_MemberName::vmtarget(oop mname) { + assert(is_instance(mname), "wrong type"); + return mname->obj_field(_vmtarget_offset); +} + +void sun_dyn_MemberName::set_vmtarget(oop mname, oop ref) { + assert(is_instance(mname), "wrong type"); + mname->obj_field_put(_vmtarget_offset, ref); +} + +int sun_dyn_MemberName::vmindex(oop mname) { + assert(is_instance(mname), "wrong type"); + return mname->int_field(_vmindex_offset); +} + +void sun_dyn_MemberName::set_vmindex(oop mname, int index) { + assert(is_instance(mname), "wrong type"); + mname->int_field_put(_vmindex_offset, index); +} + +oop java_dyn_MethodHandle::vmtarget(oop mh) { + assert(is_instance(mh), "MH only"); + return mh->obj_field(_vmtarget_offset); +} + +void java_dyn_MethodHandle::set_vmtarget(oop mh, oop ref) { + assert(is_instance(mh), "MH only"); + mh->obj_field_put(_vmtarget_offset, ref); +} + +int sun_dyn_DirectMethodHandle::vmindex(oop mh) { + assert(is_instance(mh), "DMH only"); + return mh->int_field(_vmindex_offset); +} + +void sun_dyn_DirectMethodHandle::set_vmindex(oop mh, int index) { + assert(is_instance(mh), "DMH only"); + mh->int_field_put(_vmindex_offset, index); +} + +int sun_dyn_BoundMethodHandle::vmargslot(oop mh) { + assert(is_instance(mh), "BMH only"); + return mh->int_field(_vmargslot_offset); +} + +oop sun_dyn_BoundMethodHandle::argument(oop mh) { + assert(is_instance(mh), "BMH only"); + return mh->obj_field(_argument_offset); +} + +int sun_dyn_AdapterMethodHandle::conversion(oop mh) { + assert(is_instance(mh), "AMH only"); + return mh->int_field(_conversion_offset); +} + +void sun_dyn_AdapterMethodHandle::set_conversion(oop mh, int conv) { + assert(is_instance(mh), "AMH only"); + mh->int_field_put(_conversion_offset, conv); +} + + +// Support for java_dyn_MethodType + +int java_dyn_MethodType::_rtype_offset; +int java_dyn_MethodType::_ptypes_offset; +int java_dyn_MethodType::_form_offset; + +void java_dyn_MethodType::compute_offsets() { + klassOop k = SystemDictionary::MethodType_klass(); + if (k != NULL) { + compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature()); + compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature()); + compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_dyn_MethodTypeForm_signature()); + } +} + +void java_dyn_MethodType::print_signature(oop mt, outputStream* st) { + st->print("("); + objArrayOop pts = ptypes(mt); + for (int i = 0, limit = pts->length(); i < limit; i++) { + java_lang_Class::print_signature(pts->obj_at(i), st); + } + st->print(")"); + java_lang_Class::print_signature(rtype(mt), st); +} + +symbolOop java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) { + ResourceMark rm; + stringStream buffer(128); + print_signature(mt, &buffer); + const char* sigstr = buffer.base(); + int siglen = (int) buffer.size(); + if (!intern_if_not_found) + return SymbolTable::probe(sigstr, siglen); + else + return oopFactory::new_symbol(sigstr, siglen, THREAD); +} + +oop java_dyn_MethodType::rtype(oop mt) { + assert(is_instance(mt), "must be a MethodType"); + return mt->obj_field(_rtype_offset); +} + +objArrayOop java_dyn_MethodType::ptypes(oop mt) { + assert(is_instance(mt), "must be a MethodType"); + return (objArrayOop) mt->obj_field(_ptypes_offset); +} + +oop java_dyn_MethodType::form(oop mt) { + assert(is_instance(mt), "must be a MethodType"); + return mt->obj_field(_form_offset); +} + +oop java_dyn_MethodType::ptype(oop mt, int idx) { + return ptypes(mt)->obj_at(idx); +} + + + +// Support for java_dyn_MethodTypeForm + +int java_dyn_MethodTypeForm::_vmslots_offset; +int java_dyn_MethodTypeForm::_erasedType_offset; + +void java_dyn_MethodTypeForm::compute_offsets() { + klassOop k = SystemDictionary::MethodTypeForm_klass(); + if (k != NULL) { + compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true); + compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_dyn_MethodType_signature(), true); + } +} + +int java_dyn_MethodTypeForm::vmslots(oop mtform) { + assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); + return mtform->int_field(_vmslots_offset); +} + +oop java_dyn_MethodTypeForm::erasedType(oop mtform) { + assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); + return mtform->obj_field(_erasedType_offset); +} + + + + // Support for java_security_AccessControlContext int java_security_AccessControlContext::_context_offset = 0; int java_security_AccessControlContext::_privilegedContext_offset = 0; int java_security_AccessControlContext::_isPrivileged_offset = 0; - void java_security_AccessControlContext::compute_offsets() { assert(_isPrivileged_offset == 0, "offsets should be initialized only once"); fieldDescriptor fd; @@ -2442,6 +2766,15 @@ java_lang_System::compute_offsets(); java_lang_Thread::compute_offsets(); java_lang_ThreadGroup::compute_offsets(); + if (EnableMethodHandles) { + java_dyn_MethodHandle::compute_offsets(); + sun_dyn_MemberName::compute_offsets(); + sun_dyn_DirectMethodHandle::compute_offsets(); + sun_dyn_BoundMethodHandle::compute_offsets(); + sun_dyn_AdapterMethodHandle::compute_offsets(); + java_dyn_MethodType::compute_offsets(); + java_dyn_MethodTypeForm::compute_offsets(); + } java_security_AccessControlContext::compute_offsets(); // Initialize reflection classes. The layouts of these classes // changed with the new reflection implementation in JDK 1.4, and @@ -2459,6 +2792,9 @@ sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets(); } sun_misc_AtomicLongCSImpl::compute_offsets(); + + // generated interpreter code wants to know about the offsets we just computed: + AbstractAssembler::update_delayed_values(); } #ifndef PRODUCT