@@ -143,12 +143,13 @@ public Loader run() {
143
143
});
144
144
145
145
Set <String > extractedVariables = new HashSet <>();
146
- compile (contextsToCompilers .get (context ), loader , extractedVariables , scriptName , scriptSource , params );
146
+ ScriptRoot scriptRoot = compile (contextsToCompilers .get (context ), loader , extractedVariables , scriptName , scriptSource , params );
147
147
148
148
if (context .statefulFactoryClazz != null ) {
149
- return generateFactory (loader , context , extractedVariables , generateStatefulFactory (loader , context , extractedVariables ));
149
+ return generateFactory (loader , context , extractedVariables , generateStatefulFactory (loader , context , extractedVariables ),
150
+ scriptRoot );
150
151
} else {
151
- return generateFactory (loader , context , extractedVariables , WriterConstants .CLASS_TYPE );
152
+ return generateFactory (loader , context , extractedVariables , WriterConstants .CLASS_TYPE , scriptRoot );
152
153
}
153
154
}
154
155
@@ -270,14 +271,16 @@ private <T extends ScriptFactory> Type generateStatefulFactory(
270
271
* @param context The {@link ScriptContext}'s semantics are used to define the factory class.
271
272
* @param classType The type to be instaniated in the newFactory or newInstance method. Depends
272
273
* on whether a {@link ScriptContext#statefulFactoryClazz} is specified.
274
+ * @param scriptRoot the {@link ScriptRoot} used to do the compilation
273
275
* @param <T> The factory class.
274
276
* @return A factory class that will return script instances.
275
277
*/
276
278
private <T extends ScriptFactory > T generateFactory (
277
279
Loader loader ,
278
280
ScriptContext <T > context ,
279
281
Set <String > extractedVariables ,
280
- Type classType
282
+ Type classType ,
283
+ ScriptRoot scriptRoot
281
284
) {
282
285
int classFrames = ClassWriter .COMPUTE_FRAMES | ClassWriter .COMPUTE_MAXS ;
283
286
int classAccess = Opcodes .ACC_PUBLIC | Opcodes .ACC_SUPER | Opcodes .ACC_FINAL ;
@@ -330,8 +333,19 @@ private <T extends ScriptFactory> T generateFactory(
330
333
adapter .endMethod ();
331
334
332
335
writeNeedsMethods (context .factoryClazz , writer , extractedVariables );
333
- writer .visitEnd ();
334
336
337
+ String methodName = "isResultDeterministic" ;
338
+ org .objectweb .asm .commons .Method isResultDeterministic = new org .objectweb .asm .commons .Method (methodName ,
339
+ MethodType .methodType (boolean .class ).toMethodDescriptorString ());
340
+
341
+ GeneratorAdapter deterAdapter = new GeneratorAdapter (Opcodes .ASM5 , isResultDeterministic ,
342
+ writer .visitMethod (Opcodes .ACC_PUBLIC , methodName , isResultDeterministic .getDescriptor (), null , null ));
343
+ deterAdapter .visitCode ();
344
+ deterAdapter .push (scriptRoot .deterministic );
345
+ deterAdapter .returnValue ();
346
+ deterAdapter .endMethod ();
347
+
348
+ writer .visitEnd ();
335
349
Class <?> factory = loader .defineFactory (className .replace ('/' , '.' ), writer .toByteArray ());
336
350
337
351
try {
@@ -363,19 +377,17 @@ private void writeNeedsMethods(Class<?> clazz, ClassWriter writer, Set<String> e
363
377
}
364
378
}
365
379
366
- void compile (Compiler compiler , Loader loader , Set <String > extractedVariables ,
380
+ ScriptRoot compile (Compiler compiler , Loader loader , Set <String > extractedVariables ,
367
381
String scriptName , String source , Map <String , String > params ) {
368
382
final CompilerSettings compilerSettings = buildCompilerSettings (params );
369
383
370
384
try {
371
385
// Drop all permissions to actually compile the code itself.
372
- AccessController .doPrivileged (new PrivilegedAction <Void >() {
386
+ return AccessController .doPrivileged (new PrivilegedAction <ScriptRoot >() {
373
387
@ Override
374
- public Void run () {
388
+ public ScriptRoot run () {
375
389
String name = scriptName == null ? source : scriptName ;
376
- compiler .compile (loader , extractedVariables , name , source , compilerSettings );
377
-
378
- return null ;
390
+ return compiler .compile (loader , extractedVariables , name , source , compilerSettings );
379
391
}
380
392
}, COMPILATION_CONTEXT );
381
393
// Note that it is safe to catch any of the following errors since Painless is stateless.
0 commit comments