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;
  27 
  28 import static jdk.nashorn.internal.lookup.Lookup.MH;
  29 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  30 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  31 
  32 import java.io.IOException;
  33 import java.io.ObjectInputStream;
  34 import java.io.Serializable;
  35 import java.lang.invoke.MethodHandle;
  36 import java.lang.invoke.MethodHandles;
  37 import java.lang.invoke.MethodType;
  38 import java.util.Collection;
  39 import java.util.LinkedList;
  40 import java.util.List;
  41 import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
  42 
  43 
  44 /**
  45  * A container for data needed to instantiate a specific {@link ScriptFunction} at runtime.
  46  * Instances of this class are created during codegen and stored in script classes'
  47  * constants array to reduce function instantiation overhead during runtime.
  48  */
  49 public abstract class ScriptFunctionData implements Serializable {
  50     static final int MAX_ARITY = LinkerCallSite.ARGLIMIT;
  51     static {
  52         // Assert it fits in a byte, as that's what we store it in. It's just a size optimization though, so if needed
  53         // "byte arity" field can be widened.
  54         assert MAX_ARITY < 256;
  55     }
  56 
  57     /** Name of the function or "" for anonymous functions */
  58     protected final String name;
  59 
  60     /**
  61      * A list of code versions of a function sorted in ascending order of generic descriptors.
  62      */
  63     protected transient LinkedList<CompiledFunction> code = new LinkedList<>();
  64 
  65     /** Function flags */
  66     protected int flags;
  67 
  68     // Parameter arity of the function, corresponding to "f.length". E.g. "function f(a, b, c) { ... }" arity is 3, and
  69     // some built-in ECMAScript functions have their arity declared by the specification. Note that regardless of this
  70     // value, the function might still be capable of receiving variable number of arguments, see isVariableArity.
  71     private int arity;
  72 
  73     /**
  74      * A pair of method handles used for generic invoker and constructor. Field is volatile as it can be initialized by
  75      * multiple threads concurrently, but we still tolerate a race condition in it as all values stored into it are
  76      * idempotent.
  77      */
  78     private volatile transient GenericInvokers genericInvokers;
  79 
  80     private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class);
  81 
  82     /** Is this a strict mode function? */
  83     public static final int IS_STRICT            = 1 << 0;
  84     /** Is this a built-in function? */
  85     public static final int IS_BUILTIN           = 1 << 1;
  86     /** Is this a constructor function? */
  87     public static final int IS_CONSTRUCTOR       = 1 << 2;
  88     /** Does this function expect a callee argument? */
  89     public static final int NEEDS_CALLEE         = 1 << 3;
  90     /** Does this function make use of the this-object argument? */
  91     public static final int USES_THIS            = 1 << 4;
  92     /** Is this a variable arity function? */
  93     public static final int IS_VARIABLE_ARITY    = 1 << 5;
  94     /** Is this a object literal property getter or setter? */
  95     public static final int IS_PROPERTY_ACCESSOR = 1 << 6;
  96     /** Is this an ES6 method? */
  97     public static final int IS_ES6_METHOD        = 1 << 7;
  98 
  99     /** Flag for strict or built-in functions */
 100     public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
 101     /** Flag for built-in constructors */
 102     public static final int IS_BUILTIN_CONSTRUCTOR = IS_BUILTIN | IS_CONSTRUCTOR;
 103 
 104     private static final long serialVersionUID = 4252901245508769114L;
 105 
 106     /**
 107      * Constructor
 108      *
 109      * @param name  script function name
 110      * @param arity arity
 111      * @param flags the function flags
 112      */
 113     ScriptFunctionData(final String name, final int arity, final int flags) {
 114         this.name  = name;
 115         this.flags = flags;
 116         setArity(arity);
 117     }
 118 
 119     final int getArity() {
 120         return arity;
 121     }
 122 
 123     String getDocumentation() {
 124         return toSource();
 125     }
 126 
 127     String getDocumentationKey() {
 128         return null;
 129     }
 130 
 131     final boolean isVariableArity() {
 132         return (flags & IS_VARIABLE_ARITY) != 0;
 133     }
 134 
 135     /**
 136      * Used from e.g. Native*$Constructors as an explicit call. TODO - make arity immutable and final
 137      * @param arity new arity
 138      */
 139     void setArity(final int arity) {
 140         if(arity < 0 || arity > MAX_ARITY) {
 141             throw new IllegalArgumentException(String.valueOf(arity));
 142         }
 143         this.arity = arity;
 144     }
 145 
 146     /**
 147      * Used from nasgen generated code.
 148      *
 149      * @param docKey documentation key for this function
 150      */
 151     void setDocumentationKey(final String docKey) {
 152     }
 153 
 154 
 155     CompiledFunction bind(final CompiledFunction originalInv, final ScriptFunction fn, final Object self, final Object[] args) {
 156         final MethodHandle boundInvoker = bindInvokeHandle(originalInv.createComposableInvoker(), fn, self, args);
 157 
 158         if (isConstructor()) {
 159             return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.createComposableConstructor(), fn, args), null);
 160         }
 161 
 162         return new CompiledFunction(boundInvoker);
 163     }
 164 
 165     /**
 166      * Is this a ScriptFunction generated with strict semantics?
 167      * @return true if strict, false otherwise
 168      */
 169     public final boolean isStrict() {
 170         return (flags & IS_STRICT) != 0;
 171     }
 172 
 173     /**
 174      * Return the complete internal function name for this
 175      * data, not anonymous or similar. May be identical
 176      * @return internal function name
 177      */
 178     protected String getFunctionName() {
 179         return getName();
 180     }
 181 
 182     final boolean isBuiltin() {
 183         return (flags & IS_BUILTIN) != 0;
 184     }
 185 
 186     final boolean isConstructor() {
 187         return (flags & IS_CONSTRUCTOR) != 0;
 188     }
 189 
 190     abstract boolean needsCallee();
 191 
 192     /**
 193      * Returns true if this is a non-strict, non-built-in function that requires non-primitive this argument
 194      * according to ECMA 10.4.3.
 195      * @return true if this argument must be an object
 196      */
 197     final boolean needsWrappedThis() {
 198         return (flags & USES_THIS) != 0 && (flags & IS_STRICT_OR_BUILTIN) == 0;
 199     }
 200 
 201     String toSource() {
 202         return "function " + (name == null ? "" : name) + "() { [native code] }";
 203     }
 204 
 205     String getName() {
 206         return name;
 207     }
 208 
 209     /**
 210      * Get this function as a String containing its source code. If no source code
 211      * exists in this ScriptFunction, its contents will be displayed as {@code [native code]}
 212      *
 213      * @return string representation of this function
 214      */
 215     @Override
 216     public String toString() {
 217         return name.isEmpty() ? "<anonymous>" : name;
 218     }
 219 
 220     /**
 221      * Verbose description of data
 222      * @return verbose description
 223      */
 224     public String toStringVerbose() {
 225         final StringBuilder sb = new StringBuilder();
 226 
 227         sb.append("name='").
 228                 append(name.isEmpty() ? "<anonymous>" : name).
 229                 append("' ").
 230                 append(code.size()).
 231                 append(" invokers=").
 232                 append(code);
 233 
 234         return sb.toString();
 235     }
 236 
 237     /**
 238      * Pick the best invoker, i.e. the one version of this method with as narrow and specific
 239      * types as possible. If the call site arguments are objects, but boxed primitives we can
 240      * also try to get a primitive version of the method and do an unboxing filter, but then
 241      * we need to insert a guard that checks the argument is really always a boxed primitive
 242      * and not suddenly a "real" object
 243      *
 244      * @param callSiteType callsite type
 245      * @return compiled function object representing the best invoker.
 246      */
 247     final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope) {
 248         return getBestInvoker(callSiteType, runtimeScope, CompiledFunction.NO_FUNCTIONS);
 249     }
 250 
 251     final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
 252         final CompiledFunction cf = getBest(callSiteType, runtimeScope, forbidden);
 253         assert cf != null;
 254         return cf;
 255     }
 256 
 257     final CompiledFunction getBestConstructor(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
 258         if (!isConstructor()) {
 259             throw typeError("not.a.constructor", toSource());
 260         }
 261         // Constructor call sites don't have a "this", but getBest is meant to operate on "callee, this, ..." style
 262         final CompiledFunction cf = getBest(callSiteType.insertParameterTypes(1, Object.class), runtimeScope, forbidden);
 263         return cf;
 264     }
 265 
 266     /**
 267      * If we can have lazy code generation, this is a hook to ensure that the code has been compiled.
 268      * This does not guarantee the code been installed in this {@code ScriptFunctionData} instance
 269      */
 270     protected void ensureCompiled() {
 271         //empty
 272     }
 273 
 274     /**
 275      * Return a generic Object/Object invoker for this method. It will ensure code
 276      * is generated, get the most generic of all versions of this function and adapt it
 277      * to Objects.
 278      *
 279      * @param runtimeScope the runtime scope. It can be used to evaluate types of scoped variables to guide the
 280      * optimistic compilation, should the call to this method trigger code compilation. Can be null if current runtime
 281      * scope is not known, but that might cause compilation of code that will need more deoptimization passes.
 282      * @return generic invoker of this script function
 283      */
 284     final MethodHandle getGenericInvoker(final ScriptObject runtimeScope) {
 285         // This method has race conditions both on genericsInvoker and genericsInvoker.invoker, but even if invoked
 286         // concurrently, they'll create idempotent results, so it doesn't matter. We could alternatively implement this
 287         // using java.util.concurrent.AtomicReferenceFieldUpdater, but it's hardly worth it.
 288         final GenericInvokers lgenericInvokers = ensureGenericInvokers();
 289         MethodHandle invoker = lgenericInvokers.invoker;
 290         if(invoker == null) {
 291             lgenericInvokers.invoker = invoker = createGenericInvoker(runtimeScope);
 292         }
 293         return invoker;
 294     }
 295 
 296     private MethodHandle createGenericInvoker(final ScriptObject runtimeScope) {
 297         return makeGenericMethod(getGeneric(runtimeScope).createComposableInvoker());
 298     }
 299 
 300     final MethodHandle getGenericConstructor(final ScriptObject runtimeScope) {
 301         // This method has race conditions both on genericsInvoker and genericsInvoker.constructor, but even if invoked
 302         // concurrently, they'll create idempotent results, so it doesn't matter. We could alternatively implement this
 303         // using java.util.concurrent.AtomicReferenceFieldUpdater, but it's hardly worth it.
 304         final GenericInvokers lgenericInvokers = ensureGenericInvokers();
 305         MethodHandle constructor = lgenericInvokers.constructor;
 306         if(constructor == null) {
 307             lgenericInvokers.constructor = constructor = createGenericConstructor(runtimeScope);
 308         }
 309         return constructor;
 310     }
 311 
 312     private MethodHandle createGenericConstructor(final ScriptObject runtimeScope) {
 313         return makeGenericMethod(getGeneric(runtimeScope).createComposableConstructor());
 314     }
 315 
 316     private GenericInvokers ensureGenericInvokers() {
 317         GenericInvokers lgenericInvokers = genericInvokers;
 318         if(lgenericInvokers == null) {
 319             genericInvokers = lgenericInvokers = new GenericInvokers();
 320         }
 321         return lgenericInvokers;
 322     }
 323 
 324     private static MethodType widen(final MethodType cftype) {
 325         final Class<?>[] paramTypes = new Class<?>[cftype.parameterCount()];
 326         for (int i = 0; i < cftype.parameterCount(); i++) {
 327             paramTypes[i] = cftype.parameterType(i).isPrimitive() ? cftype.parameterType(i) : Object.class;
 328         }
 329         return MH.type(cftype.returnType(), paramTypes);
 330     }
 331 
 332     /**
 333      * Used to find an apply to call version that fits this callsite.
 334      * We cannot just, as in the normal matcher case, return e.g. (Object, Object, int)
 335      * for (Object, Object, int, int, int) or we will destroy the semantics and get
 336      * a function that, when padded with undefined values, behaves differently
 337      * @param type actual call site type
 338      * @return apply to call that perfectly fits this callsite or null if none found
 339      */
 340     CompiledFunction lookupExactApplyToCall(final MethodType type) {
 341         // Callsite type always has callee, drop it if this function doesn't need it.
 342         final MethodType adaptedType = needsCallee() ? type : type.dropParameterTypes(0, 1);
 343 
 344         for (final CompiledFunction cf : code) {
 345             if (!cf.isApplyToCall()) {
 346                 continue;
 347             }
 348 
 349             final MethodType cftype = cf.type();
 350             if (cftype.parameterCount() != adaptedType.parameterCount()) {
 351                 continue;
 352             }
 353 
 354             if (widen(cftype).equals(widen(adaptedType))) {
 355                 return cf;
 356             }
 357         }
 358 
 359         return null;
 360     }
 361 
 362     CompiledFunction pickFunction(final MethodType callSiteType, final boolean canPickVarArg) {
 363         for (final CompiledFunction candidate : code) {
 364             if (candidate.matchesCallSite(callSiteType, canPickVarArg)) {
 365                 return candidate;
 366             }
 367         }
 368         return null;
 369     }
 370 
 371     /**
 372      * Returns the best function for the specified call site type.
 373      * @param callSiteType The call site type. Call site types are expected to have the form
 374      * {@code (callee, this[, args...])}.
 375      * @param runtimeScope the runtime scope. It can be used to evaluate types of scoped variables to guide the
 376      * optimistic compilation, should the call to this method trigger code compilation. Can be null if current runtime
 377      * scope is not known, but that might cause compilation of code that will need more deoptimization passes.
 378      * @param linkLogicOkay is a CompiledFunction with a LinkLogic acceptable?
 379      * @return the best function for the specified call site type.
 380      */
 381     abstract CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden, final boolean linkLogicOkay);
 382 
 383     /**
 384      * Returns the best function for the specified call site type.
 385      * @param callSiteType The call site type. Call site types are expected to have the form
 386      * {@code (callee, this[, args...])}.
 387      * @param runtimeScope the runtime scope. It can be used to evaluate types of scoped variables to guide the
 388      * optimistic compilation, should the call to this method trigger code compilation. Can be null if current runtime
 389      * scope is not known, but that might cause compilation of code that will need more deoptimization passes.
 390      * @return the best function for the specified call site type.
 391      */
 392     final CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
 393         return getBest(callSiteType, runtimeScope, forbidden, true);
 394     }
 395 
 396     boolean isValidCallSite(final MethodType callSiteType) {
 397         return callSiteType.parameterCount() >= 2  && // Must have at least (callee, this)
 398                callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class); // Callee must be assignable from script function
 399     }
 400 
 401     CompiledFunction getGeneric(final ScriptObject runtimeScope) {
 402         return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS, false);
 403     }
 404 
 405     /**
 406      * Get a method type for a generic invoker.
 407      * @return the method type for the generic invoker
 408      */
 409     abstract MethodType getGenericType();
 410 
 411     /**
 412      * Allocates an object using this function's allocator.
 413      *
 414      * @param map the property map for the allocated object.
 415      * @return the object allocated using this function's allocator, or null if the function doesn't have an allocator.
 416      */
 417     ScriptObject allocate(final PropertyMap map) {
 418         return null;
 419     }
 420 
 421     /**
 422      * Get the property map to use for objects allocated by this function.
 423      *
 424      * @param prototype the prototype of the allocated object
 425      * @return the property map for allocated objects.
 426      */
 427     PropertyMap getAllocatorMap(final ScriptObject prototype) {
 428         return null;
 429     }
 430 
 431     /**
 432      * This method is used to create the immutable portion of a bound function.
 433      * See {@link ScriptFunction#createBound(Object, Object[])}
 434      *
 435      * @param fn the original function being bound
 436      * @param self this reference to bind. Can be null.
 437      * @param args additional arguments to bind. Can be null.
 438      */
 439     ScriptFunctionData makeBoundFunctionData(final ScriptFunction fn, final Object self, final Object[] args) {
 440         final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args;
 441         final int length = args == null ? 0 : args.length;
 442         // Clear the callee and this flags
 443         final int boundFlags = flags & ~NEEDS_CALLEE & ~USES_THIS;
 444 
 445         final List<CompiledFunction> boundList = new LinkedList<>();
 446         final ScriptObject runtimeScope = fn.getScope();
 447         final CompiledFunction bindTarget = new CompiledFunction(getGenericInvoker(runtimeScope), getGenericConstructor(runtimeScope), null);
 448         boundList.add(bind(bindTarget, fn, self, allArgs));
 449 
 450         return new FinalScriptFunctionData(name, Math.max(0, getArity() - length), boundList, boundFlags);
 451     }
 452 
 453     /**
 454      * Convert this argument for non-strict functions according to ES 10.4.3
 455      *
 456      * @param thiz the this argument
 457      *
 458      * @return the converted this object
 459      */
 460     private Object convertThisObject(final Object thiz) {
 461         return needsWrappedThis() ? wrapThis(thiz) : thiz;
 462     }
 463 
 464     static Object wrapThis(final Object thiz) {
 465         if (!(thiz instanceof ScriptObject)) {
 466             if (JSType.nullOrUndefined(thiz)) {
 467                 return Context.getGlobal();
 468             }
 469 
 470             if (isPrimitiveThis(thiz)) {
 471                 return Context.getGlobal().wrapAsObject(thiz);
 472             }
 473         }
 474 
 475         return thiz;
 476     }
 477 
 478     static boolean isPrimitiveThis(final Object obj) {
 479         return JSType.isString(obj) || obj instanceof Number || obj instanceof Boolean;
 480     }
 481 
 482     /**
 483      * Creates an invoker method handle for a bound function.
 484      *
 485      * @param targetFn the function being bound
 486      * @param originalInvoker an original invoker method handle for the function. This can be its generic invoker or
 487      * any of its specializations.
 488      * @param self the "this" value being bound
 489      * @param args additional arguments being bound
 490      *
 491      * @return a bound invoker method handle that will bind the self value and the specified arguments. The resulting
 492      * invoker never needs a callee; if the original invoker needed it, it will be bound to {@code fn}. The resulting
 493      * invoker still takes an initial {@code this} parameter, but it is always dropped and the bound {@code self} passed
 494      * to the original invoker on invocation.
 495      */
 496     private MethodHandle bindInvokeHandle(final MethodHandle originalInvoker, final ScriptFunction targetFn, final Object self, final Object[] args) {
 497         // Is the target already bound? If it is, we won't bother binding either callee or self as they're already bound
 498         // in the target and will be ignored anyway.
 499         final boolean isTargetBound = targetFn.isBoundFunction();
 500 
 501         final boolean needsCallee = needsCallee(originalInvoker);
 502         assert needsCallee == needsCallee() : "callee contract violation 2";
 503         assert !(isTargetBound && needsCallee); // already bound functions don't need a callee
 504 
 505         final Object boundSelf = isTargetBound ? null : convertThisObject(self);
 506         final MethodHandle boundInvoker;
 507 
 508         if (isVarArg(originalInvoker)) {
 509             // First, bind callee and this without arguments
 510             final MethodHandle noArgBoundInvoker;
 511 
 512             if (isTargetBound) {
 513                 // Don't bind either callee or this
 514                 noArgBoundInvoker = originalInvoker;
 515             } else if (needsCallee) {
 516                 // Bind callee and this
 517                 noArgBoundInvoker = MH.insertArguments(originalInvoker, 0, targetFn, boundSelf);
 518             } else {
 519                 // Only bind this
 520                 noArgBoundInvoker = MH.bindTo(originalInvoker, boundSelf);
 521             }
 522             // Now bind arguments
 523             if (args.length > 0) {
 524                 boundInvoker = varArgBinder(noArgBoundInvoker, args);
 525             } else {
 526                 boundInvoker = noArgBoundInvoker;
 527             }
 528         } else {
 529             // If target is already bound, insert additional bound arguments after "this" argument, at position 1.
 530             final int argInsertPos = isTargetBound ? 1 : 0;
 531             final Object[] boundArgs = new Object[Math.min(originalInvoker.type().parameterCount() - argInsertPos, args.length + (isTargetBound ? 0 : needsCallee  ? 2 : 1))];
 532             int next = 0;
 533             if (!isTargetBound) {
 534                 if (needsCallee) {
 535                     boundArgs[next++] = targetFn;
 536                 }
 537                 boundArgs[next++] = boundSelf;
 538             }
 539             // If more bound args were specified than the function can take, we'll just drop those.
 540             System.arraycopy(args, 0, boundArgs, next, boundArgs.length - next);
 541             // If target is already bound, insert additional bound arguments after "this" argument, at position 1;
 542             // "this" will get dropped anyway by the target invoker. We previously asserted that already bound functions
 543             // don't take a callee parameter, so we can know that the signature is (this[, args...]) therefore args
 544             // start at position 1. If the function is not bound, we start inserting arguments at position 0.
 545             boundInvoker = MH.insertArguments(originalInvoker, argInsertPos, boundArgs);
 546         }
 547 
 548         if (isTargetBound) {
 549             return boundInvoker;
 550         }
 551 
 552         // If the target is not already bound, add a dropArguments that'll throw away the passed this
 553         return MH.dropArguments(boundInvoker, 0, Object.class);
 554     }
 555 
 556     /**
 557      * Creates a constructor method handle for a bound function using the passed constructor handle.
 558      *
 559      * @param originalConstructor the constructor handle to bind. It must be a composed constructor.
 560      * @param fn the function being bound
 561      * @param args arguments being bound
 562      *
 563      * @return a bound constructor method handle that will bind the specified arguments. The resulting constructor never
 564      * needs a callee; if the original constructor needed it, it will be bound to {@code fn}. The resulting constructor
 565      * still takes an initial {@code this} parameter and passes it to the underlying original constructor. Finally, if
 566      * this script function data object has no constructor handle, null is returned.
 567      */
 568     private static MethodHandle bindConstructHandle(final MethodHandle originalConstructor, final ScriptFunction fn, final Object[] args) {
 569         assert originalConstructor != null;
 570 
 571         // If target function is already bound, don't bother binding the callee.
 572         final MethodHandle calleeBoundConstructor = fn.isBoundFunction() ? originalConstructor :
 573             MH.dropArguments(MH.bindTo(originalConstructor, fn), 0, ScriptFunction.class);
 574 
 575         if (args.length == 0) {
 576             return calleeBoundConstructor;
 577         }
 578 
 579         if (isVarArg(calleeBoundConstructor)) {
 580             return varArgBinder(calleeBoundConstructor, args);
 581         }
 582 
 583         final Object[] boundArgs;
 584 
 585         final int maxArgCount = calleeBoundConstructor.type().parameterCount() - 1;
 586         if (args.length <= maxArgCount) {
 587             boundArgs = args;
 588         } else {
 589             boundArgs = new Object[maxArgCount];
 590             System.arraycopy(args, 0, boundArgs, 0, maxArgCount);
 591         }
 592 
 593         return MH.insertArguments(calleeBoundConstructor, 1, boundArgs);
 594     }
 595 
 596     /**
 597      * Takes a method handle, and returns a potentially different method handle that can be used in
 598      * {@code ScriptFunction#invoke(Object, Object...)} or {code ScriptFunction#construct(Object, Object...)}.
 599      * The returned method handle will be sure to return {@code Object}, and will have all its parameters turned into
 600      * {@code Object} as well, except for the following ones:
 601      * <ul>
 602      *   <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li>
 603      *   <li>the first argument, which is forced to be {@link ScriptFunction}, in case the function receives itself
 604      *   (callee) as an argument.</li>
 605      * </ul>
 606      *
 607      * @param mh the original method handle
 608      *
 609      * @return the new handle, conforming to the rules above.
 610      */
 611     private static MethodHandle makeGenericMethod(final MethodHandle mh) {
 612         final MethodType type = mh.type();
 613         final MethodType newType = makeGenericType(type);
 614         return type.equals(newType) ? mh : mh.asType(newType);
 615     }
 616 
 617     private static MethodType makeGenericType(final MethodType type) {
 618         MethodType newType = type.generic();
 619         if (isVarArg(type)) {
 620             newType = newType.changeParameterType(type.parameterCount() - 1, Object[].class);
 621         }
 622         if (needsCallee(type)) {
 623             newType = newType.changeParameterType(0, ScriptFunction.class);
 624         }
 625         return newType;
 626     }
 627 
 628     /**
 629      * Execute this script function.
 630      *
 631      * @param self  Target object.
 632      * @param arguments  Call arguments.
 633      * @return ScriptFunction result.
 634      *
 635      * @throws Throwable if there is an exception/error with the invocation or thrown from it
 636      */
 637     Object invoke(final ScriptFunction fn, final Object self, final Object... arguments) throws Throwable {
 638         final MethodHandle mh      = getGenericInvoker(fn.getScope());
 639         final Object       selfObj = convertThisObject(self);
 640         final Object[]     args    = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;
 641 
 642         DebuggerSupport.notifyInvoke(mh);
 643 
 644         if (isVarArg(mh)) {
 645             if (needsCallee(mh)) {
 646                 return mh.invokeExact(fn, selfObj, args);
 647             }
 648             return mh.invokeExact(selfObj, args);
 649         }
 650 
 651         final int paramCount = mh.type().parameterCount();
 652         if (needsCallee(mh)) {
 653             switch (paramCount) {
 654             case 2:
 655                 return mh.invokeExact(fn, selfObj);
 656             case 3:
 657                 return mh.invokeExact(fn, selfObj, getArg(args, 0));
 658             case 4:
 659                 return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1));
 660             case 5:
 661                 return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2));
 662             case 6:
 663                 return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3));
 664             case 7:
 665                 return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4));
 666             case 8:
 667                 return mh.invokeExact(fn, selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5));
 668             default:
 669                 return mh.invokeWithArguments(withArguments(fn, selfObj, paramCount, args));
 670             }
 671         }
 672 
 673         switch (paramCount) {
 674         case 1:
 675             return mh.invokeExact(selfObj);
 676         case 2:
 677             return mh.invokeExact(selfObj, getArg(args, 0));
 678         case 3:
 679             return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1));
 680         case 4:
 681             return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2));
 682         case 5:
 683             return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3));
 684         case 6:
 685             return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4));
 686         case 7:
 687             return mh.invokeExact(selfObj, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5));
 688         default:
 689             return mh.invokeWithArguments(withArguments(null, selfObj, paramCount, args));
 690         }
 691     }
 692 
 693     Object construct(final ScriptFunction fn, final Object... arguments) throws Throwable {
 694         final MethodHandle mh   = getGenericConstructor(fn.getScope());
 695         final Object[]     args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;
 696 
 697         DebuggerSupport.notifyInvoke(mh);
 698 
 699         if (isVarArg(mh)) {
 700             if (needsCallee(mh)) {
 701                 return mh.invokeExact(fn, args);
 702             }
 703             return mh.invokeExact(args);
 704         }
 705 
 706         final int paramCount = mh.type().parameterCount();
 707         if (needsCallee(mh)) {
 708             switch (paramCount) {
 709             case 1:
 710                 return mh.invokeExact(fn);
 711             case 2:
 712                 return mh.invokeExact(fn, getArg(args, 0));
 713             case 3:
 714                 return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1));
 715             case 4:
 716                 return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2));
 717             case 5:
 718                 return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3));
 719             case 6:
 720                 return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4));
 721             case 7:
 722                 return mh.invokeExact(fn, getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5));
 723             default:
 724                 return mh.invokeWithArguments(withArguments(fn, paramCount, args));
 725             }
 726         }
 727 
 728         switch (paramCount) {
 729         case 0:
 730             return mh.invokeExact();
 731         case 1:
 732             return mh.invokeExact(getArg(args, 0));
 733         case 2:
 734             return mh.invokeExact(getArg(args, 0), getArg(args, 1));
 735         case 3:
 736             return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2));
 737         case 4:
 738             return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3));
 739         case 5:
 740             return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4));
 741         case 6:
 742             return mh.invokeExact(getArg(args, 0), getArg(args, 1), getArg(args, 2), getArg(args, 3), getArg(args, 4), getArg(args, 5));
 743         default:
 744             return mh.invokeWithArguments(withArguments(null, paramCount, args));
 745         }
 746     }
 747 
 748     private static Object getArg(final Object[] args, final int i) {
 749         return i < args.length ? args[i] : UNDEFINED;
 750     }
 751 
 752     private static Object[] withArguments(final ScriptFunction fn, final int argCount, final Object[] args) {
 753         final Object[] finalArgs = new Object[argCount];
 754 
 755         int nextArg = 0;
 756         if (fn != null) {
 757             //needs callee
 758             finalArgs[nextArg++] = fn;
 759         }
 760 
 761         // Don't add more args that there is argCount in the handle (including self and callee).
 762         for (int i = 0; i < args.length && nextArg < argCount;) {
 763             finalArgs[nextArg++] = args[i++];
 764         }
 765 
 766         // If we have fewer args than argCount, pad with undefined.
 767         while (nextArg < argCount) {
 768             finalArgs[nextArg++] = UNDEFINED;
 769         }
 770 
 771         return finalArgs;
 772     }
 773 
 774     private static Object[] withArguments(final ScriptFunction fn, final Object self, final int argCount, final Object[] args) {
 775         final Object[] finalArgs = new Object[argCount];
 776 
 777         int nextArg = 0;
 778         if (fn != null) {
 779             //needs callee
 780             finalArgs[nextArg++] = fn;
 781         }
 782         finalArgs[nextArg++] = self;
 783 
 784         // Don't add more args that there is argCount in the handle (including self and callee).
 785         for (int i = 0; i < args.length && nextArg < argCount;) {
 786             finalArgs[nextArg++] = args[i++];
 787         }
 788 
 789         // If we have fewer args than argCount, pad with undefined.
 790         while (nextArg < argCount) {
 791             finalArgs[nextArg++] = UNDEFINED;
 792         }
 793 
 794         return finalArgs;
 795     }
 796     /**
 797      * Takes a variable-arity method and binds a variable number of arguments in it. The returned method will filter the
 798      * vararg array and pass a different array that prepends the bound arguments in front of the arguments passed on
 799      * invocation
 800      *
 801      * @param mh the handle
 802      * @param args the bound arguments
 803      *
 804      * @return the bound method handle
 805      */
 806     private static MethodHandle varArgBinder(final MethodHandle mh, final Object[] args) {
 807         assert args != null;
 808         assert args.length > 0;
 809         return MH.filterArguments(mh, mh.type().parameterCount() - 1, MH.bindTo(BIND_VAR_ARGS, args));
 810     }
 811 
 812     /**
 813      * Heuristic to figure out if the method handle has a callee argument. If it's type is
 814      * {@code (ScriptFunction, ...)}, then we'll assume it has a callee argument. We need this as
 815      * the constructor above is not passed this information, and can't just blindly assume it's false
 816      * (notably, it's being invoked for creation of new scripts, and scripts have scopes, therefore
 817      * they also always receive a callee).
 818      *
 819      * @param mh the examined method handle
 820      *
 821      * @return true if the method handle expects a callee, false otherwise
 822      */
 823     protected static boolean needsCallee(final MethodHandle mh) {
 824         return needsCallee(mh.type());
 825     }
 826 
 827     static boolean needsCallee(final MethodType type) {
 828         final int length = type.parameterCount();
 829 
 830         if (length == 0) {
 831             return false;
 832         }
 833 
 834         final Class<?> param0 = type.parameterType(0);
 835         return param0 == ScriptFunction.class || param0 == boolean.class && length > 1 && type.parameterType(1) == ScriptFunction.class;
 836     }
 837 
 838     /**
 839      * Check if a javascript function methodhandle is a vararg handle
 840      *
 841      * @param mh method handle to check
 842      *
 843      * @return true if vararg
 844      */
 845     protected static boolean isVarArg(final MethodHandle mh) {
 846         return isVarArg(mh.type());
 847     }
 848 
 849     static boolean isVarArg(final MethodType type) {
 850         return type.parameterType(type.parameterCount() - 1).isArray();
 851     }
 852 
 853     /**
 854      * Is this ScriptFunction declared in a dynamic context
 855      * @return true if in dynamic context, false if not or irrelevant
 856      */
 857     public boolean inDynamicContext() {
 858         return false;
 859     }
 860 
 861     @SuppressWarnings("unused")
 862     private static Object[] bindVarArgs(final Object[] array1, final Object[] array2) {
 863         if (array2 == null) {
 864             // Must clone it, as we can't allow the receiving method to alter the array
 865             return array1.clone();
 866         }
 867 
 868         final int l2 = array2.length;
 869         if (l2 == 0) {
 870             return array1.clone();
 871         }
 872 
 873         final int l1 = array1.length;
 874         final Object[] concat = new Object[l1 + l2];
 875         System.arraycopy(array1, 0, concat, 0, l1);
 876         System.arraycopy(array2, 0, concat, l1, l2);
 877 
 878         return concat;
 879     }
 880 
 881     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
 882         return MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, name, MH.type(rtype, types));
 883     }
 884 
 885     /**
 886      * This class is used to hold the generic invoker and generic constructor pair. It is structured in this way since
 887      * most functions will never use them, so this way ScriptFunctionData only pays storage cost for one null reference
 888      * to the GenericInvokers object, instead of two null references for the two method handles.
 889      */
 890     private static final class GenericInvokers {
 891         volatile MethodHandle invoker;
 892         volatile MethodHandle constructor;
 893     }
 894 
 895     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
 896         in.defaultReadObject();
 897         code = new LinkedList<>();
 898     }
 899 }