src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java

Print this page




  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.objects;
  27 
  28 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  29 import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
  30 
  31 import java.lang.invoke.MethodHandle;
  32 import java.lang.invoke.MethodHandles;


  33 import jdk.nashorn.internal.codegen.objects.FunctionObjectCreator;
  34 import jdk.nashorn.internal.runtime.GlobalFunctions;
  35 import jdk.nashorn.internal.runtime.Property;
  36 import jdk.nashorn.internal.runtime.PropertyMap;
  37 import jdk.nashorn.internal.runtime.ScriptFunction;
  38 import jdk.nashorn.internal.runtime.ScriptObject;
  39 import jdk.nashorn.internal.runtime.ScriptRuntime;
  40 import jdk.nashorn.internal.runtime.Source;
  41 import jdk.nashorn.internal.runtime.linker.Lookup;
  42 import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
  43 
  44 /**
  45  * Concrete implementation of ScriptFunction. This sets correct map for the
  46  * function objects -- to expose properties like "prototype", "length" etc.
  47  */
  48 public class ScriptFunctionImpl extends ScriptFunction {
  49     // per-function object flags
  50     private static final int IS_STRICT  = 0b0000_0001;
  51     private static final int IS_BUILTIN = 0b0000_0010;
  52     private static final int HAS_CALLEE = 0b0000_0100;
  53 
  54     // set this function to be a builtin function
  55     private void setIsBuiltin() {
  56         flags |= IS_BUILTIN;
  57     }
  58 
  59     // set this function to be a ECMAScript strict function
  60     private void setIsStrict() {
  61         flags |= IS_STRICT;
  62     }
  63 
  64     private static final MethodHandle BOUND_FUNCTION    = findOwnMH("boundFunction",    Object.class, ScriptFunction.class, Object.class, Object[].class, Object.class, Object[].class);
  65     private static final MethodHandle BOUND_CONSTRUCTOR = findOwnMH("boundConstructor", Object.class, ScriptFunction.class, Object[].class, Object.class, Object[].class);
  66 
  67     private static final PropertyMap nasgenmap$;
  68 
  69     private int flags;
  70 
  71     /**
  72      * Constructor
  73      *
  74      * Called by Nasgen generated code, no membercount, use the default map
  75      * Creates builtin functions only
  76      *
  77      * @param name name of function
  78      * @param invokeHandle handle for invocation
  79      * @param specs specialized versions of this method, if available, null otherwise
  80      */
  81     ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs) {
  82         this(name, invokeHandle, nasgenmap$, specs);

  83     }
  84 
  85     /**
  86      * Constructor
  87      *
  88      * Called by Nasgen generated code, no membercount, use the default map
  89      * Creates builtin functions only
  90      *
  91      * @param name name of function
  92      * @param methodHandle handle for invocation
  93      * @param map initial property map
  94      * @param specs specialized versions of this method, if available, null otherwise
  95      */
  96     ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final PropertyMap map, final MethodHandle[] specs) {
  97         super(name, methodHandle, (nasgenmap$ == map) ? nasgenmap$ : map.addAll(nasgenmap$), null, null, 0, false, specs);
  98         this.setIsBuiltin();
  99         init();
 100     }
 101 
 102     /**
 103      * Constructor
 104      *
 105      * Called by Global.newScriptFunction (runtime)
 106      *
 107      * @param name name of function
 108      * @param methodHandle handle for invocation
 109      * @param scope scope object
 110      * @param strict are we in strict mode
 111      * @param specs specialized versions of this method, if available, null otherwise


 112      */
 113     ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final boolean strict, final MethodHandle[] specs) {
 114         super(name, methodHandle, getMap(strict), scope, specs);
 115         if (strict) {
 116             this.setIsStrict();
 117         }
 118         init();
 119     }
 120 
 121     /**
 122      * Constructor
 123      *
 124      * Called by (compiler) generated code for {@link ScriptObject}s. Code is
 125      * generated by {@link FunctionObjectCreator}
 126      *
 127      * TODO this is a horrible constructor - can we do it with fewer args?
 128      *
 129      * @param name name of function
 130      * @param methodHandle handle for invocation
 131      * @param scope scope object
 132      * @param source source
 133      * @param token token
 134      * @param allocator instance constructor for function
 135      * @param allocatorMap initial map that constructor will keep reference to for future instantiations
 136      * @param needCallee does the function use the {@code callee} variable
 137      * @param strict are we in strict mode
 138      */
 139     public ScriptFunctionImpl(
 140             final String name,
 141             final MethodHandle methodHandle,
 142             final ScriptObject scope,
 143             final Source source,
 144             final long token,
 145             final MethodHandle allocator,
 146             final PropertyMap allocatorMap,
 147             final boolean needCallee,
 148             final boolean strict) {
 149         super(name, methodHandle, getMap(strict), scope, source, token, allocator, allocatorMap, needCallee, null);
 150         if (strict) {
 151             this.setIsStrict();
 152         }
 153         init();
 154     }
 155 
 156     static {
 157         PropertyMap map = PropertyMap.newMap(ScriptFunctionImpl.class);
 158         map = Lookup.newProperty(map, "prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE);
 159         map = Lookup.newProperty(map, "length",    Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null);
 160         map = Lookup.newProperty(map, "name",      Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null);
 161         nasgenmap$ = map;
 162     }
 163 
 164     // function object representing TypeErrorThrower
 165     private static ScriptFunction typeErrorThrower;
 166 
 167     static synchronized ScriptFunction getTypeErrorThrower() {
 168         if (typeErrorThrower == null) {
 169             //name handle
 170             final ScriptFunctionImpl func = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_SETTER, null, false, null);
 171             // clear constructor handle...
 172             func.constructHandle = null;
 173             func.prototype       = UNDEFINED;
 174             typeErrorThrower     = func;
 175         }
 176 
 177         return typeErrorThrower;
 178     }
 179 
 180     // add a new property that throws TypeError on get as well as set
 181     static synchronized PropertyMap newThrowerProperty(final PropertyMap map, final String name, final int flags) {
 182         return map.newProperty(name, flags, Lookup.TYPE_ERROR_THROWER_GETTER, Lookup.TYPE_ERROR_THROWER_SETTER);
 183     }
 184 
 185     // property map for strict mode functions - lazily initialized
 186     private static PropertyMap strictmodemap$;
 187 
 188     // Choose the map based on strict mode!
 189     private static PropertyMap getMap(final boolean strict) {
 190         if (strict) {
 191             synchronized (ScriptFunctionImpl.class) {
 192                 if (strictmodemap$ == null) {
 193                     // In strict mode, the following properties should throw TypeError


 199             return strictmodemap$;
 200         }
 201 
 202         return nasgenmap$;
 203     }
 204 
 205     // Instance of this class is used as global anonymous function which
 206     // serves as Function.prototype object.
 207     private static class AnonymousFunction extends ScriptFunctionImpl {
 208         private static final PropertyMap nasgenmap$$ = PropertyMap.newMap(AnonymousFunction.class);
 209 
 210         AnonymousFunction() {
 211             super("", GlobalFunctions.ANONYMOUS, nasgenmap$$, null);
 212         }
 213     }
 214 
 215     static ScriptFunctionImpl newAnonymousFunction() {
 216         return new AnonymousFunction();
 217     }
 218 
 219     @Override
 220     public final boolean isStrict() {
 221         return (flags & IS_STRICT) != 0;
 222     }
 223 
 224     @Override
 225     public final boolean hasCalleeParameter() {
 226         return (flags & HAS_CALLEE) != 0;
 227     }
 228 
 229     @Override
 230     protected void setHasCalleeParameter() {
 231         flags |= HAS_CALLEE;
 232     }
 233 
 234     @Override
 235     public final boolean isBuiltin() {
 236         return (flags & IS_BUILTIN) != 0;
 237     }
 238 
 239     /**
 240      * Factory method for non-constructor functions
 241      *
 242      * @param name   function name
 243      * @param methodHandle handle for invocation
 244      * @param specs  specialized versions of function if available, null otherwise
 245      * @param strict are we in strict mode
 246      * @return new ScriptFunction
 247      */
 248     public static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs, final boolean strict) {
 249         final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, strict, specs);
 250 
 251         func.setIsBuiltin();
 252         func.setConstructHandle(null);
 253         func.setPrototype(UNDEFINED);
 254 
 255         return func;
 256     }
 257 
 258     /**
 259      * Factory method for non-constructor functions
 260      *
 261      * @param name   function name
 262      * @param methodHandle handle for invocation
 263      * @param specs  specialized versions of function if available, null otherwise
 264      * @return new ScriptFunction
 265      */
 266     public static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) {
 267         return makeFunction(name, methodHandle, specs, false);
 268     }
 269 
 270     /**
 271      * Factory method for non-constructor functions
 272      *
 273      * @param name   function name
 274      * @param methodHandle handle for invocation
 275      * @return new ScriptFunction
 276      */
 277     public static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle) {
 278         return makeFunction(name, methodHandle, null);
 279     }
 280 
 281     /**
 282      * This method is used to create a bound function. See also
 283      * {@link NativeFunction#bind(Object, Object...)} method implementation.
 284      *
 285      * @param thiz this reference to bind
 286      * @param args arguments to bind
 287      */
 288     @Override
 289     public ScriptFunction makeBoundFunction(final Object thiz, final Object[] args) {
 290         Object[] allArgs = args;
 291 




  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.objects;
  27 
  28 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  29 import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
  30 
  31 import java.lang.invoke.MethodHandle;
  32 import java.lang.invoke.MethodHandles;
  33 
  34 import jdk.nashorn.internal.runtime.ScriptFunctionData;
  35 import jdk.nashorn.internal.codegen.objects.FunctionObjectCreator;
  36 import jdk.nashorn.internal.runtime.GlobalFunctions;
  37 import jdk.nashorn.internal.runtime.Property;
  38 import jdk.nashorn.internal.runtime.PropertyMap;
  39 import jdk.nashorn.internal.runtime.ScriptFunction;
  40 import jdk.nashorn.internal.runtime.ScriptObject;
  41 import jdk.nashorn.internal.runtime.ScriptRuntime;

  42 import jdk.nashorn.internal.runtime.linker.Lookup;
  43 import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
  44 
  45 /**
  46  * Concrete implementation of ScriptFunction. This sets correct map for the
  47  * function objects -- to expose properties like "prototype", "length" etc.
  48  */
  49 public class ScriptFunctionImpl extends ScriptFunction {














  50 
  51     private static final MethodHandle BOUND_FUNCTION    = findOwnMH("boundFunction",    Object.class, ScriptFunction.class, Object.class, Object[].class, Object.class, Object[].class);
  52     private static final MethodHandle BOUND_CONSTRUCTOR = findOwnMH("boundConstructor", Object.class, ScriptFunction.class, Object[].class, Object.class, Object[].class);
  53 
  54     private static final PropertyMap nasgenmap$;
  55 


  56     /**
  57      * Constructor called by Nasgen generated code, no membercount, use the default map.
  58      * Creates builtin functions only.


  59      *
  60      * @param name name of function
  61      * @param invokeHandle handle for invocation
  62      * @param specs specialized versions of this method, if available, null otherwise
  63      */
  64     ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs) {
  65         super(name, invokeHandle, nasgenmap$, null, specs, false, true);
  66         init();
  67     }
  68 
  69     /**
  70      * Constructor called by Nasgen generated code, no membercount, use the map passed as argument.
  71      * Creates builtin functions only.


  72      *
  73      * @param name name of function
  74      * @param invokeHandle handle for invocation
  75      * @param map initial property map
  76      * @param specs specialized versions of this method, if available, null otherwise
  77      */
  78     ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs) {
  79         super(name, invokeHandle, map.addAll(nasgenmap$), null, specs, false, true);

  80         init();
  81     }
  82 
  83     /**
  84      * Constructor called by Global.newScriptFunction (runtime).


  85      *
  86      * @param name name of function
  87      * @param methodHandle handle for invocation
  88      * @param scope scope object

  89      * @param specs specialized versions of this method, if available, null otherwise
  90      * @param strict are we in strict mode
  91      * @param builtin is this a built-in function
  92      */
  93     ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final boolean strict, final boolean builtin) {
  94         super(name, methodHandle, getMap(strict), scope, specs, strict, builtin);



  95         init();
  96     }
  97 
  98     /**
  99      * Constructor called by (compiler) generated code for {@link ScriptObject}s.
 100      * Code is generated by {@link FunctionObjectCreator}


 101      *
 102      * @param data static function data


 103      * @param methodHandle handle for invocation
 104      * @param scope scope object


 105      * @param allocator instance constructor for function



 106      */
 107     public ScriptFunctionImpl(final ScriptFunctionData data, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle allocator) {
 108         super(data, getMap(data.isStrict()), scope);
 109         // Set method handles in script data
 110         if (data.getInvoker() == null) {
 111             data.setMethodHandles(methodHandle, allocator);








 112         }
 113         init();
 114     }
 115 
 116     static {
 117         PropertyMap map = PropertyMap.newMap(ScriptFunctionImpl.class);
 118         map = Lookup.newProperty(map, "prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE);
 119         map = Lookup.newProperty(map, "length",    Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null);
 120         map = Lookup.newProperty(map, "name",      Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null);
 121         nasgenmap$ = map;
 122     }
 123 
 124     // function object representing TypeErrorThrower
 125     private static ScriptFunction typeErrorThrower;
 126 
 127     static synchronized ScriptFunction getTypeErrorThrower() {
 128         if (typeErrorThrower == null) {
 129             //name handle
 130             final ScriptFunctionImpl func = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_SETTER, null, null, false, false);
 131             // clear constructor handle...
 132             func.setConstructHandle(null);
 133             func.setPrototype(UNDEFINED);
 134             typeErrorThrower = func;
 135         }
 136 
 137         return typeErrorThrower;
 138     }
 139 
 140     // add a new property that throws TypeError on get as well as set
 141     static synchronized PropertyMap newThrowerProperty(final PropertyMap map, final String name, final int flags) {
 142         return map.newProperty(name, flags, Lookup.TYPE_ERROR_THROWER_GETTER, Lookup.TYPE_ERROR_THROWER_SETTER);
 143     }
 144 
 145     // property map for strict mode functions - lazily initialized
 146     private static PropertyMap strictmodemap$;
 147 
 148     // Choose the map based on strict mode!
 149     private static PropertyMap getMap(final boolean strict) {
 150         if (strict) {
 151             synchronized (ScriptFunctionImpl.class) {
 152                 if (strictmodemap$ == null) {
 153                     // In strict mode, the following properties should throw TypeError


 159             return strictmodemap$;
 160         }
 161 
 162         return nasgenmap$;
 163     }
 164 
 165     // Instance of this class is used as global anonymous function which
 166     // serves as Function.prototype object.
 167     private static class AnonymousFunction extends ScriptFunctionImpl {
 168         private static final PropertyMap nasgenmap$$ = PropertyMap.newMap(AnonymousFunction.class);
 169 
 170         AnonymousFunction() {
 171             super("", GlobalFunctions.ANONYMOUS, nasgenmap$$, null);
 172         }
 173     }
 174 
 175     static ScriptFunctionImpl newAnonymousFunction() {
 176         return new AnonymousFunction();
 177     }
 178 




















 179     /**
 180      * Factory method for non-constructor built-in functions
 181      *
 182      * @param name   function name
 183      * @param methodHandle handle for invocation
 184      * @param specs  specialized versions of function if available, null otherwise
 185      * @param strict are we in strict mode
 186      * @return new ScriptFunction
 187      */
 188     public static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs, final boolean strict) {
 189         final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, strict, true);


 190         func.setConstructHandle(null);
 191         func.setPrototype(UNDEFINED);
 192 
 193         return func;
 194     }
 195 
 196     /**
 197      * Factory method for non-constructor built-in functions
 198      *
 199      * @param name   function name
 200      * @param methodHandle handle for invocation
 201      * @param specs  specialized versions of function if available, null otherwise
 202      * @return new ScriptFunction
 203      */
 204     public static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) {
 205         return makeFunction(name, methodHandle, specs, false);
 206     }
 207 
 208     /**
 209      * Factory method for non-constructor built-in functions
 210      *
 211      * @param name   function name
 212      * @param methodHandle handle for invocation
 213      * @return new ScriptFunction
 214      */
 215     public static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle) {
 216         return makeFunction(name, methodHandle, null);
 217     }
 218 
 219     /**
 220      * This method is used to create a bound function. See also
 221      * {@link NativeFunction#bind(Object, Object...)} method implementation.
 222      *
 223      * @param thiz this reference to bind
 224      * @param args arguments to bind
 225      */
 226     @Override
 227     public ScriptFunction makeBoundFunction(final Object thiz, final Object[] args) {
 228         Object[] allArgs = args;
 229