1 /*
   2  * Copyright (c) 2010, 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.  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 jdk.nashorn.internal.runtime.linker;
  27 
  28 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_FINAL;
  29 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PRIVATE;
  30 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
  31 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
  32 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
  33 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_VARARGS;
  34 import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
  35 import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE;
  36 import static jdk.internal.org.objectweb.asm.Opcodes.D2F;
  37 import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
  38 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
  39 import static jdk.internal.org.objectweb.asm.Opcodes.I2B;
  40 import static jdk.internal.org.objectweb.asm.Opcodes.I2S;
  41 import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
  42 import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
  43 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
  44 import static jdk.nashorn.internal.lookup.Lookup.MH;
  45 import static jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome.ERROR_NO_ACCESSIBLE_CONSTRUCTOR;
  46 
  47 import java.lang.invoke.CallSite;
  48 import java.lang.invoke.MethodHandle;
  49 import java.lang.invoke.MethodHandles.Lookup;
  50 import java.lang.invoke.MethodType;
  51 import java.lang.reflect.AccessibleObject;
  52 import java.lang.reflect.Constructor;
  53 import java.lang.reflect.Method;
  54 import java.lang.reflect.Modifier;
  55 import java.security.AccessControlContext;
  56 import java.security.AccessController;
  57 import java.security.PrivilegedAction;
  58 import java.security.ProtectionDomain;
  59 import java.util.Arrays;
  60 import java.util.Collection;
  61 import java.util.HashSet;
  62 import java.util.Iterator;
  63 import java.util.List;
  64 import java.util.Set;
  65 import jdk.internal.org.objectweb.asm.ClassWriter;
  66 import jdk.internal.org.objectweb.asm.Handle;
  67 import jdk.internal.org.objectweb.asm.Label;
  68 import jdk.internal.org.objectweb.asm.Opcodes;
  69 import jdk.internal.org.objectweb.asm.Type;
  70 import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
  71 import jdk.nashorn.api.scripting.ScriptObjectMirror;
  72 import jdk.nashorn.api.scripting.ScriptUtils;
  73 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
  74 import jdk.nashorn.internal.runtime.ScriptFunction;
  75 import jdk.nashorn.internal.runtime.ScriptObject;
  76 import jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome;
  77 import jdk.internal.reflect.CallerSensitive;
  78 
  79 /**
  80  * Generates bytecode for a Java adapter class. Used by the {@link JavaAdapterFactory}.
  81  * </p><p>
  82  * For every protected or public constructor in the extended class, the adapter class will have either one or two
  83  * public constructors (visibility of protected constructors in the extended class is promoted to public).
  84  * <li>
  85  * <li>For adapter classes with instance-level overrides, a constructor taking a trailing ScriptObject argument preceded
  86  * by original constructor arguments is always created on the adapter class. When such a constructor is invoked, the
  87  * passed ScriptObject's member functions are used to implement and/or override methods on the original class,
  88  * dispatched by name. A single JavaScript function will act as the implementation for all overloaded methods of the
  89  * same name. When methods on an adapter instance are invoked, the functions are invoked having the ScriptObject passed
  90  * in the instance constructor as their "this". Subsequent changes to the ScriptObject (reassignment or removal of its
  91  * functions) will be reflected in the adapter instance as it is live dispatching to its members on every method invocation.
  92  * {@code java.lang.Object} methods {@code equals}, {@code hashCode}, and {@code toString} can also be overridden. The
  93  * only restriction is that since every JavaScript object already has a {@code toString} function through the
  94  * {@code Object.prototype}, the {@code toString} in the adapter is only overridden if the passed ScriptObject has a
  95  * {@code toString} function as its own property, and not inherited from a prototype. All other adapter methods can be
  96  * implemented or overridden through a prototype-inherited function of the ScriptObject passed to the constructor too.
  97  * </li>
  98  * <li>
  99  * If the original types collectively have only one abstract method, or have several of them, but all share the
 100  * same name, an additional constructor for instance-level override adapter is provided for every original constructor;
 101  * this one takes a ScriptFunction as its last argument preceded by original constructor arguments. This constructor
 102  * will use the passed function as the implementation for all abstract methods. For consistency, any concrete methods
 103  * sharing the single abstract method name will also be overridden by the function. When methods on the adapter instance
 104  * are invoked, the ScriptFunction is invoked with UNDEFINED or Global as its "this" depending whether the function is
 105  * strict or not.
 106  * </li>
 107  * <li>
 108  * If the adapter being generated has class-level overrides, constructors taking same arguments as the superclass
 109  * constructors are created. These constructors simply delegate to the superclass constructor. They are simply used to
 110  * create instances of the adapter class, with no instance-level overrides, as they don't have them. If the original
 111  * class' constructor was variable arity, the adapter constructor will also be variable arity. Protected constructors
 112  * are exposed as public.
 113  * </li>
 114  * </ul>
 115  * </p><p>
 116  * For adapter methods that return values, all the JavaScript-to-Java conversions supported by Nashorn will be in effect
 117  * to coerce the JavaScript function return value to the expected Java return type.
 118  * </p><p>
 119  * Since we are adding a trailing argument to the generated constructors in the adapter class with instance-level overrides, they will never be
 120  * declared as variable arity, even if the original constructor in the superclass was declared as variable arity. The
 121  * reason we are passing the additional argument at the end of the argument list instead at the front is that the
 122  * source-level script expression <code>new X(a, b) { ... }</code> (which is a proprietary syntax extension Nashorn uses
 123  * to resemble Java anonymous classes) is actually equivalent to <code>new X(a, b, { ... })</code>.
 124  * </p><p>
 125  * It is possible to create two different adapter classes: those that can have class-level overrides, and those that can
 126  * have instance-level overrides. When {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject, ProtectionDomain)}
 127  * or {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject, Lookup)} is invoked
 128  * with non-null {@code classOverrides} parameter, an adapter class is created that can have class-level overrides, and
 129  * the passed script object will be used as the implementations for its methods, just as in the above case of the
 130  * constructor taking a script object. Note that in the case of class-level overrides, a new adapter class is created on
 131  * every invocation, and the implementation object is bound to the class, not to any instance. All created instances
 132  * will share these functions. If it is required to have both class-level overrides and instance-level overrides, the
 133  * class-level override adapter class should be subclassed with an instance-override adapter. Since adapters delegate to
 134  * super class when an overriding method handle is not specified, this will behave as expected. It is not possible to
 135  * have both class-level and instance-level overrides in the same class for security reasons: adapter classes are
 136  * defined with a protection domain of their creator code, and an adapter class that has both class and instance level
 137  * overrides would need to have two potentially different protection domains: one for class-based behavior and one for
 138  * instance-based behavior; since Java classes can only belong to a single protection domain, this could not be
 139  * implemented securely.
 140  */
 141 final class JavaAdapterBytecodeGenerator {
 142     // Field names in adapters
 143     private static final String GLOBAL_FIELD_NAME = "global";
 144     private static final String DELEGATE_FIELD_NAME = "delegate";
 145     private static final String IS_FUNCTION_FIELD_NAME = "isFunction";
 146     private static final String CALL_THIS_FIELD_NAME = "callThis";
 147 
 148     // Initializer names
 149     private static final String INIT = "<init>";
 150     private static final String CLASS_INIT = "<clinit>";
 151 
 152     // Types often used in generated bytecode
 153     private static final Type OBJECT_TYPE = Type.getType(Object.class);
 154     private static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
 155     private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
 156     private static final Type SCRIPT_OBJECT_MIRROR_TYPE = Type.getType(ScriptObjectMirror.class);
 157 
 158     // JavaAdapterServices methods used in generated bytecode
 159     private static final Call CHECK_FUNCTION = lookupServiceMethod("checkFunction", ScriptFunction.class, Object.class, String.class);
 160     private static final Call EXPORT_RETURN_VALUE = lookupServiceMethod("exportReturnValue", Object.class, Object.class);
 161     private static final Call GET_CALL_THIS = lookupServiceMethod("getCallThis", Object.class, ScriptFunction.class, Object.class);
 162     private static final Call GET_CLASS_OVERRIDES = lookupServiceMethod("getClassOverrides", ScriptObject.class);
 163     private static final Call GET_NON_NULL_GLOBAL = lookupServiceMethod("getNonNullGlobal", ScriptObject.class);
 164     private static final Call HAS_OWN_TO_STRING = lookupServiceMethod("hasOwnToString", boolean.class, ScriptObject.class);
 165     private static final Call INVOKE_NO_PERMISSIONS = lookupServiceMethod("invokeNoPermissions", void.class, MethodHandle.class, Object.class);
 166     private static final Call NOT_AN_OBJECT = lookupServiceMethod("notAnObject", void.class, Object.class);
 167     private static final Call SET_GLOBAL = lookupServiceMethod("setGlobal", Runnable.class, ScriptObject.class);
 168     private static final Call TO_CHAR_PRIMITIVE = lookupServiceMethod("toCharPrimitive", char.class, Object.class);
 169     private static final Call UNSUPPORTED = lookupServiceMethod("unsupported", UnsupportedOperationException.class);
 170     private static final Call WRAP_THROWABLE = lookupServiceMethod("wrapThrowable", RuntimeException.class, Throwable.class);
 171     private static final Call UNWRAP_MIRROR = lookupServiceMethod("unwrapMirror", ScriptObject.class, Object.class, boolean.class);
 172 
 173     // Other methods invoked by the generated bytecode
 174     private static final Call UNWRAP = staticCallNoLookup(ScriptUtils.class, "unwrap", Object.class, Object.class);
 175     private static final Call CHAR_VALUE_OF = staticCallNoLookup(Character.class, "valueOf", Character.class, char.class);
 176     private static final Call DOUBLE_VALUE_OF = staticCallNoLookup(Double.class, "valueOf", Double.class, double.class);
 177     private static final Call LONG_VALUE_OF = staticCallNoLookup(Long.class, "valueOf", Long.class, long.class);
 178     private static final Call RUN = interfaceCallNoLookup(Runnable.class, "run", void.class);
 179 
 180     // ASM handle to the bootstrap method
 181     private static final Handle BOOTSTRAP_HANDLE = new Handle(H_INVOKESTATIC,
 182             Type.getInternalName(JavaAdapterServices.class), "bootstrap",
 183             MethodType.methodType(CallSite.class, Lookup.class, String.class,
 184                     MethodType.class, int.class).toMethodDescriptorString(), false);
 185 
 186     // ASM handle to the bootstrap method for array populator
 187     private static final Handle CREATE_ARRAY_BOOTSTRAP_HANDLE = new Handle(H_INVOKESTATIC,
 188             Type.getInternalName(JavaAdapterServices.class), "createArrayBootstrap",
 189             MethodType.methodType(CallSite.class, Lookup.class, String.class,
 190                     MethodType.class).toMethodDescriptorString(), false);
 191 
 192     // Field type names used in the generated bytecode
 193     private static final String SCRIPT_OBJECT_TYPE_DESCRIPTOR = SCRIPT_OBJECT_TYPE.getDescriptor();
 194     private static final String OBJECT_TYPE_DESCRIPTOR = OBJECT_TYPE.getDescriptor();
 195     private static final String BOOLEAN_TYPE_DESCRIPTOR = Type.BOOLEAN_TYPE.getDescriptor();
 196 
 197     // Throwable names used in the generated bytecode
 198     private static final String RUNTIME_EXCEPTION_TYPE_NAME = Type.getInternalName(RuntimeException.class);
 199     private static final String ERROR_TYPE_NAME = Type.getInternalName(Error.class);
 200     private static final String THROWABLE_TYPE_NAME = Type.getInternalName(Throwable.class);
 201 
 202     // Some more frequently used method descriptors
 203     private static final String GET_METHOD_PROPERTY_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE, SCRIPT_OBJECT_TYPE);
 204     private static final String VOID_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
 205 
 206     private static final String ADAPTER_PACKAGE_INTERNAL = "jdk/nashorn/javaadapters/";
 207     private static final int MAX_GENERATED_TYPE_NAME_LENGTH = 255;
 208 
 209     // Method name prefix for invoking super-methods
 210     static final String SUPER_PREFIX = "super$";
 211 
 212     // Method name and type for the no-privilege finalizer delegate
 213     private static final String FINALIZER_DELEGATE_NAME = "$$nashornFinalizerDelegate";
 214     private static final String FINALIZER_DELEGATE_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE);
 215 
 216     /**
 217      * Collection of methods we never override: Object.clone(), Object.finalize().
 218      */
 219     private static final Collection<MethodInfo> EXCLUDED = getExcludedMethods();
 220 
 221     // This is the superclass for our generated adapter.
 222     private final Class<?> superClass;
 223     // Interfaces implemented by our generated adapter.
 224     private final List<Class<?>> interfaces;
 225     // Class loader used as the parent for the class loader we'll create to load the generated class. It will be a class
 226     // loader that has the visibility of all original types (class to extend and interfaces to implement) and of the
 227     // Nashorn classes.
 228     private final ClassLoader commonLoader;
 229     // Is this a generator for the version of the class that can have overrides on the class level?
 230     private final boolean classOverride;
 231     // Binary name of the superClass
 232     private final String superClassName;
 233     // Binary name of the generated class.
 234     private final String generatedClassName;
 235     private final Set<String> abstractMethodNames = new HashSet<>();
 236     private final String samName;
 237     private final Set<MethodInfo> finalMethods = new HashSet<>(EXCLUDED);
 238     private final Set<MethodInfo> methodInfos = new HashSet<>();
 239     private final boolean autoConvertibleFromFunction;
 240     private boolean hasExplicitFinalizer = false;
 241 
 242     private final ClassWriter cw;
 243 
 244     /**
 245      * Creates a generator for the bytecode for the adapter for the specified superclass and interfaces.
 246      * @param superClass the superclass the adapter will extend.
 247      * @param interfaces the interfaces the adapter will implement.
 248      * @param commonLoader the class loader that can see all of superClass, interfaces, and Nashorn classes.
 249      * @param classOverride true to generate the bytecode for the adapter that has class-level overrides, false to
 250      * generate the bytecode for the adapter that has instance-level overrides.
 251      * @throws AdaptationException if the adapter can not be generated for some reason.
 252      */
 253     JavaAdapterBytecodeGenerator(final Class<?> superClass, final List<Class<?>> interfaces,
 254                                  final ClassLoader commonLoader, final boolean classOverride) throws AdaptationException {
 255         assert superClass != null && !superClass.isInterface();
 256         assert interfaces != null;
 257 
 258         this.superClass = superClass;
 259         this.interfaces = interfaces;
 260         this.classOverride = classOverride;
 261         this.commonLoader = commonLoader;
 262         cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
 263             @Override
 264             protected String getCommonSuperClass(final String type1, final String type2) {
 265                 // We need to override ClassWriter.getCommonSuperClass to use this factory's commonLoader as a class
 266                 // loader to find the common superclass of two types when needed.
 267                 return JavaAdapterBytecodeGenerator.this.getCommonSuperClass(type1, type2);
 268             }
 269         };
 270         superClassName = Type.getInternalName(superClass);
 271         generatedClassName = getGeneratedClassName(superClass, interfaces);
 272 
 273         cw.visit(Opcodes.V1_8, ACC_PUBLIC | ACC_SUPER, generatedClassName, null, superClassName, getInternalTypeNames(interfaces));
 274         generateField(GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 275         generateField(DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 276 
 277         gatherMethods(superClass);
 278         gatherMethods(interfaces);
 279         if (abstractMethodNames.size() == 1) {
 280             samName = abstractMethodNames.iterator().next();
 281             generateField(CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
 282             generateField(IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
 283         } else {
 284             samName = null;
 285         }
 286         if(classOverride) {
 287             generateClassInit();
 288         }
 289         autoConvertibleFromFunction = generateConstructors();
 290         generateMethods();
 291         generateSuperMethods();
 292         if (hasExplicitFinalizer) {
 293             generateFinalizerMethods();
 294         }
 295         // }
 296         cw.visitEnd();
 297     }
 298 
 299     private void generateField(final String name, final String fieldDesc) {
 300         cw.visitField(ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0), name, fieldDesc, null, null).visitEnd();
 301     }
 302 
 303     JavaAdapterClassLoader createAdapterClassLoader() {
 304         return new JavaAdapterClassLoader(generatedClassName, cw.toByteArray());
 305     }
 306 
 307     boolean isAutoConvertibleFromFunction() {
 308         return autoConvertibleFromFunction;
 309     }
 310 
 311     private static String getGeneratedClassName(final Class<?> superType, final List<Class<?>> interfaces) {
 312         // The class we use to primarily name our adapter is either the superclass, or if it is Object (meaning we're
 313         // just implementing interfaces or extending Object), then the first implemented interface or Object.
 314         final Class<?> namingType = superType == Object.class ? (interfaces.isEmpty()? Object.class : interfaces.get(0)) : superType;
 315         final Package pkg = namingType.getPackage();
 316         final String namingTypeName = Type.getInternalName(namingType);
 317         final StringBuilder buf = new StringBuilder();
 318         buf.append(ADAPTER_PACKAGE_INTERNAL).append(namingTypeName.replace('/', '_'));
 319         final Iterator<Class<?>> it = interfaces.iterator();
 320         if(superType == Object.class && it.hasNext()) {
 321             it.next(); // Skip first interface, it was used to primarily name the adapter
 322         }
 323         // Append interface names to the adapter name
 324         while(it.hasNext()) {
 325             buf.append("$$").append(it.next().getSimpleName());
 326         }
 327         return buf.toString().substring(0, Math.min(MAX_GENERATED_TYPE_NAME_LENGTH, buf.length()));
 328     }
 329 
 330     /**
 331      * Given a list of class objects, return an array with their binary names. Used to generate the array of interface
 332      * names to implement.
 333      * @param classes the classes
 334      * @return an array of names
 335      */
 336     private static String[] getInternalTypeNames(final List<Class<?>> classes) {
 337         final int interfaceCount = classes.size();
 338         final String[] interfaceNames = new String[interfaceCount];
 339         for(int i = 0; i < interfaceCount; ++i) {
 340             interfaceNames[i] = Type.getInternalName(classes.get(i));
 341         }
 342         return interfaceNames;
 343     }
 344 
 345     private void generateClassInit() {
 346         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_STATIC, CLASS_INIT,
 347                 VOID_METHOD_DESCRIPTOR, null, null));
 348 
 349         // Assign "global = Context.getGlobal()"
 350         GET_NON_NULL_GLOBAL.invoke(mv);
 351         mv.putstatic(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 352 
 353         GET_CLASS_OVERRIDES.invoke(mv);
 354         if(samName != null) {
 355             // If the class is a SAM, allow having ScriptFunction passed as class overrides
 356             mv.dup();
 357             mv.instanceOf(SCRIPT_FUNCTION_TYPE);
 358             mv.dup();
 359             mv.putstatic(generatedClassName, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
 360             final Label notFunction = new Label();
 361             mv.ifeq(notFunction);
 362             mv.dup();
 363             mv.checkcast(SCRIPT_FUNCTION_TYPE);
 364             emitInitCallThis(mv);
 365             mv.visitLabel(notFunction);
 366         }
 367         mv.putstatic(generatedClassName, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 368 
 369         endInitMethod(mv);
 370     }
 371 
 372     /**
 373      * Emit bytecode for initializing the "callThis" field.
 374      */
 375     private void emitInitCallThis(final InstructionAdapter mv) {
 376         loadField(mv, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 377         GET_CALL_THIS.invoke(mv);
 378         if(classOverride) {
 379             mv.putstatic(generatedClassName, CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
 380         } else {
 381             // It is presumed ALOAD 0 was already executed
 382             mv.putfield(generatedClassName, CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
 383         }
 384     }
 385 
 386     private boolean generateConstructors() throws AdaptationException {
 387         boolean gotCtor = false;
 388         boolean canBeAutoConverted = false;
 389         for (final Constructor<?> ctor: superClass.getDeclaredConstructors()) {
 390             final int modifier = ctor.getModifiers();
 391             if((modifier & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0 && !isCallerSensitive(ctor)) {
 392                 canBeAutoConverted = generateConstructors(ctor) | canBeAutoConverted;
 393                 gotCtor = true;
 394             }
 395         }
 396         if(!gotCtor) {
 397             throw new AdaptationException(ERROR_NO_ACCESSIBLE_CONSTRUCTOR, superClass.getCanonicalName());
 398         }
 399         return canBeAutoConverted;
 400     }
 401 
 402     private boolean generateConstructors(final Constructor<?> ctor) {
 403         if(classOverride) {
 404             // Generate a constructor that just delegates to ctor. This is used with class-level overrides, when we want
 405             // to create instances without further per-instance overrides.
 406             generateDelegatingConstructor(ctor);
 407             return false;
 408         }
 409 
 410             // Generate a constructor that delegates to ctor, but takes an additional ScriptObject parameter at the
 411             // beginning of its parameter list.
 412             generateOverridingConstructor(ctor, false);
 413 
 414         if (samName == null) {
 415             return false;
 416         }
 417         // If all our abstract methods have a single name, generate an additional constructor, one that takes a
 418         // ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods.
 419         generateOverridingConstructor(ctor, true);
 420         // If the original type only has a single abstract method name, as well as a default ctor, then it can
 421         // be automatically converted from JS function.
 422         return ctor.getParameterTypes().length == 0;
 423     }
 424 
 425     private void generateDelegatingConstructor(final Constructor<?> ctor) {
 426         final Type originalCtorType = Type.getType(ctor);
 427         final Type[] argTypes = originalCtorType.getArgumentTypes();
 428 
 429         // All constructors must be public, even if in the superclass they were protected.
 430         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC |
 431                 (ctor.isVarArgs() ? ACC_VARARGS : 0), INIT,
 432                 Type.getMethodDescriptor(originalCtorType.getReturnType(), argTypes), null, null));
 433 
 434         mv.visitCode();
 435         emitSuperConstructorCall(mv, originalCtorType.getDescriptor());
 436 
 437         endInitMethod(mv);
 438     }
 439 
 440     /**
 441      * Generates a constructor for the instance adapter class. This constructor will take the same arguments as the supertype
 442      * constructor passed as the argument here, and delegate to it. However, it will take an additional argument of
 443      * either ScriptObject or ScriptFunction type (based on the value of the "fromFunction" parameter), and initialize
 444      * all the method handle fields of the adapter instance with functions from the script object (or the script
 445      * function itself, if that's what's passed). Additionally, it will create another constructor with an additional
 446      * Object type parameter that can be used for ScriptObjectMirror objects.
 447      * The constructor will also store the Nashorn global that was current at the constructor
 448      * invocation time in a field named "global". The generated constructor will be public, regardless of whether the
 449      * supertype constructor was public or protected. The generated constructor will not be variable arity, even if the
 450      * supertype constructor was.
 451      * @param ctor the supertype constructor that is serving as the base for the generated constructor.
 452      * @param fromFunction true if we're generating a constructor that initializes SAM types from a single
 453      * ScriptFunction passed to it, false if we're generating a constructor that initializes an arbitrary type from a
 454      * ScriptObject passed to it.
 455      */
 456     private void generateOverridingConstructor(final Constructor<?> ctor, final boolean fromFunction) {
 457         final Type originalCtorType = Type.getType(ctor);
 458         final Type[] originalArgTypes = originalCtorType.getArgumentTypes();
 459         final int argLen = originalArgTypes.length;
 460         final Type[] newArgTypes = new Type[argLen + 1];
 461 
 462         // Insert ScriptFunction|ScriptObject as the last argument to the constructor
 463         final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : SCRIPT_OBJECT_TYPE;
 464         newArgTypes[argLen] = extraArgumentType;
 465         System.arraycopy(originalArgTypes, 0, newArgTypes, 0, argLen);
 466 
 467         // All constructors must be public, even if in the superclass they were protected.
 468         // Existing super constructor <init>(this, args...) triggers generating <init>(this, args..., delegate).
 469         // Any variable arity constructors become fixed-arity with explicit array arguments.
 470         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
 471                 Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null));
 472 
 473         mv.visitCode();
 474         // First, invoke super constructor with original arguments.
 475         final int extraArgOffset = emitSuperConstructorCall(mv, originalCtorType.getDescriptor());
 476 
 477         // Assign "this.global = Context.getGlobal()"
 478         mv.visitVarInsn(ALOAD, 0);
 479         GET_NON_NULL_GLOBAL.invoke(mv);
 480         mv.putfield(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 481 
 482         // Assign "this.delegate = delegate"
 483         mv.visitVarInsn(ALOAD, 0);
 484         mv.visitVarInsn(ALOAD, extraArgOffset);
 485         mv.putfield(generatedClassName, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 486 
 487         if (fromFunction) {
 488             // Assign "isFunction = true"
 489             mv.visitVarInsn(ALOAD, 0);
 490             mv.iconst(1);
 491             mv.putfield(generatedClassName, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
 492 
 493         mv.visitVarInsn(ALOAD, 0);
 494             mv.visitVarInsn(ALOAD, extraArgOffset);
 495             emitInitCallThis(mv);
 496         }
 497 
 498         endInitMethod(mv);
 499 
 500         if (! fromFunction) {
 501             newArgTypes[argLen] = OBJECT_TYPE;
 502             final InstructionAdapter mv2 = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
 503                     Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null));
 504             generateOverridingConstructorWithObjectParam(mv2, originalCtorType.getDescriptor());
 505         }
 506     }
 507 
 508     // Object additional param accepting constructor for handling ScriptObjectMirror objects, which are
 509     // unwrapped to work as ScriptObjects or ScriptFunctions. This also handles null and undefined values for
 510     // script adapters by throwing TypeError on such script adapters.
 511     private void generateOverridingConstructorWithObjectParam(final InstructionAdapter mv, final String ctorDescriptor) {
 512         mv.visitCode();
 513         final int extraArgOffset = emitSuperConstructorCall(mv, ctorDescriptor);
 514 
 515         // Check for ScriptObjectMirror
 516         mv.visitVarInsn(ALOAD, extraArgOffset);
 517         mv.instanceOf(SCRIPT_OBJECT_MIRROR_TYPE);
 518         final Label notMirror = new Label();
 519         mv.ifeq(notMirror);
 520 
 521         mv.visitVarInsn(ALOAD, 0);
 522         mv.visitVarInsn(ALOAD, extraArgOffset);
 523         mv.iconst(0);
 524         UNWRAP_MIRROR.invoke(mv);
 525         mv.putfield(generatedClassName, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 526 
 527         mv.visitVarInsn(ALOAD, 0);
 528         mv.visitVarInsn(ALOAD, extraArgOffset);
 529         mv.iconst(1);
 530         UNWRAP_MIRROR.invoke(mv);
 531         mv.putfield(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 532 
 533         final Label done = new Label();
 534 
 535         if (samName != null) {
 536             mv.visitVarInsn(ALOAD, 0);
 537             mv.getfield(generatedClassName, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 538             mv.instanceOf(SCRIPT_FUNCTION_TYPE);
 539             mv.ifeq(done);
 540 
 541             // Assign "isFunction = true"
 542             mv.visitVarInsn(ALOAD, 0);
 543             mv.iconst(1);
 544             mv.putfield(generatedClassName, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
 545 
 546             mv.visitVarInsn(ALOAD, 0);
 547             mv.dup();
 548             mv.getfield(generatedClassName, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 549             mv.checkcast(SCRIPT_FUNCTION_TYPE);
 550             emitInitCallThis(mv);
 551             mv.goTo(done);
 552         }
 553 
 554         mv.visitLabel(notMirror);
 555 
 556         // Throw error if not a ScriptObject
 557         mv.visitVarInsn(ALOAD, extraArgOffset);
 558         NOT_AN_OBJECT.invoke(mv);
 559 
 560         mv.visitLabel(done);
 561         endInitMethod(mv);
 562     }
 563 
 564     private static void endInitMethod(final InstructionAdapter mv) {
 565         mv.visitInsn(RETURN);
 566         endMethod(mv);
 567     }
 568 
 569     private static void endMethod(final InstructionAdapter mv) {
 570         mv.visitMaxs(0, 0);
 571         mv.visitEnd();
 572     }
 573 
 574     /**
 575      * Encapsulation of the information used to generate methods in the adapter classes. Basically, a wrapper around the
 576      * reflective Method object, a cached MethodType, and the name of the field in the adapter class that will hold the
 577      * method handle serving as the implementation of this method in adapter instances.
 578      *
 579      */
 580     private static class MethodInfo {
 581         private final Method method;
 582         private final MethodType type;
 583 
 584         private MethodInfo(final Class<?> clazz, final String name, final Class<?>... argTypes) throws NoSuchMethodException {
 585             this(clazz.getDeclaredMethod(name, argTypes));
 586         }
 587 
 588         private MethodInfo(final Method method) {
 589             this.method = method;
 590             this.type   = MH.type(method.getReturnType(), method.getParameterTypes());
 591         }
 592 
 593         @Override
 594         public boolean equals(final Object obj) {
 595             return obj instanceof MethodInfo && equals((MethodInfo)obj);
 596         }
 597 
 598         private boolean equals(final MethodInfo other) {
 599             // Only method name and type are used for comparison; method handle field name is not.
 600             return getName().equals(other.getName()) && type.equals(other.type);
 601         }
 602 
 603         String getName() {
 604             return method.getName();
 605         }
 606 
 607         @Override
 608         public int hashCode() {
 609             return getName().hashCode() ^ type.hashCode();
 610         }
 611     }
 612 
 613     private void generateMethods() {
 614         for(final MethodInfo mi: methodInfos) {
 615             generateMethod(mi);
 616         }
 617     }
 618 
 619     /**
 620      * Generates a method in the adapter class that adapts a method from the
 621      * original class. The generated method will either invoke the delegate
 622      * using a CALL dynamic operation call site (if it is a SAM method and the
 623      * delegate is a ScriptFunction), or invoke GET_METHOD_PROPERTY dynamic
 624      * operation with the method name as the argument and then invoke the
 625      * returned ScriptFunction using the CALL dynamic operation. If
 626      * GET_METHOD_PROPERTY returns null or undefined (that is, the JS object
 627      * doesn't provide an implementation for the method) then the method will
 628      * either do a super invocation to base class, or if the method is abstract,
 629      * throw an {@link UnsupportedOperationException}. Finally, if
 630      * GET_METHOD_PROPERTY returns something other than a ScriptFunction, null,
 631      * or undefined, a TypeError is thrown. The current Global is checked before
 632      * the dynamic operations, and if it is different  than the Global used to
 633      * create the adapter, the creating Global is set to be the current Global.
 634      * In this case, the previously current Global is restored after the
 635      * invocation. If CALL results in a Throwable that is not one of the
 636      * method's declared exceptions, and is not an unchecked throwable, then it
 637      * is wrapped into a {@link RuntimeException} and the runtime exception is
 638      * thrown.
 639      * @param mi the method info describing the method to be generated.
 640      */
 641     private void generateMethod(final MethodInfo mi) {
 642         final Method method = mi.method;
 643         final Class<?>[] exceptions = method.getExceptionTypes();
 644         final String[] exceptionNames = getExceptionNames(exceptions);
 645         final MethodType type = mi.type;
 646         final String methodDesc = type.toMethodDescriptorString();
 647         final String name = mi.getName();
 648 
 649         final Type asmType = Type.getMethodType(methodDesc);
 650         final Type[] asmArgTypes = asmType.getArgumentTypes();
 651 
 652         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method), name,
 653                 methodDesc, null, exceptionNames));
 654         mv.visitCode();
 655 
 656         final Class<?> returnType = type.returnType();
 657         final Type asmReturnType = Type.getType(returnType);
 658 
 659         // Determine the first index for a local variable
 660         int nextLocalVar = 1; // "this" is at 0
 661         for(final Type t: asmArgTypes) {
 662             nextLocalVar += t.getSize();
 663         }
 664         // Set our local variable index
 665         final int globalRestoringRunnableVar = nextLocalVar++;
 666 
 667         // Load the creatingGlobal object
 668         loadField(mv, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 669         // stack: [creatingGlobal]
 670         SET_GLOBAL.invoke(mv);
 671         // stack: [runnable]
 672         mv.visitVarInsn(ASTORE, globalRestoringRunnableVar);
 673         // stack: []
 674 
 675         final Label tryBlockStart = new Label();
 676         mv.visitLabel(tryBlockStart);
 677 
 678         final Label callCallee = new Label();
 679         final Label defaultBehavior = new Label();
 680         // If this is a SAM type...
 681         if (samName != null) {
 682             // ...every method will be checking whether we're initialized with a
 683             // function.
 684             loadField(mv, IS_FUNCTION_FIELD_NAME, BOOLEAN_TYPE_DESCRIPTOR);
 685             // stack: [isFunction]
 686             if (name.equals(samName)) {
 687                 final Label notFunction = new Label();
 688                 mv.ifeq(notFunction);
 689                 // stack: []
 690                 // If it's a SAM method, it'll load delegate as the "callee" and
 691                 // "callThis" as "this" for the call if delegate is a function.
 692                 loadField(mv, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 693                 // NOTE: if we added "mv.checkcast(SCRIPT_FUNCTION_TYPE);" here
 694                 // we could emit the invokedynamic CALL instruction with signature
 695                 // (ScriptFunction, Object, ...) instead of (Object, Object, ...).
 696                 // We could combine this with an optimization in
 697                 // ScriptFunction.findCallMethod where it could link a call with a
 698                 // thinner guard when the call site statically guarantees that the
 699                 // callee argument is a ScriptFunction. Additionally, we could use
 700                 // a "ScriptFunction function" field in generated classes instead
 701                 // of a "boolean isFunction" field to avoid the checkcast.
 702                 loadField(mv, CALL_THIS_FIELD_NAME, OBJECT_TYPE_DESCRIPTOR);
 703                 // stack: [callThis, delegate]
 704                 mv.goTo(callCallee);
 705                 mv.visitLabel(notFunction);
 706             } else {
 707                 // If it's not a SAM method, and the delegate is a function,
 708                 // it'll fall back to default behavior
 709                 mv.ifne(defaultBehavior);
 710                 // stack: []
 711             }
 712         }
 713 
 714         // At this point, this is either not a SAM method or the delegate is
 715         // not a ScriptFunction. We need to emit a GET_METHOD_PROPERTY Nashorn
 716         // invokedynamic.
 717 
 718         if(name.equals("toString")) {
 719             // Since every JS Object has a toString, we only override
 720             // "String toString()" it if it's explicitly specified on the object.
 721             loadField(mv, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 722             // stack: [delegate]
 723             HAS_OWN_TO_STRING.invoke(mv);
 724             // stack: [hasOwnToString]
 725             mv.ifeq(defaultBehavior);
 726         }
 727 
 728         loadField(mv, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 729         //For the cases like scripted overridden methods invoked from super constructors get adapter global/delegate fields as null, since we
 730         //cannot set these fields before invoking super constructor better solution is opt out of scripted overridden method if global/delegate fields
 731         //are null and invoke super method instead
 732         mv.ifnull(defaultBehavior);
 733         loadField(mv, DELEGATE_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
 734         mv.dup();
 735         // stack: [delegate, delegate]
 736         final String encodedName = NameCodec.encode(name);
 737         mv.visitInvokeDynamicInsn(encodedName,
 738                 GET_METHOD_PROPERTY_METHOD_DESCRIPTOR, BOOTSTRAP_HANDLE,
 739                 NashornCallSiteDescriptor.GET_METHOD_PROPERTY);
 740         // stack: [callee, delegate]
 741         mv.visitLdcInsn(name);
 742         // stack: [name, callee, delegate]
 743         CHECK_FUNCTION.invoke(mv);
 744         // stack: [fnCalleeOrNull, delegate]
 745         final Label hasFunction = new Label();
 746         mv.dup();
 747         // stack: [fnCalleeOrNull, fnCalleeOrNull, delegate]
 748         mv.ifnonnull(hasFunction);
 749         // stack: [null, delegate]
 750         // If it's null or undefined, clear stack and fall back to default
 751         // behavior.
 752         mv.pop2();
 753         // stack: []
 754 
 755         // We can also arrive here from check for "delegate instanceof ScriptFunction"
 756         // in a non-SAM method as well as from a check for "hasOwnToString(delegate)"
 757         // for a toString delegate.
 758         mv.visitLabel(defaultBehavior);
 759         final Runnable emitFinally = ()->emitFinally(mv, globalRestoringRunnableVar);
 760         final Label normalFinally = new Label();
 761         if(Modifier.isAbstract(method.getModifiers())) {
 762             // If the super method is abstract, throw UnsupportedOperationException
 763             UNSUPPORTED.invoke(mv);
 764             // NOTE: no need to invoke emitFinally.run() as we're inside the
 765             // tryBlockStart/tryBlockEnd range, so throwing this exception will
 766             // transfer control to the rethrow handler and the finally block in it
 767             // will execute.
 768             mv.athrow();
 769         } else {
 770             // If the super method is not abstract, delegate to it.
 771             emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
 772             mv.goTo(normalFinally);
 773         }
 774 
 775         mv.visitLabel(hasFunction);
 776         // stack: [callee, delegate]
 777         mv.swap();
 778         // stack [delegate, callee]
 779         mv.visitLabel(callCallee);
 780 
 781 
 782         // Load all parameters back on stack for dynamic invocation.
 783 
 784         int varOffset = 1;
 785         // If the param list length is more than 253 slots, we can't invoke it
 786         // directly as with (callee, this) it'll exceed 255.
 787         final boolean isVarArgCall = getParamListLengthInSlots(asmArgTypes) > 253;
 788         for (final Type t : asmArgTypes) {
 789             mv.load(varOffset, t);
 790             convertParam(mv, t, isVarArgCall);
 791             varOffset += t.getSize();
 792         }
 793         // stack: [args..., callee, delegate]
 794 
 795         // If the resulting parameter list length is too long...
 796         if (isVarArgCall) {
 797             // ... we pack the parameters (except callee and this) into an array
 798             // and use Nashorn vararg invocation.
 799             mv.visitInvokeDynamicInsn(NameCodec.EMPTY_NAME,
 800                     getArrayCreatorMethodType(type).toMethodDescriptorString(),
 801                     CREATE_ARRAY_BOOTSTRAP_HANDLE);
 802         }
 803 
 804         // Invoke the target method handle
 805         mv.visitInvokeDynamicInsn(encodedName,
 806                 getCallMethodType(isVarArgCall, type).toMethodDescriptorString(),
 807                 BOOTSTRAP_HANDLE, NashornCallSiteDescriptor.CALL);
 808         // stack: [returnValue]
 809         convertReturnValue(mv, returnType);
 810         mv.visitLabel(normalFinally);
 811         emitFinally.run();
 812         mv.areturn(asmReturnType);
 813 
 814         // If Throwable is not declared, we need an adapter from Throwable to RuntimeException
 815         final boolean throwableDeclared = isThrowableDeclared(exceptions);
 816         final Label throwableHandler;
 817         if (!throwableDeclared) {
 818             // Add "throw new RuntimeException(Throwable)" handler for Throwable
 819             throwableHandler = new Label();
 820             mv.visitLabel(throwableHandler);
 821             WRAP_THROWABLE.invoke(mv);
 822             // Fall through to rethrow handler
 823         } else {
 824             throwableHandler = null;
 825         }
 826         final Label rethrowHandler = new Label();
 827         mv.visitLabel(rethrowHandler);
 828         // Rethrow handler for RuntimeException, Error, and all declared exception types
 829         emitFinally.run();
 830         mv.athrow();
 831 
 832         if(throwableDeclared) {
 833             mv.visitTryCatchBlock(tryBlockStart, normalFinally, rethrowHandler, THROWABLE_TYPE_NAME);
 834             assert throwableHandler == null;
 835         } else {
 836             mv.visitTryCatchBlock(tryBlockStart, normalFinally, rethrowHandler, RUNTIME_EXCEPTION_TYPE_NAME);
 837             mv.visitTryCatchBlock(tryBlockStart, normalFinally, rethrowHandler, ERROR_TYPE_NAME);
 838             for(final String excName: exceptionNames) {
 839                 mv.visitTryCatchBlock(tryBlockStart, normalFinally, rethrowHandler, excName);
 840             }
 841             mv.visitTryCatchBlock(tryBlockStart, normalFinally, throwableHandler, THROWABLE_TYPE_NAME);
 842         }
 843         endMethod(mv);
 844     }
 845 
 846     private static MethodType getCallMethodType(final boolean isVarArgCall, final MethodType type) {
 847         final Class<?>[] callParamTypes;
 848         if (isVarArgCall) {
 849             // Variable arity calls are always (Object callee, Object this, Object[] params)
 850             callParamTypes = new Class<?>[] { Object.class, Object.class, Object[].class };
 851         } else {
 852             // Adjust invocation type signature for conversions we instituted in
 853             // convertParam; also, byte and short get passed as ints.
 854             final Class<?>[] origParamTypes = type.parameterArray();
 855             callParamTypes = new Class<?>[origParamTypes.length + 2];
 856             callParamTypes[0] = Object.class; // callee; could be ScriptFunction.class ostensibly
 857             callParamTypes[1] = Object.class; // this
 858             for(int i = 0; i < origParamTypes.length; ++i) {
 859                 callParamTypes[i + 2] = getNashornParamType(origParamTypes[i], false);
 860             }
 861         }
 862         return MethodType.methodType(getNashornReturnType(type.returnType()), callParamTypes);
 863     }
 864 
 865     private static MethodType getArrayCreatorMethodType(final MethodType type) {
 866         final Class<?>[] callParamTypes = type.parameterArray();
 867         for(int i = 0; i < callParamTypes.length; ++i) {
 868             callParamTypes[i] = getNashornParamType(callParamTypes[i], true);
 869         }
 870         return MethodType.methodType(Object[].class, callParamTypes);
 871     }
 872 
 873     private static Class<?> getNashornParamType(final Class<?> clazz, final boolean varArg) {
 874         if (clazz == byte.class || clazz == short.class) {
 875             return int.class;
 876         } else if (clazz == float.class) {
 877             // If using variable arity, we'll pass a Double instead of double
 878             // so that floats don't extend the length of the parameter list.
 879             // We return Object.class instead of Double.class though as the
 880             // array collector will anyway operate on Object.
 881             return varArg ? Object.class : double.class;
 882         } else if (!clazz.isPrimitive() || clazz == long.class || clazz == char.class) {
 883             return Object.class;
 884         }
 885         return clazz;
 886     }
 887 
 888     private static Class<?> getNashornReturnType(final Class<?> clazz) {
 889         if (clazz == byte.class || clazz == short.class) {
 890             return int.class;
 891         } else if (clazz == float.class) {
 892             return double.class;
 893         } else if (clazz == void.class || clazz == char.class) {
 894             return Object.class;
 895         }
 896         return clazz;
 897     }
 898 
 899 
 900     private void loadField(final InstructionAdapter mv, final String name, final String desc) {
 901         if(classOverride) {
 902             mv.getstatic(generatedClassName, name, desc);
 903         } else {
 904             mv.visitVarInsn(ALOAD, 0);
 905             mv.getfield(generatedClassName, name, desc);
 906         }
 907     }
 908 
 909     private static void convertReturnValue(final InstructionAdapter mv, final Class<?> origReturnType) {
 910         if (origReturnType == void.class) {
 911             mv.pop();
 912         } else if (origReturnType == Object.class) {
 913             // Must hide ConsString (and potentially other internal Nashorn types) from callers
 914             EXPORT_RETURN_VALUE.invoke(mv);
 915         } else if (origReturnType == byte.class) {
 916             mv.visitInsn(I2B);
 917         } else if (origReturnType == short.class) {
 918             mv.visitInsn(I2S);
 919         } else if (origReturnType == float.class) {
 920             mv.visitInsn(D2F);
 921         } else if (origReturnType == char.class) {
 922             TO_CHAR_PRIMITIVE.invoke(mv);
 923         }
 924     }
 925 
 926     /**
 927      * Emits instruction for converting a parameter on the top of the stack to
 928      * a type that is understood by Nashorn.
 929      * @param mv the current method visitor
 930      * @param t the type on the top of the stack
 931      * @param varArg if the invocation will be variable arity
 932      */
 933     private static void convertParam(final InstructionAdapter mv, final Type t, final boolean varArg) {
 934         // We perform conversions of some primitives to accommodate types that
 935         // Nashorn can handle.
 936         switch(t.getSort()) {
 937         case Type.CHAR:
 938             // Chars are boxed, as we don't know if the JS code wants to treat
 939             // them as an effective "unsigned short" or as a single-char string.
 940             CHAR_VALUE_OF.invoke(mv);
 941             break;
 942         case Type.FLOAT:
 943             // Floats are widened to double.
 944             mv.visitInsn(Opcodes.F2D);
 945             if (varArg) {
 946                 // We'll be boxing everything anyway for the vararg invocation,
 947                 // so we might as well do it proactively here and thus not cause
 948                 // a widening in the number of slots, as that could even make
 949                 // the array creation invocation go over 255 param slots.
 950                 DOUBLE_VALUE_OF.invoke(mv);
 951             }
 952             break;
 953         case Type.LONG:
 954             // Longs are boxed as Nashorn can't represent them precisely as a
 955             // primitive number.
 956             LONG_VALUE_OF.invoke(mv);
 957             break;
 958         case Type.OBJECT:
 959             if(t.equals(OBJECT_TYPE)) {
 960                 // Object can carry a ScriptObjectMirror and needs to be unwrapped
 961                 // before passing into a Nashorn function.
 962                 UNWRAP.invoke(mv);
 963             }
 964             break;
 965         }
 966     }
 967 
 968     private static int getParamListLengthInSlots(final Type[] paramTypes) {
 969         int len = paramTypes.length;
 970         for(final Type t: paramTypes) {
 971             final int sort = t.getSort();
 972             if (sort == Type.FLOAT || sort == Type.DOUBLE) {
 973                 // Floats are widened to double, so they'll take up two slots.
 974                 // Longs on the other hand are always boxed, so their width
 975                 // becomes 1 and thus they don't contribute an extra slot here.
 976                 ++len;
 977             }
 978         }
 979         return len;
 980     }
 981 
 982     /**
 983      * Emit code to restore the previous Nashorn Context when needed.
 984      * @param mv the instruction adapter
 985      * @param globalRestoringRunnableVar index of the local variable holding the reference to the global restoring Runnable
 986      */
 987     private static void emitFinally(final InstructionAdapter mv, final int globalRestoringRunnableVar) {
 988         mv.visitVarInsn(ALOAD, globalRestoringRunnableVar);
 989         RUN.invoke(mv);
 990     }
 991 
 992     private static boolean isThrowableDeclared(final Class<?>[] exceptions) {
 993         for (final Class<?> exception : exceptions) {
 994             if (exception == Throwable.class) {
 995                 return true;
 996             }
 997         }
 998         return false;
 999     }
1000 
1001     private void generateSuperMethods() {
1002         for(final MethodInfo mi: methodInfos) {
1003             if(!Modifier.isAbstract(mi.method.getModifiers())) {
1004                 generateSuperMethod(mi);
1005             }
1006         }
1007     }
1008 
1009     private void generateSuperMethod(final MethodInfo mi) {
1010         final Method method = mi.method;
1011 
1012         final String methodDesc = mi.type.toMethodDescriptorString();
1013         final String name = mi.getName();
1014 
1015         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method),
1016                 SUPER_PREFIX + name, methodDesc, null, getExceptionNames(method.getExceptionTypes())));
1017         mv.visitCode();
1018 
1019         emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
1020         mv.areturn(Type.getType(mi.type.returnType()));
1021         endMethod(mv);
1022     }
1023 
1024     // find the appropriate super type to use for invokespecial on the given interface
1025     private Class<?> findInvokespecialOwnerFor(final Class<?> cl) {
1026         assert Modifier.isInterface(cl.getModifiers()) : cl + " is not an interface";
1027 
1028         if (cl.isAssignableFrom(superClass)) {
1029             return superClass;
1030         }
1031 
1032         for (final Class<?> iface : interfaces) {
1033             if (cl.isAssignableFrom(iface)) {
1034                 return iface;
1035             }
1036         }
1037 
1038         // we better that interface that extends the given interface!
1039         throw new AssertionError("can't find the class/interface that extends " + cl);
1040     }
1041 
1042     private int emitSuperConstructorCall(final InstructionAdapter mv, final String methodDesc) {
1043         return emitSuperCall(mv, null, INIT, methodDesc, true);
1044     }
1045 
1046     private int emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name, final String methodDesc) {
1047         return emitSuperCall(mv, owner, name, methodDesc, false);
1048     }
1049 
1050     private int emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name, final String methodDesc, final boolean constructor) {
1051         mv.visitVarInsn(ALOAD, 0);
1052         int nextParam = 1;
1053         final Type methodType = Type.getMethodType(methodDesc);
1054         for(final Type t: methodType.getArgumentTypes()) {
1055             mv.load(nextParam, t);
1056             nextParam += t.getSize();
1057         }
1058 
1059         // default method - non-abstract, interface method
1060         if (!constructor && Modifier.isInterface(owner.getModifiers())) {
1061             // we should call default method on the immediate "super" type - not on (possibly)
1062             // the indirectly inherited interface class!
1063             final Class<?> superType = findInvokespecialOwnerFor(owner);
1064             mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(superType), name, methodDesc,
1065                 Modifier.isInterface(superType.getModifiers()));
1066         } else {
1067             mv.invokespecial(superClassName, name, methodDesc, false);
1068         }
1069         return nextParam;
1070     }
1071 
1072     private void generateFinalizerMethods() {
1073         generateFinalizerDelegate();
1074         generateFinalizerOverride();
1075     }
1076 
1077     private void generateFinalizerDelegate() {
1078         // Generate a delegate that will be invoked from the no-permission trampoline. Note it can be private, as we'll
1079         // refer to it with a MethodHandle constant pool entry in the overridden finalize() method (see
1080         // generateFinalizerOverride()).
1081         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PRIVATE | ACC_STATIC,
1082                 FINALIZER_DELEGATE_NAME, FINALIZER_DELEGATE_METHOD_DESCRIPTOR, null, null));
1083 
1084         // Simply invoke super.finalize()
1085         mv.visitVarInsn(ALOAD, 0);
1086         mv.checkcast(Type.getType('L' + generatedClassName + ';'));
1087         mv.invokespecial(superClassName, "finalize", VOID_METHOD_DESCRIPTOR, false);
1088 
1089         mv.visitInsn(RETURN);
1090         endMethod(mv);
1091     }
1092 
1093     private void generateFinalizerOverride() {
1094         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, "finalize",
1095                 VOID_METHOD_DESCRIPTOR, null, null));
1096         // Overridden finalizer will take a MethodHandle to the finalizer delegating method, ...
1097         mv.aconst(new Handle(Opcodes.H_INVOKESTATIC, generatedClassName, FINALIZER_DELEGATE_NAME,
1098                 FINALIZER_DELEGATE_METHOD_DESCRIPTOR, false));
1099         mv.visitVarInsn(ALOAD, 0);
1100         // ...and invoke it through JavaAdapterServices.invokeNoPermissions
1101         INVOKE_NO_PERMISSIONS.invoke(mv);
1102         mv.visitInsn(RETURN);
1103         endMethod(mv);
1104     }
1105 
1106     private static String[] getExceptionNames(final Class<?>[] exceptions) {
1107         final String[] exceptionNames = new String[exceptions.length];
1108         for (int i = 0; i < exceptions.length; ++i) {
1109             exceptionNames[i] = Type.getInternalName(exceptions[i]);
1110         }
1111         return exceptionNames;
1112     }
1113 
1114     private static int getAccessModifiers(final Method method) {
1115         return ACC_PUBLIC | (method.isVarArgs() ? ACC_VARARGS : 0);
1116     }
1117 
1118     /**
1119      * Gathers methods that can be implemented or overridden from the specified type into this factory's
1120      * {@link #methodInfos} set. It will add all non-final, non-static methods that are either public or protected from
1121      * the type if the type itself is public. If the type is a class, the method will recursively invoke itself for its
1122      * superclass and the interfaces it implements, and add further methods that were not directly declared on the
1123      * class.
1124      * @param type the type defining the methods.
1125      */
1126     private void gatherMethods(final Class<?> type) throws AdaptationException {
1127         if (Modifier.isPublic(type.getModifiers())) {
1128             final Method[] typeMethods = type.isInterface() ? type.getMethods() : type.getDeclaredMethods();
1129 
1130             for (final Method typeMethod: typeMethods) {
1131                 final String name = typeMethod.getName();
1132                 if(name.startsWith(SUPER_PREFIX)) {
1133                     continue;
1134                 }
1135                 final int m = typeMethod.getModifiers();
1136                 if (Modifier.isStatic(m)) {
1137                     continue;
1138                 }
1139                 if (Modifier.isPublic(m) || Modifier.isProtected(m)) {
1140                     // Is it a "finalize()"?
1141                     if(name.equals("finalize") && typeMethod.getParameterCount() == 0) {
1142                         if(type != Object.class) {
1143                             hasExplicitFinalizer = true;
1144                             if(Modifier.isFinal(m)) {
1145                                 // Must be able to override an explicit finalizer
1146                                 throw new AdaptationException(Outcome.ERROR_FINAL_FINALIZER, type.getCanonicalName());
1147                             }
1148                         }
1149                         continue;
1150                     }
1151 
1152                     final MethodInfo mi = new MethodInfo(typeMethod);
1153                     if (Modifier.isFinal(m) || isCallerSensitive(typeMethod)) {
1154                         finalMethods.add(mi);
1155                     } else if (!finalMethods.contains(mi) && methodInfos.add(mi) && Modifier.isAbstract(m)) {
1156                         abstractMethodNames.add(mi.getName());
1157                     }
1158                 }
1159             }
1160         }
1161         // If the type is a class, visit its superclasses and declared interfaces. If it's an interface, we're done.
1162         // Needing to invoke the method recursively for a non-interface Class object is the consequence of needing to
1163         // see all declared protected methods, and Class.getDeclaredMethods() doesn't provide those declared in a
1164         // superclass. For interfaces, we used Class.getMethods(), as we're only interested in public ones there, and
1165         // getMethods() does provide those declared in a superinterface.
1166         if (!type.isInterface()) {
1167             final Class<?> superType = type.getSuperclass();
1168             if (superType != null) {
1169                 gatherMethods(superType);
1170             }
1171             for (final Class<?> itf: type.getInterfaces()) {
1172                 gatherMethods(itf);
1173             }
1174         }
1175     }
1176 
1177     private void gatherMethods(final List<Class<?>> classes) throws AdaptationException {
1178         for(final Class<?> c: classes) {
1179             gatherMethods(c);
1180         }
1181     }
1182 
1183     private static final AccessControlContext GET_DECLARED_MEMBERS_ACC_CTXT = ClassAndLoader.createPermAccCtxt("accessDeclaredMembers");
1184 
1185     /**
1186      * Creates a collection of methods that are not final, but we still never allow them to be overridden in adapters,
1187      * as explicitly declaring them automatically is a bad idea. Currently, this means {@code Object.finalize()} and
1188      * {@code Object.clone()}.
1189      * @return a collection of method infos representing those methods that we never override in adapter classes.
1190      */
1191     private static Collection<MethodInfo> getExcludedMethods() {
1192         return AccessController.doPrivileged(new PrivilegedAction<Collection<MethodInfo>>() {
1193             @Override
1194             public Collection<MethodInfo> run() {
1195                 try {
1196                     return Arrays.asList(
1197                             new MethodInfo(Object.class, "finalize"),
1198                             new MethodInfo(Object.class, "clone"));
1199                 } catch (final NoSuchMethodException e) {
1200                     throw new AssertionError(e);
1201                 }
1202             }
1203         }, GET_DECLARED_MEMBERS_ACC_CTXT);
1204     }
1205 
1206     private String getCommonSuperClass(final String type1, final String type2) {
1207         try {
1208             final Class<?> c1 = Class.forName(type1.replace('/', '.'), false, commonLoader);
1209             final Class<?> c2 = Class.forName(type2.replace('/', '.'), false, commonLoader);
1210             if (c1.isAssignableFrom(c2)) {
1211                 return type1;
1212             }
1213             if (c2.isAssignableFrom(c1)) {
1214                 return type2;
1215             }
1216             if (c1.isInterface() || c2.isInterface()) {
1217                 return OBJECT_TYPE.getInternalName();
1218             }
1219             return assignableSuperClass(c1, c2).getName().replace('.', '/');
1220         } catch(final ClassNotFoundException e) {
1221             throw new RuntimeException(e);
1222         }
1223     }
1224 
1225     private static Class<?> assignableSuperClass(final Class<?> c1, final Class<?> c2) {
1226         final Class<?> superClass = c1.getSuperclass();
1227         return superClass.isAssignableFrom(c2) ? superClass : assignableSuperClass(superClass, c2);
1228     }
1229 
1230     private static boolean isCallerSensitive(final AccessibleObject e) {
1231         return e.isAnnotationPresent(CallerSensitive.class);
1232     }
1233 
1234     private static Call lookupServiceMethod(final String name, final Class<?> rtype, final Class<?>... ptypes) {
1235         return staticCallNoLookup(JavaAdapterServices.class, name, rtype, ptypes);
1236     }
1237 }