methodHandles.hpp revision 7877:cc8363b030d5
1/*
2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#ifndef SHARE_VM_PRIMS_METHODHANDLES_HPP
26#define SHARE_VM_PRIMS_METHODHANDLES_HPP
27
28#include "classfile/javaClasses.hpp"
29#include "classfile/vmSymbols.hpp"
30#include "runtime/frame.inline.hpp"
31#include "runtime/globals.hpp"
32#include "runtime/interfaceSupport.hpp"
33
34class MacroAssembler;
35class Label;
36
37class MethodHandles: AllStatic {
38  // JVM support for MethodHandle, MethodType, and related types
39  // in java.lang.invoke and sun.invoke.
40  // See also  javaClasses for layouts java_lang_invoke_Method{Handle,Type,Type::Form}.
41 public:
42 public:
43  static bool enabled()                         { return _enabled; }
44  static void set_enabled(bool z);
45
46 private:
47  static bool _enabled;
48
49  // Adapters.
50  static MethodHandlesAdapterBlob* _adapter_code;
51
52  // utility functions for reifying names and types
53  static oop field_name_or_null(Symbol* s);
54  static oop field_signature_type_or_null(Symbol* s);
55
56 public:
57  // working with member names
58  static Handle resolve_MemberName(Handle mname, KlassHandle caller, TRAPS); // compute vmtarget/vmindex from name/type
59  static void expand_MemberName(Handle mname, int suppress, TRAPS);  // expand defc/name/type if missing
60  static Handle new_MemberName(TRAPS);  // must be followed by init_MemberName
61  static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target
62  static oop init_field_MemberName(Handle mname_h, fieldDescriptor& fd, bool is_setter = false);
63  static oop init_method_MemberName(Handle mname_h, CallInfo& info);
64  static int method_ref_kind(Method* m, bool do_dispatch_if_possible = true);
65  static int find_MemberNames(KlassHandle k, Symbol* name, Symbol* sig,
66                              int mflags, KlassHandle caller,
67                              int skip, objArrayHandle results);
68  // bit values for suppress argument to expand_MemberName:
69  enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
70
71  // Generate MethodHandles adapters.
72  static bool generate_adapters();
73
74  // Called from MethodHandlesAdapterGenerator.
75  static address generate_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid);
76  static void generate_method_handle_dispatch(MacroAssembler* _masm,
77                                              vmIntrinsics::ID iid,
78                                              Register receiver_reg,
79                                              Register member_reg,
80                                              bool for_compiler_entry);
81
82  // Queries
83  static bool is_signature_polymorphic(vmIntrinsics::ID iid) {
84    return (iid >= vmIntrinsics::FIRST_MH_SIG_POLY &&
85            iid <= vmIntrinsics::LAST_MH_SIG_POLY);
86  }
87
88  static bool is_signature_polymorphic_intrinsic(vmIntrinsics::ID iid) {
89    assert(is_signature_polymorphic(iid), "");
90    // Most sig-poly methods are intrinsics which do not require an
91    // appeal to Java for adapter code.
92    return (iid != vmIntrinsics::_invokeGeneric);
93  }
94
95  static bool is_signature_polymorphic_static(vmIntrinsics::ID iid) {
96    assert(is_signature_polymorphic(iid), "");
97    return (iid >= vmIntrinsics::FIRST_MH_STATIC &&
98            iid <= vmIntrinsics::LAST_MH_SIG_POLY);
99  }
100
101  static bool has_member_arg(vmIntrinsics::ID iid) {
102    assert(is_signature_polymorphic(iid), "");
103    return (iid >= vmIntrinsics::_linkToVirtual &&
104            iid <= vmIntrinsics::_linkToInterface);
105  }
106  static bool has_member_arg(Symbol* klass, Symbol* name) {
107    if ((klass == vmSymbols::java_lang_invoke_MethodHandle()) &&
108        is_signature_polymorphic_name(name)) {
109      vmIntrinsics::ID iid = signature_polymorphic_name_id(name);
110      return has_member_arg(iid);
111    }
112    return false;
113  }
114
115  static Symbol* signature_polymorphic_intrinsic_name(vmIntrinsics::ID iid);
116  static int signature_polymorphic_intrinsic_ref_kind(vmIntrinsics::ID iid);
117
118  static vmIntrinsics::ID signature_polymorphic_name_id(Klass* klass, Symbol* name);
119  static vmIntrinsics::ID signature_polymorphic_name_id(Symbol* name);
120  static bool is_signature_polymorphic_name(Symbol* name) {
121    return signature_polymorphic_name_id(name) != vmIntrinsics::_none;
122  }
123  static bool is_method_handle_invoke_name(Klass* klass, Symbol* name);
124  static bool is_signature_polymorphic_name(Klass* klass, Symbol* name) {
125    return signature_polymorphic_name_id(klass, name) != vmIntrinsics::_none;
126  }
127
128  enum {
129    // format of query to getConstant:
130    GC_COUNT_GWT = 4,
131    GC_LAMBDA_SUPPORT = 5
132  };
133  static int get_named_constant(int which, Handle name_box, TRAPS);
134
135public:
136  static Symbol* lookup_signature(oop type_str, bool polymorphic, TRAPS);  // use TempNewSymbol
137  static Symbol* lookup_basic_type_signature(Symbol* sig, bool keep_last_arg, TRAPS);  // use TempNewSymbol
138  static Symbol* lookup_basic_type_signature(Symbol* sig, TRAPS) {
139    return lookup_basic_type_signature(sig, false, THREAD);
140  }
141  static bool is_basic_type_signature(Symbol* sig);
142
143  static Symbol* lookup_method_type(Symbol* msig, Handle mtype, TRAPS);
144
145  static void print_as_method_type_on(outputStream* st, Symbol* sig) {
146    print_as_basic_type_signature_on(st, sig, true, true);
147  }
148  static void print_as_basic_type_signature_on(outputStream* st, Symbol* sig, bool keep_arrays = false, bool keep_basic_names = false);
149
150  // decoding CONSTANT_MethodHandle constants
151  enum { JVM_REF_MIN = JVM_REF_getField, JVM_REF_MAX = JVM_REF_invokeInterface };
152  static bool ref_kind_is_valid(int ref_kind) {
153    return (ref_kind >= JVM_REF_MIN && ref_kind <= JVM_REF_MAX);
154  }
155  static bool ref_kind_is_field(int ref_kind) {
156    assert(ref_kind_is_valid(ref_kind), "");
157    return (ref_kind <= JVM_REF_putStatic);
158  }
159  static bool ref_kind_is_getter(int ref_kind) {
160    assert(ref_kind_is_valid(ref_kind), "");
161    return (ref_kind <= JVM_REF_getStatic);
162  }
163  static bool ref_kind_is_setter(int ref_kind) {
164    return ref_kind_is_field(ref_kind) && !ref_kind_is_getter(ref_kind);
165  }
166  static bool ref_kind_is_method(int ref_kind) {
167    return !ref_kind_is_field(ref_kind) && (ref_kind != JVM_REF_newInvokeSpecial);
168  }
169  static bool ref_kind_has_receiver(int ref_kind) {
170    assert(ref_kind_is_valid(ref_kind), "");
171    return (ref_kind & 1) != 0;
172  }
173  static bool ref_kind_is_static(int ref_kind) {
174    return !ref_kind_has_receiver(ref_kind) && (ref_kind != JVM_REF_newInvokeSpecial);
175  }
176  static bool ref_kind_does_dispatch(int ref_kind) {
177    return (ref_kind == JVM_REF_invokeVirtual ||
178            ref_kind == JVM_REF_invokeInterface);
179  }
180
181
182#ifdef TARGET_ARCH_x86
183# include "methodHandles_x86.hpp"
184#endif
185#ifdef TARGET_ARCH_sparc
186# include "methodHandles_sparc.hpp"
187#endif
188#ifdef TARGET_ARCH_zero
189# include "methodHandles_zero.hpp"
190#endif
191#ifdef TARGET_ARCH_arm
192# include "methodHandles_arm.hpp"
193#endif
194#ifdef TARGET_ARCH_ppc
195# include "methodHandles_ppc.hpp"
196#endif
197#ifdef TARGET_ARCH_aarch64
198# include "methodHandles_aarch64.hpp"
199#endif
200
201  // Tracing
202  static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
203  static void trace_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid) {
204    if (TraceMethodHandles) {
205      const char* name = vmIntrinsics::name_at(iid);
206      if (*name == '_')  name += 1;
207      const size_t len = strlen(name) + 50;
208      char* qname = NEW_C_HEAP_ARRAY(char, len, mtInternal);
209      const char* suffix = "";
210      if (is_signature_polymorphic(iid)) {
211        if (is_signature_polymorphic_static(iid))
212          suffix = "/static";
213        else
214          suffix = "/private";
215      }
216      jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix);
217      trace_method_handle(_masm, qname);
218      // Note:  Don't free the allocated char array because it's used
219      // during runtime.
220    }
221  }
222};
223
224//------------------------------------------------------------------------------
225// MethodHandlesAdapterGenerator
226//
227class MethodHandlesAdapterGenerator : public StubCodeGenerator {
228public:
229  MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code, PrintMethodHandleStubs) {}
230
231  void generate();
232};
233
234//------------------------------------------------------------------------------
235// MemberNameTable
236//
237
238class MemberNameTable : public GrowableArray<jweak> {
239 public:
240  MemberNameTable(int methods_cnt);
241  ~MemberNameTable();
242  void add_member_name(int index, jweak mem_name_ref);
243  oop  get_member_name(int index);
244
245#if INCLUDE_JVMTI
246 public:
247  // RedefineClasses() API support:
248  // If a MemberName refers to old_method then update it
249  // to refer to new_method.
250  void adjust_method_entries(Method** old_methods, Method** new_methods,
251                             int methods_length, bool *trace_name_printed);
252 private:
253  oop find_member_name_by_method(Method* old_method);
254#endif // INCLUDE_JVMTI
255};
256
257#endif // SHARE_VM_PRIMS_METHODHANDLES_HPP
258