70 * more specific type for sorting |
70 * more specific type for sorting |
71 */ |
71 */ |
72 private MethodHandle invoker; |
72 private MethodHandle invoker; |
73 private MethodHandle constructor; |
73 private MethodHandle constructor; |
74 private OptimismInfo optimismInfo; |
74 private OptimismInfo optimismInfo; |
|
75 private int flags; // from FunctionNode |
75 |
76 |
76 CompiledFunction(final MethodHandle invoker) { |
77 CompiledFunction(final MethodHandle invoker) { |
77 this.invoker = invoker; |
78 this.invoker = invoker; |
78 } |
79 } |
79 |
80 |
85 CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) { |
86 CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) { |
86 this(invoker); |
87 this(invoker); |
87 this.constructor = constructor; |
88 this.constructor = constructor; |
88 } |
89 } |
89 |
90 |
90 CompiledFunction(final MethodHandle invoker, final RecompilableScriptFunctionData functionData, final boolean isOptimistic) { |
91 CompiledFunction(final MethodHandle invoker, final RecompilableScriptFunctionData functionData, final int flags) { |
91 this(invoker); |
92 this(invoker); |
92 if(isOptimistic) { |
93 this.flags = flags; |
|
94 if ((flags & FunctionNode.IS_OPTIMISTIC) != 0) { |
93 optimismInfo = new OptimismInfo(functionData); |
95 optimismInfo = new OptimismInfo(functionData); |
94 } else { |
96 } else { |
95 optimismInfo = null; |
97 optimismInfo = null; |
96 } |
98 } |
|
99 } |
|
100 |
|
101 int getFlags() { |
|
102 return flags; |
|
103 } |
|
104 |
|
105 boolean isVarArg() { |
|
106 return isVarArgsType(invoker.type()); |
97 } |
107 } |
98 |
108 |
99 @Override |
109 @Override |
100 public String toString() { |
110 public String toString() { |
101 return "<callSiteType=" + invoker.type() + " invoker=" + invoker + " ctor=" + constructor + " weight=" + weight() + ">"; |
111 return "<callSiteType=" + invoker.type() + " invoker=" + invoker + " ctor=" + constructor + " weight=" + weight() + ">"; |
125 * non-null, and that you can relink the call site it is set into as a target if the switch point is invalidated. In |
135 * non-null, and that you can relink the call site it is set into as a target if the switch point is invalidated. In |
126 * all other cases, use {@link #createComposableConstructor()}. |
136 * all other cases, use {@link #createComposableConstructor()}. |
127 * @return a direct constructor method handle for this function. |
137 * @return a direct constructor method handle for this function. |
128 */ |
138 */ |
129 MethodHandle getConstructor() { |
139 MethodHandle getConstructor() { |
130 if(constructor == null) { |
140 if (constructor == null) { |
131 constructor = createConstructorFromInvoker(createInvokerForPessimisticCaller()); |
141 constructor = createConstructorFromInvoker(createInvokerForPessimisticCaller()); |
132 } |
142 } |
133 |
143 |
134 return constructor; |
144 return constructor; |
|
145 } |
|
146 |
|
147 MethodHandle getInvoker() { |
|
148 return invoker; |
135 } |
149 } |
136 |
150 |
137 /** |
151 /** |
138 * Creates a version of the invoker intended for a pessimistic caller (return type is Object, no caller optimistic |
152 * Creates a version of the invoker intended for a pessimistic caller (return type is Object, no caller optimistic |
139 * program point available). |
153 * program point available). |
246 weight += type.parameterCount(); //more params outweigh few parameters |
260 weight += type.parameterCount(); //more params outweigh few parameters |
247 |
261 |
248 return weight; |
262 return weight; |
249 } |
263 } |
250 |
264 |
251 private static boolean isVarArgsType(final MethodType type) { |
265 static boolean isVarArgsType(final MethodType type) { |
252 assert type.parameterCount() >= 1 : type; |
266 assert type.parameterCount() >= 1 : type; |
253 return type.parameterType(type.parameterCount() - 1) == Object[].class; |
267 return type.parameterType(type.parameterCount() - 1) == Object[].class; |
254 } |
268 } |
255 |
269 |
256 static boolean moreGenericThan(final MethodType mt0, final MethodType mt1) { |
270 static boolean moreGenericThan(final MethodType mt0, final MethodType mt1) { |
403 final int fixParamCount = paramTypes.length - (isVarArg ? 1 : 0); |
417 final int fixParamCount = paramTypes.length - (isVarArg ? 1 : 0); |
404 if(i < fixParamCount) { |
418 if(i < fixParamCount) { |
405 return paramTypes[i]; |
419 return paramTypes[i]; |
406 } |
420 } |
407 assert isVarArg; |
421 assert isVarArg; |
408 return ((ArrayType)(paramTypes[paramTypes.length - 1])).getElementType(); |
422 return ((ArrayType)paramTypes[paramTypes.length - 1]).getElementType(); |
409 } |
423 } |
410 |
424 |
411 boolean matchesCallSite(final MethodType callSiteType) { |
425 boolean matchesCallSite(final MethodType callSiteType, final boolean pickVarArg) { |
412 if(!ScriptEnvironment.globalOptimistic()) { |
426 if (!ScriptEnvironment.globalOptimistic()) { |
413 // Without optimistic recompilation, always choose the first eagerly compiled version. |
427 // Without optimistic recompilation, always choose the first eagerly compiled version. |
414 return true; |
428 return true; |
415 } |
429 } |
416 |
430 |
417 final MethodType type = type(); |
431 final MethodType type = type(); |
418 final int fnParamCount = getParamCount(type); |
432 final int fnParamCount = getParamCount(type); |
419 final boolean isVarArg = fnParamCount == Integer.MAX_VALUE; |
433 final boolean isVarArg = fnParamCount == Integer.MAX_VALUE; |
420 if(isVarArg) { |
434 if (isVarArg) { |
421 return true; |
435 return pickVarArg; |
422 } |
436 } |
423 |
437 |
424 final int csParamCount = getParamCount(callSiteType); |
438 final int csParamCount = getParamCount(callSiteType); |
425 final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE; |
439 final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE; |
426 final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type |
440 final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type |
616 FunctionNode recompile(final MethodType callSiteType, final RewriteException e) { |
630 FunctionNode recompile(final MethodType callSiteType, final RewriteException e) { |
617 final Type retType = e.getReturnType(); |
631 final Type retType = e.getReturnType(); |
618 final Type previousFailedType = invalidatedProgramPoints.put(e.getProgramPoint(), retType); |
632 final Type previousFailedType = invalidatedProgramPoints.put(e.getProgramPoint(), retType); |
619 if (previousFailedType != null && !previousFailedType.narrowerThan(retType)) { |
633 if (previousFailedType != null && !previousFailedType.narrowerThan(retType)) { |
620 final StackTraceElement[] stack = e.getStackTrace(); |
634 final StackTraceElement[] stack = e.getStackTrace(); |
621 final String functionId = stack.length == 0 ? data.getName() : (stack[0].getClassName() + "." + stack[0].getMethodName()); |
635 final String functionId = stack.length == 0 ? data.getName() : stack[0].getClassName() + "." + stack[0].getMethodName(); |
622 LOG.info("RewriteException for an already invalidated program point ", e.getProgramPoint(), " in ", functionId, ". This is okay for a recursive function invocation, but a bug otherwise."); |
636 LOG.info("RewriteException for an already invalidated program point ", e.getProgramPoint(), " in ", functionId, ". This is okay for a recursive function invocation, but a bug otherwise."); |
623 return null; |
637 return null; |
624 } |
638 } |
625 SwitchPoint.invalidateAll(new SwitchPoint[] { optimisticAssumptions }); |
639 SwitchPoint.invalidateAll(new SwitchPoint[] { optimisticAssumptions }); |
626 return data.compile(callSiteType, invalidatedProgramPoints, e.getRuntimeScope(), "Deoptimizing recompilation"); |
640 return data.compile(callSiteType, invalidatedProgramPoints, e.getRuntimeScope(), "Deoptimizing recompilation"); |