src/jdk/nashorn/internal/runtime/ScriptFunctionData.java

Print this page

        

@@ -45,37 +45,49 @@
     protected final String name;
 
     /** All versions of this function that have been generated to code */
     protected final CompiledFunctions code;
 
-    private int arity;
-
-    private final boolean isStrict;
-
-    private final boolean isBuiltin;
+    /** Function flags */
+    protected int flags;
 
-    private final boolean isConstructor;
+    private int arity;
 
     private static final MethodHandle NEWFILTER     = findOwnMH("newFilter", Object.class, Object.class, Object.class);
     private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class);
 
+    /** Is this a strict mode function? */
+    public static final int IS_STRICT      = 0b0000_0001;
+    /** Is this a built-in function? */
+    public static final int IS_BUILTIN     = 0b0000_0010;
+    /** Is this a constructor function? */
+    public static final int IS_CONSTRUCTOR = 0b0000_0100;
+    /** Does this function expect a callee argument? */
+    public static final int NEEDS_CALLEE   = 0b0000_1000;
+    /** Does this function make use of the this-object argument? */
+    public static final int USES_THIS      = 0b0001_0000;
+
+    /** Flag for strict or built-in functions */
+    public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
+    /** Flag for built-in constructors */
+    public static final int IS_BUILTIN_CONSTRUCTOR = IS_BUILTIN | IS_CONSTRUCTOR;
+    /** Flag for strict constructors */
+    public static final int IS_STRICT_CONSTRUCTOR = IS_STRICT | IS_CONSTRUCTOR;
+
+
     /**
      * Constructor
      *
      * @param name          script function name
      * @param arity         arity
-     * @param isStrict      is the function strict
-     * @param isBuiltin     is the function built in
-     * @param isConstructor is the function a constructor
+     * @param flags         the function flags
      */
-    ScriptFunctionData(final String name, final int arity, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) {
+    ScriptFunctionData(final String name, final int arity, final int flags) {
         this.name          = name;
         this.arity         = arity;
         this.code          = new CompiledFunctions();
-        this.isStrict      = isStrict;
-        this.isBuiltin     = isBuiltin;
-        this.isConstructor = isConstructor;
+        this.flags = flags;
     }
 
     final int getArity() {
         return arity;
     }

@@ -103,34 +115,34 @@
     /**
      * Is this a ScriptFunction generated with strict semantics?
      * @return true if strict, false otherwise
      */
     public boolean isStrict() {
-        return isStrict;
+        return (flags & IS_STRICT) != 0;
     }
 
     boolean isBuiltin() {
-        return isBuiltin;
+        return (flags & IS_BUILTIN) != 0;
     }
 
     boolean isConstructor() {
-        return isConstructor;
+        return (flags & IS_CONSTRUCTOR) != 0;
     }
 
     boolean needsCallee() {
-        // we don't know if we need a callee or not unless we are generated
-        ensureCodeGenerated();
-        return code.needsCallee();
+        // we don't know if we need a callee or not unless code has been compiled
+        ensureCompiled();
+        return (flags & NEEDS_CALLEE) != 0;
     }
 
     /**
      * Returns true if this is a non-strict, non-built-in function that requires non-primitive this argument
      * according to ECMA 10.4.3.
      * @return true if this argument must be an object
      */
     boolean needsWrappedThis() {
-        return !isStrict && !isBuiltin;
+        return (flags & USES_THIS) != 0 && (flags & IS_STRICT_OR_BUILTIN) == 0;
     }
 
     String toSource() {
         return "function " + (name == null ? "" : name) + "() { [native code] }";
     }

@@ -200,10 +212,19 @@
     protected void ensureCodeGenerated() {
         //empty
     }
 
     /**
+     * If we can have lazy code generation, this is a hook to ensure that the code has been compiled.
+     * This does not guarantee the code been installed in this {@code ScriptFunctionData} instance;
+     * use {@link #ensureCodeGenerated()} to install the actual method handles.
+     */
+    protected void ensureCompiled() {
+        //empty
+    }
+
+    /**
      * Return a generic Object/Object invoker for this method. It will ensure code
      * is generated, get the most generic of all versions of this function and adapt it
      * to Objects.
      *
      * TODO this is only public because {@link JavaAdapterFactory} can't supply us with

@@ -257,10 +278,12 @@
     ScriptFunctionData makeBoundFunctionData(final ScriptFunction fn, final Object self, final Object[] args) {
         ensureCodeGenerated();
 
         final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args;
         final int length = args == null ? 0 : args.length;
+        // Clear the callee and this flags
+        final int boundFlags = flags & ~NEEDS_CALLEE & ~USES_THIS;
 
         CompiledFunctions boundList = new CompiledFunctions();
         if (code.size() == 1) {
             // only one variant - bind that
             boundList.add(bind(code.first(), fn, self, allArgs));

@@ -271,12 +294,11 @@
             final MethodHandle genInvoker = getGenericInvoker();
             final CompiledFunction inv = new CompiledFunction(genInvoker.type(), genInvoker, getGenericConstructor());
             boundList.add(bind(inv, fn, self, allArgs));
         }
 
-        ScriptFunctionData boundData = new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, isStrict(), isBuiltin(), isConstructor());
-        return boundData;
+        return new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, boundFlags);
     }
 
     /**
      * Compose a constructor given a primordial constructor handle.
      *