--- a/hotspot/src/share/vm/oops/methodOop.cpp Wed Apr 08 00:12:59 2009 -0700
+++ b/hotspot/src/share/vm/oops/methodOop.cpp Wed Apr 08 10:56:49 2009 -0700
@@ -304,6 +304,12 @@
}
+int methodOopDesc::extra_stack_words() {
+ // not an inline function, to avoid a header dependency on Interpreter
+ return extra_stack_entries() * Interpreter::stackElementSize();
+}
+
+
void methodOopDesc::compute_size_of_parameters(Thread *thread) {
symbolHandle h_signature(thread, signature());
ArgumentSizeComputer asc(h_signature);
@@ -564,6 +570,11 @@
bool methodOopDesc::is_not_compilable(int comp_level) const {
+ if (is_method_handle_invoke()) {
+ // compilers must recognize this method specially, or not at all
+ return true;
+ }
+
methodDataOop mdo = method_data();
if (mdo != NULL
&& (uint)mdo->decompile_count() > (uint)PerMethodRecompilationCutoff) {
@@ -651,7 +662,7 @@
assert(entry != NULL, "interpreter entry must be non-null");
// Sets both _i2i_entry and _from_interpreted_entry
set_interpreter_entry(entry);
- if (is_native()) {
+ if (is_native() && !is_method_handle_invoke()) {
set_native_function(
SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
!native_bind_event_is_interesting);
@@ -783,6 +794,100 @@
return false;
}
+// Constant pool structure for invoke methods:
+enum {
+ _imcp_invoke_name = 1, // utf8: 'invoke'
+ _imcp_invoke_signature, // utf8: (variable symbolOop)
+ _imcp_method_type_value, // string: (variable java/dyn/MethodType, sic)
+ _imcp_limit
+};
+
+oop methodOopDesc::method_handle_type() const {
+ if (!is_method_handle_invoke()) { assert(false, "caller resp."); return NULL; }
+ oop mt = constants()->resolved_string_at(_imcp_method_type_value);
+ assert(mt->klass() == SystemDictionary::MethodType_klass(), "");
+ return mt;
+}
+
+jint* methodOopDesc::method_type_offsets_chain() {
+ static jint pchase[] = { -1, -1, -1 };
+ if (pchase[0] == -1) {
+ jint step0 = in_bytes(constants_offset());
+ jint step1 = (constantPoolOopDesc::header_size() + _imcp_method_type_value) * HeapWordSize;
+ // do this in reverse to avoid races:
+ OrderAccess::release_store(&pchase[1], step1);
+ OrderAccess::release_store(&pchase[0], step0);
+ }
+ return pchase;
+}
+
+methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
+ symbolHandle signature,
+ Handle method_type, TRAPS) {
+ methodHandle empty;
+
+ assert(holder() == SystemDictionary::MethodHandle_klass(),
+ "must be a JSR 292 magic type");
+
+ if (TraceMethodHandles) {
+ tty->print("Creating invoke method for ");
+ signature->print_value();
+ tty->cr();
+ }
+
+ constantPoolHandle cp;
+ {
+ constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty));
+ cp = constantPoolHandle(THREAD, cp_oop);
+ }
+ cp->symbol_at_put(_imcp_invoke_name, vmSymbols::invoke_name());
+ cp->symbol_at_put(_imcp_invoke_signature, signature());
+ cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature());
+ cp->set_pool_holder(holder());
+
+ // set up the fancy stuff:
+ cp->pseudo_string_at_put(_imcp_method_type_value, method_type());
+ methodHandle m;
+ {
+ int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL);
+ methodOop m_oop = oopFactory::new_method(0, accessFlags_from(flags_bits),
+ 0, 0, 0, IsSafeConc, CHECK_(empty));
+ m = methodHandle(THREAD, m_oop);
+ }
+ m->set_constants(cp());
+ m->set_name_index(_imcp_invoke_name);
+ m->set_signature_index(_imcp_invoke_signature);
+ assert(m->name() == vmSymbols::invoke_name(), "");
+ assert(m->signature() == signature(), "");
+#ifdef CC_INTERP
+ ResultTypeFinder rtf(signature());
+ m->set_result_index(rtf.type());
+#endif
+ m->compute_size_of_parameters(THREAD);
+ m->set_exception_table(Universe::the_empty_int_array());
+
+ // Finally, set up its entry points.
+ assert(m->method_handle_type() == method_type(), "");
+ assert(m->can_be_statically_bound(), "");
+ m->set_vtable_index(methodOopDesc::nonvirtual_vtable_index);
+ m->link_method(m, CHECK_(empty));
+
+#ifdef ASSERT
+ // Make sure the pointer chase works.
+ address p = (address) m();
+ for (jint* pchase = method_type_offsets_chain(); (*pchase) != -1; pchase++) {
+ p = *(address*)(p + (*pchase));
+ }
+ assert((oop)p == method_type(), "pointer chase is correct");
+#endif
+
+ if (TraceMethodHandles)
+ m->print_on(tty);
+
+ return m;
+}
+
+
methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) {