38 import jdk.nashorn.internal.runtime.ScriptFunctionData; 39 import jdk.nashorn.internal.runtime.ScriptObject; 40 import jdk.nashorn.internal.runtime.AccessorProperty; 41 42 /** 43 * Concrete implementation of ScriptFunction. This sets correct map for the 44 * function objects -- to expose properties like "prototype", "length" etc. 45 */ 46 public class ScriptFunctionImpl extends ScriptFunction { 47 48 /** Reference to constructor prototype. */ 49 private Object prototype; 50 51 // property map for strict mode functions 52 private static final PropertyMap strictmodemap$; 53 // property map for bound functions 54 private static final PropertyMap boundfunctionmap$; 55 // property map for non-strict, non-bound functions. 56 private static final PropertyMap map$; 57 58 static PropertyMap getInitialMap() { 59 return map$; 60 } 61 62 static PropertyMap getInitialAnonymousMap() { 63 return AnonymousFunction.getInitialMap(); 64 } 65 66 static PropertyMap getInitialStrictMap() { 67 return strictmodemap$; 68 } 69 70 static PropertyMap getInitialBoundMap() { 71 return boundfunctionmap$; 72 } 73 74 // Marker object for lazily initialized prototype object 75 private static final Object LAZY_PROTOTYPE = new Object(); 76 77 private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) { 78 super(name, invokeHandle, getInitialMap(), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 79 init(global); 80 } 81 82 /** 83 * Constructor called by Nasgen generated code, no membercount, use the default map. 84 * Creates builtin functions only. 85 * 86 * @param name name of function 87 * @param invokeHandle handle for invocation 88 * @param specs specialized versions of this method, if available, null otherwise 89 */ 90 ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs) { 91 this(name, invokeHandle, specs, Global.instance()); 92 } 93 94 private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) { 95 super(name, invokeHandle, map.addAll(getInitialMap()), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 96 init(global); 97 } 98 99 /** 100 * Constructor called by Nasgen generated code, no membercount, use the map passed as argument. 101 * Creates builtin functions only. 102 * 103 * @param name name of function 104 * @param invokeHandle handle for invocation 105 * @param map initial property map 106 * @param specs specialized versions of this method, if available, null otherwise 107 */ 108 ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs) { 109 this(name, invokeHandle, map, specs, Global.instance()); 110 } 111 112 private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags, final Global global) { 113 super(name, methodHandle, getMap(global, isStrict(flags)), scope, specs, flags); 114 init(global); 115 } 116 117 /** 118 * Constructor called by Global.newScriptFunction (runtime). 119 * 120 * @param name name of function 121 * @param methodHandle handle for invocation 122 * @param scope scope object 123 * @param specs specialized versions of this method, if available, null otherwise 124 * @param flags {@link ScriptFunctionData} flags 125 */ 126 ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags) { 127 this(name, methodHandle, scope, specs, flags, Global.instance()); 128 } 129 130 private ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope, final Global global) { 131 super(data, getMap(global, data.isStrict()), scope); 132 init(global); 133 } 134 135 /** 136 * Constructor called by (compiler) generated code for {@link ScriptObject}s. 137 * 138 * @param data static function data 139 * @param scope scope object 140 */ 141 public ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope) { 142 this(data, scope, Global.instance()); 143 } 144 145 /** 146 * Only invoked internally from {@link BoundScriptFunctionImpl} constructor. 147 * @param data the script function data for the bound function. 148 * @param global the global object 149 */ 150 ScriptFunctionImpl(final ScriptFunctionData data, final Global global) { 151 super(data, getInitialBoundMap(), null); 152 init(global); 153 } 154 155 static { 156 final ArrayList<Property> properties = new ArrayList<>(3); 157 properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE)); 158 properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null)); 159 properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null)); 160 map$ = PropertyMap.newMap(properties); 161 strictmodemap$ = createStrictModeMap(map$); 162 boundfunctionmap$ = createBoundFunctionMap(strictmodemap$); 163 } 164 165 private static PropertyMap createStrictModeMap(final PropertyMap map) { 166 final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; 167 PropertyMap newMap = map; 168 // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors. 169 newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags)); 170 newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags)); 171 return newMap; 172 } 173 174 private static boolean isStrict(final int flags) { 175 return (flags & ScriptFunctionData.IS_STRICT) != 0; 176 } 177 178 // Choose the map based on strict mode! 179 private static PropertyMap getMap(final Global global, final boolean strict) { 180 return strict ? getInitialStrictMap() : getInitialMap(); 181 } 182 183 private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) { 184 // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see 185 // ECMAScript 5.1 section 15.3.4.5 186 return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype")); 187 } 188 189 // Instance of this class is used as global anonymous function which 190 // serves as Function.prototype object. 191 private static class AnonymousFunction extends ScriptFunctionImpl { 192 private static final PropertyMap anonmap$ = PropertyMap.newMap(); 193 194 static PropertyMap getInitialMap() { 195 return anonmap$; 196 } 197 198 AnonymousFunction(final Global global) { 199 super("", GlobalFunctions.ANONYMOUS, getInitialAnonymousMap(), null); 200 } 201 } 202 203 static ScriptFunctionImpl newAnonymousFunction(final Global global) { 204 return new AnonymousFunction(global); 205 } 206 207 /** 208 * Factory method for non-constructor built-in functions 209 * 210 * @param name function name 211 * @param methodHandle handle for invocation 212 * @param specs specialized versions of function if available, null otherwise 213 * @return new ScriptFunction 214 */ 215 static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) { 216 final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN); 217 func.setPrototype(UNDEFINED); 218 // Non-constructor built-in functions do not have "prototype" property 219 func.deleteOwnProperty(func.getMap().findProperty("prototype")); | 38 import jdk.nashorn.internal.runtime.ScriptFunctionData; 39 import jdk.nashorn.internal.runtime.ScriptObject; 40 import jdk.nashorn.internal.runtime.AccessorProperty; 41 42 /** 43 * Concrete implementation of ScriptFunction. This sets correct map for the 44 * function objects -- to expose properties like "prototype", "length" etc. 45 */ 46 public class ScriptFunctionImpl extends ScriptFunction { 47 48 /** Reference to constructor prototype. */ 49 private Object prototype; 50 51 // property map for strict mode functions 52 private static final PropertyMap strictmodemap$; 53 // property map for bound functions 54 private static final PropertyMap boundfunctionmap$; 55 // property map for non-strict, non-bound functions. 56 private static final PropertyMap map$; 57 58 // Marker object for lazily initialized prototype object 59 private static final Object LAZY_PROTOTYPE = new Object(); 60 61 private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) { 62 super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 63 init(global); 64 } 65 66 /** 67 * Constructor called by Nasgen generated code, no membercount, use the default map. 68 * Creates builtin functions only. 69 * 70 * @param name name of function 71 * @param invokeHandle handle for invocation 72 * @param specs specialized versions of this method, if available, null otherwise 73 */ 74 ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs) { 75 this(name, invokeHandle, specs, Global.instance()); 76 } 77 78 private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) { 79 super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR); 80 init(global); 81 } 82 83 /** 84 * Constructor called by Nasgen generated code, no membercount, use the map passed as argument. 85 * Creates builtin functions only. 86 * 87 * @param name name of function 88 * @param invokeHandle handle for invocation 89 * @param map initial property map 90 * @param specs specialized versions of this method, if available, null otherwise 91 */ 92 ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs) { 93 this(name, invokeHandle, map, specs, Global.instance()); 94 } 95 96 private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags, final Global global) { 97 super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags); 98 init(global); 99 } 100 101 /** 102 * Constructor called by Global.newScriptFunction (runtime). 103 * 104 * @param name name of function 105 * @param methodHandle handle for invocation 106 * @param scope scope object 107 * @param specs specialized versions of this method, if available, null otherwise 108 * @param flags {@link ScriptFunctionData} flags 109 */ 110 ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags) { 111 this(name, methodHandle, scope, specs, flags, Global.instance()); 112 } 113 114 private ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope, final Global global) { 115 super(data, getMap(data.isStrict()), scope); 116 init(global); 117 } 118 119 /** 120 * Constructor called by (compiler) generated code for {@link ScriptObject}s. 121 * 122 * @param data static function data 123 * @param scope scope object 124 */ 125 public ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope) { 126 this(data, scope, Global.instance()); 127 } 128 129 /** 130 * Only invoked internally from {@link BoundScriptFunctionImpl} constructor. 131 * @param data the script function data for the bound function. 132 * @param global the global object 133 */ 134 ScriptFunctionImpl(final ScriptFunctionData data, final Global global) { 135 super(data, boundfunctionmap$, null); 136 init(global); 137 } 138 139 static { 140 final ArrayList<Property> properties = new ArrayList<>(3); 141 properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE)); 142 properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null)); 143 properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null)); 144 map$ = PropertyMap.newMap(properties); 145 strictmodemap$ = createStrictModeMap(map$); 146 boundfunctionmap$ = createBoundFunctionMap(strictmodemap$); 147 } 148 149 private static PropertyMap createStrictModeMap(final PropertyMap map) { 150 final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE; 151 PropertyMap newMap = map; 152 // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors. 153 newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags)); 154 newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags)); 155 return newMap; 156 } 157 158 private static boolean isStrict(final int flags) { 159 return (flags & ScriptFunctionData.IS_STRICT) != 0; 160 } 161 162 // Choose the map based on strict mode! 163 private static PropertyMap getMap(final boolean strict) { 164 return strict ? strictmodemap$ : map$; 165 } 166 167 private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) { 168 // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see 169 // ECMAScript 5.1 section 15.3.4.5 170 return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype")); 171 } 172 173 // Instance of this class is used as global anonymous function which 174 // serves as Function.prototype object. 175 private static class AnonymousFunction extends ScriptFunctionImpl { 176 private static final PropertyMap anonmap$ = PropertyMap.newMap(); 177 178 AnonymousFunction(final Global global) { 179 super("", GlobalFunctions.ANONYMOUS, anonmap$, null); 180 } 181 } 182 183 static ScriptFunctionImpl newAnonymousFunction(final Global global) { 184 return new AnonymousFunction(global); 185 } 186 187 /** 188 * Factory method for non-constructor built-in functions 189 * 190 * @param name function name 191 * @param methodHandle handle for invocation 192 * @param specs specialized versions of function if available, null otherwise 193 * @return new ScriptFunction 194 */ 195 static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) { 196 final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN); 197 func.setPrototype(UNDEFINED); 198 // Non-constructor built-in functions do not have "prototype" property 199 func.deleteOwnProperty(func.getMap().findProperty("prototype")); |