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 |