103 import jdk.nashorn.internal.ir.LabelNode; |
103 import jdk.nashorn.internal.ir.LabelNode; |
104 import jdk.nashorn.internal.ir.LexicalContext; |
104 import jdk.nashorn.internal.ir.LexicalContext; |
105 import jdk.nashorn.internal.ir.LexicalContextNode; |
105 import jdk.nashorn.internal.ir.LexicalContextNode; |
106 import jdk.nashorn.internal.ir.LiteralNode; |
106 import jdk.nashorn.internal.ir.LiteralNode; |
107 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; |
107 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; |
108 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; |
|
109 import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode; |
108 import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode; |
110 import jdk.nashorn.internal.ir.LocalVariableConversion; |
109 import jdk.nashorn.internal.ir.LocalVariableConversion; |
111 import jdk.nashorn.internal.ir.LoopNode; |
110 import jdk.nashorn.internal.ir.LoopNode; |
112 import jdk.nashorn.internal.ir.Node; |
111 import jdk.nashorn.internal.ir.Node; |
113 import jdk.nashorn.internal.ir.ObjectNode; |
112 import jdk.nashorn.internal.ir.ObjectNode; |
116 import jdk.nashorn.internal.ir.ReturnNode; |
115 import jdk.nashorn.internal.ir.ReturnNode; |
117 import jdk.nashorn.internal.ir.RuntimeNode; |
116 import jdk.nashorn.internal.ir.RuntimeNode; |
118 import jdk.nashorn.internal.ir.RuntimeNode.Request; |
117 import jdk.nashorn.internal.ir.RuntimeNode.Request; |
119 import jdk.nashorn.internal.ir.SetSplitState; |
118 import jdk.nashorn.internal.ir.SetSplitState; |
120 import jdk.nashorn.internal.ir.SplitReturn; |
119 import jdk.nashorn.internal.ir.SplitReturn; |
|
120 import jdk.nashorn.internal.ir.Splittable; |
121 import jdk.nashorn.internal.ir.Statement; |
121 import jdk.nashorn.internal.ir.Statement; |
122 import jdk.nashorn.internal.ir.SwitchNode; |
122 import jdk.nashorn.internal.ir.SwitchNode; |
123 import jdk.nashorn.internal.ir.Symbol; |
123 import jdk.nashorn.internal.ir.Symbol; |
124 import jdk.nashorn.internal.ir.TernaryNode; |
124 import jdk.nashorn.internal.ir.TernaryNode; |
125 import jdk.nashorn.internal.ir.ThrowNode; |
125 import jdk.nashorn.internal.ir.ThrowNode; |
2232 * Load a list of nodes as an array of a specific type |
2232 * Load a list of nodes as an array of a specific type |
2233 * The array will contain the visited nodes. |
2233 * The array will contain the visited nodes. |
2234 * |
2234 * |
2235 * @param arrayLiteralNode the array of contents |
2235 * @param arrayLiteralNode the array of contents |
2236 * @param arrayType the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT |
2236 * @param arrayType the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT |
2237 * |
|
2238 * @return the method generator that was used |
|
2239 */ |
2237 */ |
2240 private MethodEmitter loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) { |
2238 private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) { |
2241 assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY; |
2239 assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY; |
2242 |
2240 |
2243 final Expression[] nodes = arrayLiteralNode.getValue(); |
2241 final Expression[] nodes = arrayLiteralNode.getValue(); |
2244 final Object presets = arrayLiteralNode.getPresets(); |
2242 final Object presets = arrayLiteralNode.getPresets(); |
2245 final int[] postsets = arrayLiteralNode.getPostsets(); |
2243 final int[] postsets = arrayLiteralNode.getPostsets(); |
2246 final Class<?> type = arrayType.getTypeClass(); |
2244 final List<Splittable.SplitRange> ranges = arrayLiteralNode.getSplitRanges(); |
2247 final List<ArrayUnit> units = arrayLiteralNode.getUnits(); |
|
2248 |
2245 |
2249 loadConstant(presets); |
2246 loadConstant(presets); |
2250 |
2247 |
2251 final Type elementType = arrayType.getElementType(); |
2248 final Type elementType = arrayType.getElementType(); |
2252 |
2249 |
2253 if (units != null) { |
2250 if (ranges != null) { |
2254 final MethodEmitter savedMethod = method; |
2251 |
2255 final FunctionNode currentFunction = lc.getCurrentFunction(); |
2252 loadSplitLiteral(new SplitLiteralCreator() { |
2256 |
2253 @Override |
2257 for (final ArrayUnit arrayUnit : units) { |
2254 public void populateRange(final MethodEmitter method, final Type type, final int slot, final int start, final int end) { |
2258 unit = lc.pushCompileUnit(arrayUnit.getCompileUnit()); |
2255 for (int i = start; i < end; i++) { |
2259 |
2256 method.load(type, slot); |
2260 final String className = unit.getUnitClassName(); |
2257 storeElement(nodes, elementType, postsets[i]); |
2261 assert unit != null; |
2258 } |
2262 final String name = currentFunction.uniqueName(SPLIT_PREFIX.symbolName()); |
2259 method.load(type, slot); |
2263 final String signature = methodDescriptor(type, ScriptFunction.class, Object.class, ScriptObject.class, type); |
2260 } |
2264 |
2261 }, ranges, arrayType); |
2265 pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature)); |
2262 |
2266 |
2263 return; |
2267 method.setFunctionNode(currentFunction); |
|
2268 method.begin(); |
|
2269 |
|
2270 defineCommonSplitMethodParameters(); |
|
2271 defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), arrayType); |
|
2272 |
|
2273 // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT |
|
2274 // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit(). |
|
2275 final int arraySlot = fixScopeSlot(currentFunction, 3); |
|
2276 |
|
2277 lc.enterSplitNode(); |
|
2278 |
|
2279 for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) { |
|
2280 method.load(arrayType, arraySlot); |
|
2281 storeElement(nodes, elementType, postsets[i]); |
|
2282 } |
|
2283 |
|
2284 method.load(arrayType, arraySlot); |
|
2285 method._return(); |
|
2286 lc.exitSplitNode(); |
|
2287 method.end(); |
|
2288 lc.releaseSlots(); |
|
2289 popMethodEmitter(); |
|
2290 |
|
2291 assert method == savedMethod; |
|
2292 method.loadCompilerConstant(CALLEE); |
|
2293 method.swap(); |
|
2294 method.loadCompilerConstant(THIS); |
|
2295 method.swap(); |
|
2296 method.loadCompilerConstant(SCOPE); |
|
2297 method.swap(); |
|
2298 method.invokestatic(className, name, signature); |
|
2299 |
|
2300 unit = lc.popCompileUnit(unit); |
|
2301 } |
|
2302 |
|
2303 return method; |
|
2304 } |
2264 } |
2305 |
2265 |
2306 if(postsets.length > 0) { |
2266 if(postsets.length > 0) { |
2307 final int arraySlot = method.getUsedSlotsWithLiveTemporaries(); |
2267 final int arraySlot = method.getUsedSlotsWithLiveTemporaries(); |
2308 method.storeTemp(arrayType, arraySlot); |
2268 method.storeTemp(arrayType, arraySlot); |
2581 @Override |
2541 @Override |
2582 protected void loadValue(final Expression node, final Type type) { |
2542 protected void loadValue(final Expression node, final Type type) { |
2583 loadExpressionAsType(node, type); |
2543 loadExpressionAsType(node, type); |
2584 }}; |
2544 }}; |
2585 } |
2545 } |
2586 oc.makeObject(method); |
2546 |
|
2547 if (ranges != null) { |
|
2548 oc.createObject(method); |
|
2549 loadSplitLiteral(oc, ranges, Type.typeFor(oc.getAllocatorClass())); |
|
2550 } else { |
|
2551 oc.makeObject(method); |
|
2552 } |
2587 |
2553 |
2588 //if this is a rest of method and our continuation point was found as one of the values |
2554 //if this is a rest of method and our continuation point was found as one of the values |
2589 //in the properties above, we need to reset the map to oc.getMap() in the continuation |
2555 //in the properties above, we need to reset the map to oc.getMap() in the continuation |
2590 //handler |
2556 //handler |
2591 if (restOfProperty) { |
2557 if (restOfProperty) { |
2895 } |
2861 } |
2896 |
2862 |
2897 private void defineSplitMethodParameter(final int slot, final Type type) { |
2863 private void defineSplitMethodParameter(final int slot, final Type type) { |
2898 method.defineBlockLocalVariable(slot, slot + type.getSlots()); |
2864 method.defineBlockLocalVariable(slot, slot + type.getSlots()); |
2899 method.onLocalStore(type, slot); |
2865 method.onLocalStore(type, slot); |
|
2866 } |
|
2867 |
|
2868 private void loadSplitLiteral(final SplitLiteralCreator creator, final List<Splittable.SplitRange> ranges, final Type literalType) { |
|
2869 assert ranges != null; |
|
2870 |
|
2871 // final Type literalType = Type.typeFor(literalClass); |
|
2872 final MethodEmitter savedMethod = method; |
|
2873 final FunctionNode currentFunction = lc.getCurrentFunction(); |
|
2874 |
|
2875 for (final Splittable.SplitRange splitRange : ranges) { |
|
2876 unit = lc.pushCompileUnit(splitRange.getCompileUnit()); |
|
2877 |
|
2878 assert unit != null; |
|
2879 final String className = unit.getUnitClassName(); |
|
2880 final String name = currentFunction.uniqueName(SPLIT_PREFIX.symbolName()); |
|
2881 final Class<?> clazz = literalType.getTypeClass(); |
|
2882 final String signature = methodDescriptor(clazz, ScriptFunction.class, Object.class, ScriptObject.class, clazz); |
|
2883 |
|
2884 pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature)); |
|
2885 |
|
2886 method.setFunctionNode(currentFunction); |
|
2887 method.begin(); |
|
2888 |
|
2889 defineCommonSplitMethodParameters(); |
|
2890 defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), literalType); |
|
2891 |
|
2892 // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT |
|
2893 // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit(). |
|
2894 final int literalSlot = fixScopeSlot(currentFunction, 3); |
|
2895 |
|
2896 lc.enterSplitNode(); |
|
2897 |
|
2898 creator.populateRange(method, literalType, literalSlot, splitRange.getLow(), splitRange.getHigh()); |
|
2899 |
|
2900 method._return(); |
|
2901 lc.exitSplitNode(); |
|
2902 method.end(); |
|
2903 lc.releaseSlots(); |
|
2904 popMethodEmitter(); |
|
2905 |
|
2906 assert method == savedMethod; |
|
2907 method.loadCompilerConstant(CALLEE).swap(); |
|
2908 method.loadCompilerConstant(THIS).swap(); |
|
2909 method.loadCompilerConstant(SCOPE).swap(); |
|
2910 method.invokestatic(className, name, signature); |
|
2911 |
|
2912 unit = lc.popCompileUnit(unit); |
|
2913 } |
2900 } |
2914 } |
2901 |
2915 |
2902 private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) { |
2916 private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) { |
2903 // TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method) |
2917 // TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method) |
2904 final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE); |
2918 final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE); |
5459 method._catch(catchLabel); |
5473 method._catch(catchLabel); |
5460 popScopes(scopePopCount); |
5474 popScopes(scopePopCount); |
5461 method.uncheckedGoto(targetCatchLabel); |
5475 method.uncheckedGoto(targetCatchLabel); |
5462 } |
5476 } |
5463 } |
5477 } |
|
5478 |
|
5479 /** |
|
5480 * Interface implemented by object creators that support splitting over multiple methods. |
|
5481 */ |
|
5482 interface SplitLiteralCreator { |
|
5483 /** |
|
5484 * Generate code to populate a range of the literal object. A reference to the object |
|
5485 * should be left on the stack when the method terminates. |
|
5486 * |
|
5487 * @param method the method emitter |
|
5488 * @param type the type of the literal object |
|
5489 * @param slot the local slot containing the literal object |
|
5490 * @param start the start index (inclusive) |
|
5491 * @param end the end index (exclusive) |
|
5492 */ |
|
5493 void populateRange(MethodEmitter method, Type type, int slot, int start, int end); |
|
5494 } |
5464 } |
5495 } |