1 /*
   2  * Copyright (c) 2014, 2018, 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 jdk.internal.foreign.LayoutPathsImpl;
  29 
  30 import java.foreign.layout.Layout;
  31 import java.foreign.layout.LayoutPath;
  32 import java.foreign.layout.Value;
  33 import java.lang.reflect.Field;
  34 import java.lang.reflect.Modifier;
  35 import java.util.Map;
  36 import java.util.concurrent.ConcurrentHashMap;
  37 
  38 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  39 
  40 final class VarHandles {
  41 
  42     static ClassValue<Map<Integer, MethodHandle>> addressFactories = new ClassValue<Map<Integer, MethodHandle>>() {
  43         @Override
  44         protected Map<Integer, MethodHandle> computeValue(Class<?> type) {
  45             return new ConcurrentHashMap<>();
  46         }
  47     };
  48 
  49     static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) {
  50         if (!f.isStatic()) {
  51             long foffset = MethodHandleNatives.objectFieldOffset(f);
  52             if (!type.isPrimitive()) {
  53                 return f.isFinal() && !isWriteAllowedOnFinalFields
  54                        ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type)
  55                        : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type);
  56             }
  57             else if (type == boolean.class) {
  58                 return f.isFinal() && !isWriteAllowedOnFinalFields
  59                        ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
  60                        : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset);
  61             }
  62             else if (type == byte.class) {
  63                 return f.isFinal() && !isWriteAllowedOnFinalFields
  64                        ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
  65                        : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset);
  66             }
  67             else if (type == short.class) {
  68                 return f.isFinal() && !isWriteAllowedOnFinalFields
  69                        ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
  70                        : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset);
  71             }
  72             else if (type == char.class) {
  73                 return f.isFinal() && !isWriteAllowedOnFinalFields
  74                        ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
  75                        : new VarHandleChars.FieldInstanceReadWrite(refc, foffset);
  76             }
  77             else if (type == int.class) {
  78                 return f.isFinal() && !isWriteAllowedOnFinalFields
  79                        ? new VarHandleInts.FieldInstanceReadOnly(refc, foffset)
  80                        : new VarHandleInts.FieldInstanceReadWrite(refc, foffset);
  81             }
  82             else if (type == long.class) {
  83                 return f.isFinal() && !isWriteAllowedOnFinalFields
  84                        ? new VarHandleLongs.FieldInstanceReadOnly(refc, foffset)
  85                        : new VarHandleLongs.FieldInstanceReadWrite(refc, foffset);
  86             }
  87             else if (type == float.class) {
  88                 return f.isFinal() && !isWriteAllowedOnFinalFields
  89                        ? new VarHandleFloats.FieldInstanceReadOnly(refc, foffset)
  90                        : new VarHandleFloats.FieldInstanceReadWrite(refc, foffset);
  91             }
  92             else if (type == double.class) {
  93                 return f.isFinal() && !isWriteAllowedOnFinalFields
  94                        ? new VarHandleDoubles.FieldInstanceReadOnly(refc, foffset)
  95                        : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset);
  96             }
  97             else {
  98                 throw new UnsupportedOperationException();
  99             }
 100         }
 101         else {
 102             // TODO This is not lazy on first invocation
 103             // and might cause some circular initialization issues
 104 
 105             // Replace with something similar to direct method handles
 106             // where a barrier is used then elided after use
 107 
 108             if (UNSAFE.shouldBeInitialized(refc))
 109                 UNSAFE.ensureClassInitialized(refc);
 110 
 111             Object base = MethodHandleNatives.staticFieldBase(f);
 112             long foffset = MethodHandleNatives.staticFieldOffset(f);
 113             if (!type.isPrimitive()) {
 114                 return f.isFinal() && !isWriteAllowedOnFinalFields
 115                        ? new VarHandleReferences.FieldStaticReadOnly(base, foffset, type)
 116                        : new VarHandleReferences.FieldStaticReadWrite(base, foffset, type);
 117             }
 118             else if (type == boolean.class) {
 119                 return f.isFinal() && !isWriteAllowedOnFinalFields
 120                        ? new VarHandleBooleans.FieldStaticReadOnly(base, foffset)
 121                        : new VarHandleBooleans.FieldStaticReadWrite(base, foffset);
 122             }
 123             else if (type == byte.class) {
 124                 return f.isFinal() && !isWriteAllowedOnFinalFields
 125                        ? new VarHandleBytes.FieldStaticReadOnly(base, foffset)
 126                        : new VarHandleBytes.FieldStaticReadWrite(base, foffset);
 127             }
 128             else if (type == short.class) {
 129                 return f.isFinal() && !isWriteAllowedOnFinalFields
 130                        ? new VarHandleShorts.FieldStaticReadOnly(base, foffset)
 131                        : new VarHandleShorts.FieldStaticReadWrite(base, foffset);
 132             }
 133             else if (type == char.class) {
 134                 return f.isFinal() && !isWriteAllowedOnFinalFields
 135                        ? new VarHandleChars.FieldStaticReadOnly(base, foffset)
 136                        : new VarHandleChars.FieldStaticReadWrite(base, foffset);
 137             }
 138             else if (type == int.class) {
 139                 return f.isFinal() && !isWriteAllowedOnFinalFields
 140                        ? new VarHandleInts.FieldStaticReadOnly(base, foffset)
 141                        : new VarHandleInts.FieldStaticReadWrite(base, foffset);
 142             }
 143             else if (type == long.class) {
 144                 return f.isFinal() && !isWriteAllowedOnFinalFields
 145                        ? new VarHandleLongs.FieldStaticReadOnly(base, foffset)
 146                        : new VarHandleLongs.FieldStaticReadWrite(base, foffset);
 147             }
 148             else if (type == float.class) {
 149                 return f.isFinal() && !isWriteAllowedOnFinalFields
 150                        ? new VarHandleFloats.FieldStaticReadOnly(base, foffset)
 151                        : new VarHandleFloats.FieldStaticReadWrite(base, foffset);
 152             }
 153             else if (type == double.class) {
 154                 return f.isFinal() && !isWriteAllowedOnFinalFields
 155                        ? new VarHandleDoubles.FieldStaticReadOnly(base, foffset)
 156                        : new VarHandleDoubles.FieldStaticReadWrite(base, foffset);
 157             }
 158             else {
 159                 throw new UnsupportedOperationException();
 160             }
 161         }
 162     }
 163 
 164     // Required by instance field handles
 165     static Field getFieldFromReceiverAndOffset(Class<?> receiverType,
 166                                                long offset,
 167                                                Class<?> fieldType) {
 168         for (Field f : receiverType.getDeclaredFields()) {
 169             if (Modifier.isStatic(f.getModifiers())) continue;
 170 
 171             if (offset == UNSAFE.objectFieldOffset(f)) {
 172                 assert f.getType() == fieldType;
 173                 return f;
 174             }
 175         }
 176         throw new InternalError("Field not found at offset");
 177     }
 178 
 179     // Required by instance static field handles
 180     static Field getStaticFieldFromBaseAndOffset(Object base,
 181                                                  long offset,
 182                                                  Class<?> fieldType) {
 183         // @@@ This is a little fragile assuming the base is the class
 184         Class<?> receiverType = (Class<?>) base;
 185         for (Field f : receiverType.getDeclaredFields()) {
 186             if (!Modifier.isStatic(f.getModifiers())) continue;
 187 
 188             if (offset == UNSAFE.staticFieldOffset(f)) {
 189                 assert f.getType() == fieldType;
 190                 return f;
 191             }
 192         }
 193         throw new InternalError("Static field not found at offset");
 194     }
 195 
 196     static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
 197         if (!arrayClass.isArray())
 198             throw new IllegalArgumentException("not an array: " + arrayClass);
 199 
 200         Class<?> componentType = arrayClass.getComponentType();
 201 
 202         int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
 203         int ascale = UNSAFE.arrayIndexScale(arrayClass);
 204         int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
 205 
 206         if (!componentType.isPrimitive()) {
 207             return new VarHandleReferences.Array(aoffset, ashift, arrayClass);
 208         }
 209         else if (componentType == boolean.class) {
 210             return new VarHandleBooleans.Array(aoffset, ashift);
 211         }
 212         else if (componentType == byte.class) {
 213             return new VarHandleBytes.Array(aoffset, ashift);
 214         }
 215         else if (componentType == short.class) {
 216             return new VarHandleShorts.Array(aoffset, ashift);
 217         }
 218         else if (componentType == char.class) {
 219             return new VarHandleChars.Array(aoffset, ashift);
 220         }
 221         else if (componentType == int.class) {
 222             return new VarHandleInts.Array(aoffset, ashift);
 223         }
 224         else if (componentType == long.class) {
 225             return new VarHandleLongs.Array(aoffset, ashift);
 226         }
 227         else if (componentType == float.class) {
 228             return new VarHandleFloats.Array(aoffset, ashift);
 229         }
 230         else if (componentType == double.class) {
 231             return new VarHandleDoubles.Array(aoffset, ashift);
 232         }
 233         else {
 234             throw new UnsupportedOperationException();
 235         }
 236     }
 237 
 238     static VarHandle byteArrayViewHandle(Class<?> viewArrayClass,
 239                                          boolean be) {
 240         if (!viewArrayClass.isArray())
 241             throw new IllegalArgumentException("not an array: " + viewArrayClass);
 242 
 243         Class<?> viewComponentType = viewArrayClass.getComponentType();
 244 
 245         if (viewComponentType == long.class) {
 246             return new VarHandleByteArrayAsLongs.ArrayHandle(be);
 247         }
 248         else if (viewComponentType == int.class) {
 249             return new VarHandleByteArrayAsInts.ArrayHandle(be);
 250         }
 251         else if (viewComponentType == short.class) {
 252             return new VarHandleByteArrayAsShorts.ArrayHandle(be);
 253         }
 254         else if (viewComponentType == char.class) {
 255             return new VarHandleByteArrayAsChars.ArrayHandle(be);
 256         }
 257         else if (viewComponentType == double.class) {
 258             return new VarHandleByteArrayAsDoubles.ArrayHandle(be);
 259         }
 260         else if (viewComponentType == float.class) {
 261             return new VarHandleByteArrayAsFloats.ArrayHandle(be);
 262         }
 263 
 264         throw new UnsupportedOperationException();
 265     }
 266 
 267     static VarHandle makeByteBufferViewHandle(Class<?> viewArrayClass,
 268                                               boolean be) {
 269         if (!viewArrayClass.isArray())
 270             throw new IllegalArgumentException("not an array: " + viewArrayClass);
 271 
 272         Class<?> viewComponentType = viewArrayClass.getComponentType();
 273 
 274         if (viewComponentType == long.class) {
 275             return new VarHandleByteArrayAsLongs.ByteBufferHandle(be);
 276         }
 277         else if (viewComponentType == int.class) {
 278             return new VarHandleByteArrayAsInts.ByteBufferHandle(be);
 279         }
 280         else if (viewComponentType == short.class) {
 281             return new VarHandleByteArrayAsShorts.ByteBufferHandle(be);
 282         }
 283         else if (viewComponentType == char.class) {
 284             return new VarHandleByteArrayAsChars.ByteBufferHandle(be);
 285         }
 286         else if (viewComponentType == double.class) {
 287             return new VarHandleByteArrayAsDoubles.ByteBufferHandle(be);
 288         }
 289         else if (viewComponentType == float.class) {
 290             return new VarHandleByteArrayAsFloats.ByteBufferHandle(be);
 291         }
 292 
 293         throw new UnsupportedOperationException();
 294     }
 295 
 296     static VarHandle makeMemoryAddressViewHandle(Class<?> carrier, LayoutPath path) {
 297         if (carrier.isArray())
 298             throw new IllegalArgumentException("Illegal array carrier: " + carrier);
 299 
 300         Layout layout = path.layout();
 301 
 302         if (!(layout instanceof Value)) {
 303             throw new IllegalArgumentException("Not a value layout: " + layout);
 304         }
 305 
 306         long offset = path.offset() / 8;
 307         long length = layout.bitsSize() / 8;
 308         boolean be = ((Value)layout).endianness() == Value.Endianness.BIG_ENDIAN;
 309 
 310         long[] strides = ((LayoutPathsImpl.LayoutPathImpl)path).enclosingSequences().stream()
 311                 .mapToLong(seq -> seq.element().bitsSize() / 8)
 312                 .toArray();
 313 
 314         Map<Integer, MethodHandle> carrierFactory = addressFactories.get(carrier);
 315         MethodHandle fac = carrierFactory.computeIfAbsent(strides.length,
 316                 dims -> new AddressVarHandleGenerator(carrier, dims)
 317                             .generateHandleFactory());
 318         
 319         try {
 320             return (VarHandle)fac.invoke(be, length, offset, strides);
 321         } catch (Throwable ex) {
 322             throw new IllegalStateException(ex);
 323         }
 324     }
 325 
 326 //    /**
 327 //     * A helper program to generate the VarHandleGuards class with a set of
 328 //     * static guard methods each of which corresponds to a particular shape and
 329 //     * performs a type check of the symbolic type descriptor with the VarHandle
 330 //     * type descriptor before linking/invoking to the underlying operation as
 331 //     * characterized by the operation member name on the VarForm of the
 332 //     * VarHandle.
 333 //     * <p>
 334 //     * The generated class essentially encapsulates pre-compiled LambdaForms,
 335 //     * one for each method, for the most set of common method signatures.
 336 //     * This reduces static initialization costs, footprint costs, and circular
 337 //     * dependencies that may arise if a class is generated per LambdaForm.
 338 //     * <p>
 339 //     * A maximum of L*T*S methods will be generated where L is the number of
 340 //     * access modes kinds (or unique operation signatures) and T is the number
 341 //     * of variable types and S is the number of shapes (such as instance field,
 342 //     * static field, or array access).
 343 //     * If there are 4 unique operation signatures, 5 basic types (Object, int,
 344 //     * long, float, double), and 3 shapes then a maximum of 60 methods will be
 345 //     * generated.  However, the number is likely to be less since there
 346 //     * be duplicate signatures.
 347 //     * <p>
 348 //     * Each method is annotated with @LambdaForm.Compiled to inform the runtime
 349 //     * that such methods should be treated as if a method of a class that is the
 350 //     * result of compiling a LambdaForm.  Annotation of such methods is
 351 //     * important for correct evaluation of certain assertions and method return
 352 //     * type profiling in HotSpot.
 353 //     */
 354 //    public static class GuardMethodGenerator {
 355 //
 356 //        static final String GUARD_METHOD_SIG_TEMPLATE = "<RETURN> <NAME>_<SIGNATURE>(<PARAMS>)";
 357 //
 358 //        static final String GUARD_METHOD_TEMPLATE =
 359 //                "@ForceInline\n" +
 360 //                "@LambdaForm.Compiled\n" +
 361 //                "final static <METHOD> throws Throwable {\n" +
 362 //                "    if (handle.vform.methodType_table[ad.type] == ad.symbolicMethodType) {\n" +
 363 //                "        <RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>\n" +
 364 //                "    }\n" +
 365 //                "    else {\n" +
 366 //                "        MethodHandle mh = handle.getMethodHandle(ad.mode);\n" +
 367 //                "        <RETURN>mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
 368 //                "    }\n" +
 369 //                "}";
 370 //
 371 //        static final String GUARD_METHOD_TEMPLATE_V =
 372 //                "@ForceInline\n" +
 373 //                "@LambdaForm.Compiled\n" +
 374 //                "final static <METHOD> throws Throwable {\n" +
 375 //                "    if (handle.vform.methodType_table[ad.type] == ad.symbolicMethodType) {\n" +
 376 //                "        MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
 377 //                "    }\n" +
 378 //                "    else if (handle.vform.getMethodType_V(ad.type) == ad.symbolicMethodType) {\n" +
 379 //                "        MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
 380 //                "    }\n" +
 381 //                "    else {\n" +
 382 //                "        MethodHandle mh = handle.getMethodHandle(ad.mode);\n" +
 383 //                "        mh.asType(ad.symbolicMethodTypeInvoker).invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
 384 //                "    }\n" +
 385 //                "}";
 386 //
 387 //        // A template for deriving the operations
 388 //        // could be supported by annotating VarHandle directly with the
 389 //        // operation kind and shape
 390 //        interface VarHandleTemplate {
 391 //            Object get();
 392 //
 393 //            void set(Object value);
 394 //
 395 //            boolean compareAndSet(Object actualValue, Object expectedValue);
 396 //
 397 //            Object compareAndExchange(Object actualValue, Object expectedValue);
 398 //
 399 //            Object getAndUpdate(Object value);
 400 //        }
 401 //
 402 //        static class HandleType {
 403 //            final Class<?> receiver;
 404 //            final Class<?>[] intermediates;
 405 //            final Class<?> value;
 406 //
 407 //            HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) {
 408 //                this.receiver = receiver;
 409 //                this.intermediates = intermediates;
 410 //                this.value = value;
 411 //            }
 412 //        }
 413 //
 414 //        /**
 415 //         * @param args parameters
 416 //         */
 417 //        public static void main(String[] args) {
 418 //            System.out.println("package java.lang.invoke;");
 419 //            System.out.println();
 420 //            System.out.println("import jdk.internal.vm.annotation.ForceInline;");
 421 //            System.out.println();
 422 //            System.out.println("// This class is auto-generated by " +
 423 //                               GuardMethodGenerator.class.getName() +
 424 //                               ". Do not edit.");
 425 //            System.out.println("final class VarHandleGuards {");
 426 //
 427 //            System.out.println();
 428 //
 429 //            // Declare the stream of shapes
 430 //            Stream<HandleType> hts = Stream.of(
 431 //                    // Object->Object
 432 //                    new HandleType(Object.class, Object.class),
 433 //                    // Object->int
 434 //                    new HandleType(Object.class, int.class),
 435 //                    // Object->long
 436 //                    new HandleType(Object.class, long.class),
 437 //                    // Object->float
 438 //                    new HandleType(Object.class, float.class),
 439 //                    // Object->double
 440 //                    new HandleType(Object.class, double.class),
 441 //
 442 //                    // <static>->Object
 443 //                    new HandleType(null, Object.class),
 444 //                    // <static>->int
 445 //                    new HandleType(null, int.class),
 446 //                    // <static>->long
 447 //                    new HandleType(null, long.class),
 448 //                    // <static>->float
 449 //                    new HandleType(null, float.class),
 450 //                    // <static>->double
 451 //                    new HandleType(null, double.class),
 452 //
 453 //                    // Array[int]->Object
 454 //                    new HandleType(Object.class, Object.class, int.class),
 455 //                    // Array[int]->int
 456 //                    new HandleType(Object.class, int.class, int.class),
 457 //                    // Array[int]->long
 458 //                    new HandleType(Object.class, long.class, int.class),
 459 //                    // Array[int]->float
 460 //                    new HandleType(Object.class, float.class, int.class),
 461 //                    // Array[int]->double
 462 //                    new HandleType(Object.class, double.class, int.class),
 463 //
 464 //                    // Array[long]->int
 465 //                    new HandleType(Object.class, int.class, long.class),
 466 //                    // Array[long]->long
 467 //                    new HandleType(Object.class, long.class, long.class)
 468 //            );
 469 //
 470 //            hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()).
 471 //                    map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))).
 472 //                    distinct().
 473 //                    map(mt -> generateMethod(mt)).
 474 //                    forEach(s -> {
 475 //                        System.out.println(s);
 476 //                        System.out.println();
 477 //                    });
 478 //
 479 //            System.out.println("}");
 480 //        }
 481 //
 482 //        static MethodType generateMethodType(Method m, Class<?> receiver, Class<?> value, Class<?>... intermediates) {
 483 //            Class<?> returnType = m.getReturnType() == Object.class
 484 //                                  ? value : m.getReturnType();
 485 //
 486 //            List<Class<?>> params = new ArrayList<>();
 487 //            if (receiver != null)
 488 //                params.add(receiver);
 489 //            for (int i = 0; i < intermediates.length; i++) {
 490 //                params.add(intermediates[i]);
 491 //            }
 492 //            for (Parameter p : m.getParameters()) {
 493 //                params.add(value);
 494 //            }
 495 //            return MethodType.methodType(returnType, params);
 496 //        }
 497 //
 498 //        static String generateMethod(MethodType mt) {
 499 //            Class<?> returnType = mt.returnType();
 500 //
 501 //            LinkedHashMap<String, Class<?>> params = new LinkedHashMap<>();
 502 //            params.put("handle", VarHandle.class);
 503 //            for (int i = 0; i < mt.parameterCount(); i++) {
 504 //                params.put("arg" + i, mt.parameterType(i));
 505 //            }
 506 //            params.put("ad", VarHandle.AccessDescriptor.class);
 507 //
 508 //            // Generate method signature line
 509 //            String RETURN = className(returnType);
 510 //            String NAME = "guard";
 511 //            String SIGNATURE = getSignature(mt);
 512 //            String PARAMS = params.entrySet().stream().
 513 //                    map(e -> className(e.getValue()) + " " + e.getKey()).
 514 //                    collect(joining(", "));
 515 //            String METHOD = GUARD_METHOD_SIG_TEMPLATE.
 516 //                    replace("<RETURN>", RETURN).
 517 //                    replace("<NAME>", NAME).
 518 //                    replace("<SIGNATURE>", SIGNATURE).
 519 //                    replace("<PARAMS>", PARAMS);
 520 //
 521 //            // Generate method
 522 //            params.remove("ad");
 523 //
 524 //            List<String> LINK_TO_STATIC_ARGS = params.keySet().stream().
 525 //                    collect(toList());
 526 //            LINK_TO_STATIC_ARGS.add("handle.vform.getMemberName(ad.mode)");
 527 //            List<String> LINK_TO_STATIC_ARGS_V = params.keySet().stream().
 528 //                    collect(toList());
 529 //            LINK_TO_STATIC_ARGS_V.add("handle.vform.getMemberName_V(ad.mode)");
 530 //
 531 //            List<String> LINK_TO_INVOKER_ARGS = params.keySet().stream().
 532 //                    collect(toList());
 533 //
 534 //            RETURN = returnType == void.class
 535 //                     ? ""
 536 //                     : returnType == Object.class
 537 //                       ? "return "
 538 //                       : "return (" + returnType.getName() + ") ";
 539 //
 540 //            String RESULT_ERASED = returnType == void.class
 541 //                                   ? ""
 542 //                                   : returnType != Object.class
 543 //                                     ? "return (" + returnType.getName() + ") "
 544 //                                     : "Object r = ";
 545 //
 546 //            String RETURN_ERASED = returnType != Object.class
 547 //                                   ? ""
 548 //                                   : " return ad.returnType.cast(r);";
 549 //
 550 //            String template = returnType == void.class
 551 //                              ? GUARD_METHOD_TEMPLATE_V
 552 //                              : GUARD_METHOD_TEMPLATE;
 553 //            return template.
 554 //                    replace("<METHOD>", METHOD).
 555 //                    replace("<NAME>", NAME).
 556 //                    replaceAll("<RETURN>", RETURN).
 557 //                    replace("<RESULT_ERASED>", RESULT_ERASED).
 558 //                    replace("<RETURN_ERASED>", RETURN_ERASED).
 559 //                    replaceAll("<LINK_TO_STATIC_ARGS>", LINK_TO_STATIC_ARGS.stream().
 560 //                            collect(joining(", "))).
 561 //                    replaceAll("<LINK_TO_STATIC_ARGS_V>", LINK_TO_STATIC_ARGS_V.stream().
 562 //                            collect(joining(", "))).
 563 //                    replace("<LINK_TO_INVOKER_ARGS>", LINK_TO_INVOKER_ARGS.stream().
 564 //                            collect(joining(", ")))
 565 //                    ;
 566 //        }
 567 //
 568 //        static String className(Class<?> c) {
 569 //            String n = c.getName();
 570 //            if (n.startsWith("java.lang.")) {
 571 //                n = n.replace("java.lang.", "");
 572 //                if (n.startsWith("invoke.")) {
 573 //                    n = n.replace("invoke.", "");
 574 //                }
 575 //            }
 576 //            return n.replace('$', '.');
 577 //        }
 578 //
 579 //        static String getSignature(MethodType m) {
 580 //            StringBuilder sb = new StringBuilder(m.parameterCount() + 1);
 581 //
 582 //            for (int i = 0; i < m.parameterCount(); i++) {
 583 //                Class<?> pt = m.parameterType(i);
 584 //                sb.append(getCharType(pt));
 585 //            }
 586 //
 587 //            sb.append('_').append(getCharType(m.returnType()));
 588 //
 589 //            return sb.toString();
 590 //        }
 591 //
 592 //        static char getCharType(Class<?> pt) {
 593 //            if (pt == void.class) {
 594 //                return 'V';
 595 //            }
 596 //            else if (!pt.isPrimitive()) {
 597 //                return 'L';
 598 //            }
 599 //            else if (pt == boolean.class) {
 600 //                return 'Z';
 601 //            }
 602 //            else if (pt == int.class) {
 603 //                return 'I';
 604 //            }
 605 //            else if (pt == long.class) {
 606 //                return 'J';
 607 //            }
 608 //            else if (pt == float.class) {
 609 //                return 'F';
 610 //            }
 611 //            else if (pt == double.class) {
 612 //                return 'D';
 613 //            }
 614 //            else {
 615 //                throw new IllegalStateException(pt.getName());
 616 //            }
 617 //        }
 618 //    }
 619 }