History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/lang/invoke/MethodHandleNatives.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/lang/invoke/MethodHandleNatives.java+403−0
@@ -0,0 +1,403 @@
1+/*
2+ * Copyright (c) 2008, 2011, 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. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package java.lang.invoke;
27+
28+import java.lang.invoke.MethodHandles.Lookup;
29+import java.lang.reflect.AccessibleObject;
30+import java.lang.reflect.Field;
31+import static java.lang.invoke.MethodHandleNatives.Constants.*;
32+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
33+
34+/**
35+ * The JVM interface for the method handles package is all here.
36+ * This is an interface internal and private to an implemetantion of JSR 292.
37+ * <em>This class is not part of the JSR 292 standard.</em>
38+ * @author jrose
39+ */
40+class MethodHandleNatives {
41+
42+ private MethodHandleNatives() { } // static only
43+
44+ /// MethodName support
45+
46+ static native void init(MemberName self, Object ref);
47+ static native void expand(MemberName self);
48+ static native void resolve(MemberName self, Class<?> caller);
49+ static native int getMembers(Class<?> defc, String matchName, String matchSig,
50+ int matchFlags, Class<?> caller, int skip, MemberName[] results);
51+
52+ /// MethodHandle support
53+
54+ /** Initialize the method handle to adapt the call. */
55+ static native void init(AdapterMethodHandle self, MethodHandle target, int argnum);
56+ /** Initialize the method handle to call the correct method, directly. */
57+ static native void init(BoundMethodHandle self, Object target, int argnum);
58+ /** Initialize the method handle to call as if by an invoke* instruction. */
59+ static native void init(DirectMethodHandle self, Object ref, boolean doDispatch, Class<?> caller);
60+
61+ /** Initialize a method type, once per form. */
62+ static native void init(MethodType self);
63+
64+ /** Tell the JVM about a class's bootstrap method. */
65+ static native void registerBootstrap(Class<?> caller, MethodHandle bootstrapMethod);
66+
67+ /** Ask the JVM about a class's bootstrap method. */
68+ static native MethodHandle getBootstrap(Class<?> caller);
69+
70+ /** Tell the JVM that we need to change the target of an invokedynamic. */
71+ static native void setCallSiteTarget(CallSite site, MethodHandle target);
72+
73+ /** Fetch the vmtarget field.
74+ * It will be sanitized as necessary to avoid exposing non-Java references.
75+ * This routine is for debugging and reflection.
76+ */
77+ static native Object getTarget(MethodHandle self, int format);
78+
79+ /** Fetch the name of the handled method, if available.
80+ * This routine is for debugging and reflection.
81+ */
82+ static MemberName getMethodName(MethodHandle self) {
83+ return (MemberName) getTarget(self, ETF_METHOD_NAME);
84+ }
85+
86+ /** Fetch the reflective version of the handled method, if available.
87+ */
88+ static AccessibleObject getTargetMethod(MethodHandle self) {
89+ return (AccessibleObject) getTarget(self, ETF_REFLECT_METHOD);
90+ }
91+
92+ /** Fetch the target of this method handle.
93+ * If it directly targets a method, return a MemberName for the method.
94+ * If it is chained to another method handle, return that handle.
95+ */
96+ static Object getTargetInfo(MethodHandle self) {
97+ return getTarget(self, ETF_HANDLE_OR_METHOD_NAME);
98+ }
99+
100+ static Object[] makeTarget(Class<?> defc, String name, String sig, int mods, Class<?> refc) {
101+ return new Object[] { defc, name, sig, mods, refc };
102+ }
103+
104+ /** Fetch MH-related JVM parameter.
105+ * which=0 retrieves MethodHandlePushLimit
106+ * which=1 retrieves stack slot push size (in address units)
107+ */
108+ static native int getConstant(int which);
109+
110+ /** Java copy of MethodHandlePushLimit in range 2..255. */
111+ static final int JVM_PUSH_LIMIT;
112+ /** JVM stack motion (in words) after one slot is pushed, usually -1.
113+ */
114+ static final int JVM_STACK_MOVE_UNIT;
115+
116+ /** Which conv-ops are implemented by the JVM? */
117+ static final int CONV_OP_IMPLEMENTED_MASK;
118+ /** Derived mode flag. Only false on some old JVM implementations. */
119+ static final boolean HAVE_RICOCHET_FRAMES;
120+
121+ static final int OP_ROT_ARGS_DOWN_LIMIT_BIAS;
122+
123+ private static native void registerNatives();
124+ static {
125+ registerNatives();
126+ int k;
127+ JVM_PUSH_LIMIT = getConstant(Constants.GC_JVM_PUSH_LIMIT);
128+ JVM_STACK_MOVE_UNIT = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT);
129+ k = getConstant(Constants.GC_CONV_OP_IMPLEMENTED_MASK);
130+ CONV_OP_IMPLEMENTED_MASK = (k != 0) ? k : DEFAULT_CONV_OP_IMPLEMENTED_MASK;
131+ k = getConstant(Constants.GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS);
132+ OP_ROT_ARGS_DOWN_LIMIT_BIAS = (k != 0) ? (byte)k : -1;
133+ HAVE_RICOCHET_FRAMES = (CONV_OP_IMPLEMENTED_MASK & (1<<OP_COLLECT_ARGS)) != 0;
134+ //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
135+ }
136+
137+ // All compile-time constants go here.
138+ // There is an opportunity to check them against the JVM's idea of them.
139+ static class Constants {
140+ Constants() { } // static only
141+ // MethodHandleImpl
142+ static final int // for getConstant
143+ GC_JVM_PUSH_LIMIT = 0,
144+ GC_JVM_STACK_MOVE_UNIT = 1,
145+ GC_CONV_OP_IMPLEMENTED_MASK = 2,
146+ GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS = 3;
147+ static final int
148+ ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
149+ ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self)
150+ ETF_METHOD_NAME = 2, // ultimate method as MemberName
151+ ETF_REFLECT_METHOD = 3; // ultimate method as java.lang.reflect object (sans refClass)
152+
153+ // MemberName
154+ // The JVM uses values of -2 and above for vtable indexes.
155+ // Field values are simple positive offsets.
156+ // Ref: src/share/vm/oops/methodOop.hpp
157+ // This value is negative enough to avoid such numbers,
158+ // but not too negative.
159+ static final int
160+ MN_IS_METHOD = 0x00010000, // method (not constructor)
161+ MN_IS_CONSTRUCTOR = 0x00020000, // constructor
162+ MN_IS_FIELD = 0x00040000, // field
163+ MN_IS_TYPE = 0x00080000, // nested type
164+ MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
165+ MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers
166+ VM_INDEX_UNINITIALIZED = -99;
167+
168+ // BoundMethodHandle
169+ /** Constants for decoding the vmargslot field, which contains 2 values. */
170+ static final int
171+ ARG_SLOT_PUSH_SHIFT = 16,
172+ ARG_SLOT_MASK = (1<<ARG_SLOT_PUSH_SHIFT)-1;
173+
174+ // AdapterMethodHandle
175+ /** Conversions recognized by the JVM.
176+ * They must align with the constants in java.lang.invoke.AdapterMethodHandle,
177+ * in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp.
178+ */
179+ static final int
180+ OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
181+ OP_RETYPE_RAW = 0x1, // straight retype, trusted (void->int, Object->T)
182+ OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument
183+ OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another
184+ OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive
185+ OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper
186+ OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg)
187+ OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg)
188+ OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS)
189+ OP_DROP_ARGS = 0x9, // remove one or more argument slots
190+ OP_COLLECT_ARGS = 0xA, // combine arguments using an auxiliary function
191+ OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size)
192+ OP_FOLD_ARGS = 0xC, // combine but do not remove arguments; prepend result
193+ //OP_UNUSED_13 = 0xD, // unused code, perhaps for reified argument lists
194+ CONV_OP_LIMIT = 0xE; // limit of CONV_OP enumeration
195+ /** Shift and mask values for decoding the AMH.conversion field.
196+ * These numbers are shared with the JVM for creating AMHs.
197+ */
198+ static final int
199+ CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
200+ CONV_TYPE_MASK = 0x0F, // fits T_ADDRESS and below
201+ CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
202+ CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK
203+ CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK
204+ CONV_DEST_TYPE_SHIFT = 12, // byte 2 has the adapter BasicType (if needed)
205+ CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed)
206+ CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
207+ CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1;
208+
209+ /** Which conv-ops are implemented by the JVM? */
210+ static final int DEFAULT_CONV_OP_IMPLEMENTED_MASK =
211+ // Value to use if the corresponding JVM query fails.
212+ ((1<<OP_RETYPE_ONLY)
213+ |(1<<OP_RETYPE_RAW)
214+ |(1<<OP_CHECK_CAST)
215+ |(1<<OP_PRIM_TO_PRIM)
216+ |(1<<OP_REF_TO_PRIM)
217+ |(1<<OP_SWAP_ARGS)
218+ |(1<<OP_ROT_ARGS)
219+ |(1<<OP_DUP_ARGS)
220+ |(1<<OP_DROP_ARGS)
221+ //|(1<<OP_SPREAD_ARGS)
222+ );
223+
224+ /**
225+ * Basic types as encoded in the JVM. These code values are not
226+ * intended for use outside this class. They are used as part of
227+ * a private interface between the JVM and this class.
228+ */
229+ static final int
230+ T_BOOLEAN = 4,
231+ T_CHAR = 5,
232+ T_FLOAT = 6,
233+ T_DOUBLE = 7,
234+ T_BYTE = 8,
235+ T_SHORT = 9,
236+ T_INT = 10,
237+ T_LONG = 11,
238+ T_OBJECT = 12,
239+ //T_ARRAY = 13
240+ T_VOID = 14,
241+ //T_ADDRESS = 15
242+ T_ILLEGAL = 99;
243+
244+ /**
245+ * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
246+ */
247+ static final int
248+ REF_getField = 1,
249+ REF_getStatic = 2,
250+ REF_putField = 3,
251+ REF_putStatic = 4,
252+ REF_invokeVirtual = 5,
253+ REF_invokeStatic = 6,
254+ REF_invokeSpecial = 7,
255+ REF_newInvokeSpecial = 8,
256+ REF_invokeInterface = 9;
257+ }
258+
259+ private static native int getNamedCon(int which, Object[] name);
260+ static boolean verifyConstants() {
261+ Object[] box = { null };
262+ for (int i = 0; ; i++) {
263+ box[0] = null;
264+ int vmval = getNamedCon(i, box);
265+ if (box[0] == null) break;
266+ String name = (String) box[0];
267+ try {
268+ Field con = Constants.class.getDeclaredField(name);
269+ int jval = con.getInt(null);
270+ if (jval == vmval) continue;
271+ String err = (name+": JVM has "+vmval+" while Java has "+jval);
272+ if (name.equals("CONV_OP_LIMIT")) {
273+ System.err.println("warning: "+err);
274+ continue;
275+ }
276+ throw new InternalError(err);
277+ } catch (Exception ex) {
278+ if (ex instanceof NoSuchFieldException) {
279+ String err = (name+": JVM has "+vmval+" which Java does not define");
280+ // ignore exotic ops the JVM cares about; we just wont issue them
281+ if (name.startsWith("OP_") || name.startsWith("GC_")) {
282+ System.err.println("warning: "+err);
283+ continue;
284+ }
285+ }
286+ throw new InternalError(name+": access failed, got "+ex);
287+ }
288+ }
289+ return true;
290+ }
291+ static {
292+ assert(verifyConstants());
293+ }
294+
295+ // Up-calls from the JVM.
296+ // These must NOT be public.
297+
298+ /**
299+ * The JVM is linking an invokedynamic instruction. Create a reified call site for it.
300+ */
301+ static CallSite makeDynamicCallSite(MethodHandle bootstrapMethod,
302+ String name, MethodType type,
303+ Object info,
304+ MemberName callerMethod, int callerBCI) {
305+ return CallSite.makeSite(bootstrapMethod, name, type, info, callerMethod, callerBCI);
306+ }
307+
308+ /**
309+ * Called by the JVM to check the length of a spread array.
310+ */
311+ static void checkSpreadArgument(Object av, int n) {
312+ MethodHandleStatics.checkSpreadArgument(av, n);
313+ }
314+
315+ /**
316+ * The JVM wants a pointer to a MethodType. Oblige it by finding or creating one.
317+ */
318+ static MethodType findMethodHandleType(Class<?> rtype, Class<?>[] ptypes) {
319+ return MethodType.makeImpl(rtype, ptypes, true);
320+ }
321+
322+ /**
323+ * The JVM wants to use a MethodType with inexact invoke. Give the runtime fair warning.
324+ */
325+ static void notifyGenericMethodType(MethodType type) {
326+ type.form().notifyGenericMethodType();
327+ }
328+
329+ /**
330+ * The JVM wants to raise an exception. Here's the path.
331+ */
332+ static void raiseException(int code, Object actual, Object required) {
333+ String message = null;
334+ switch (code) {
335+ case 190: // arraylength
336+ try {
337+ String reqLength = "";
338+ if (required instanceof AdapterMethodHandle) {
339+ int conv = ((AdapterMethodHandle)required).getConversion();
340+ int spChange = AdapterMethodHandle.extractStackMove(conv);
341+ reqLength = " of length "+(spChange+1);
342+ }
343+ int actualLength = actual == null ? 0 : java.lang.reflect.Array.getLength(actual);
344+ message = "required array"+reqLength+", but encountered wrong length "+actualLength;
345+ break;
346+ } catch (IllegalArgumentException ex) {
347+ }
348+ required = Object[].class; // should have been an array
349+ code = 192; // checkcast
350+ break;
351+ case 191: // athrow
352+ // JVM is asking us to wrap an exception which happened during resolving
353+ if (required == BootstrapMethodError.class) {
354+ throw new BootstrapMethodError((Throwable) actual);
355+ }
356+ break;
357+ }
358+ // disregard the identity of the actual object, if it is not a class:
359+ if (message == null) {
360+ if (!(actual instanceof Class) && !(actual instanceof MethodType))
361+ actual = actual.getClass();
362+ if (actual != null)
363+ message = "required "+required+" but encountered "+actual;
364+ else
365+ message = "required "+required;
366+ }
367+ switch (code) {
368+ case 190: // arraylength
369+ throw new ArrayIndexOutOfBoundsException(message);
370+ case 50: //_aaload
371+ throw new ClassCastException(message);
372+ case 192: // checkcast
373+ throw new ClassCastException(message);
374+ default:
375+ throw new InternalError("unexpected code "+code+": "+message);
376+ }
377+ }
378+
379+ /**
380+ * The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help.
381+ * It will make an up-call to this method. (Do not change the name or signature.)
382+ */
383+ static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
384+ Class<?> defc, String name, Object type) {
385+ try {
386+ Lookup lookup = IMPL_LOOKUP.in(callerClass);
387+ return lookup.linkMethodHandleConstant(refKind, defc, name, type);
388+ } catch (ReflectiveOperationException ex) {
389+ Error err = new IncompatibleClassChangeError();
390+ err.initCause(ex);
391+ throw err;
392+ }
393+ }
394+
395+ /**
396+ * This assertion marks code which was written before ricochet frames were implemented.
397+ * Such code will go away when the ports catch up.
398+ */
399+ static boolean workaroundWithoutRicochetFrames() {
400+ assert(!HAVE_RICOCHET_FRAMES) : "this code should not be executed if `-XX:+UseRicochetFrames is enabled";
401+ return true;
402+ }
403+}