You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2015/08/09 14:14:35 UTC

svn commit: r1694880 - in /lucene/dev/branches/branch_5x: ./ lucene/ lucene/expressions/ lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java

Author: uschindler
Date: Sun Aug  9 12:14:34 2015
New Revision: 1694880

URL: http://svn.apache.org/r1694880
Log:
Merged revision(s) 1694876,1694879 from lucene/dev/trunk:
LUCENE-6417: Make JavascriptCompiler completely stateless (thanks to visitor pattern)

Modified:
    lucene/dev/branches/branch_5x/   (props changed)
    lucene/dev/branches/branch_5x/lucene/   (props changed)
    lucene/dev/branches/branch_5x/lucene/expressions/   (props changed)
    lucene/dev/branches/branch_5x/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java

Modified: lucene/dev/branches/branch_5x/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java?rev=1694880&r1=1694879&r2=1694880&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java (original)
+++ lucene/dev/branches/branch_5x/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java Sun Aug  9 12:14:34 2015
@@ -19,7 +19,6 @@ package org.apache.lucene.expressions.js
 import java.io.IOException;
 import java.io.Reader;
 import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.nio.charset.StandardCharsets;
@@ -37,6 +36,7 @@ import org.antlr.v4.runtime.ANTLRInputSt
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.apache.lucene.expressions.Expression;
+import org.apache.lucene.expressions.js.JavascriptParser.ExpressionContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.util.IOUtils;
 import org.objectweb.asm.ClassWriter;
@@ -45,8 +45,6 @@ import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.GeneratorAdapter;
 
-import static org.apache.lucene.expressions.js.JavascriptParser.ExpressionContext;
-
 /**
  * An expression compiler for javascript expressions.
  * <p>
@@ -74,7 +72,7 @@ import static org.apache.lucene.expressi
  * 
  * @lucene.experimental
  */
-public class JavascriptCompiler {
+public final class JavascriptCompiler {
   static final class Loader extends ClassLoader {
     Loader(ClassLoader parent) {
       super(parent);
@@ -111,10 +109,6 @@ public class JavascriptCompiler {
   private static final int MAX_SOURCE_LENGTH = 16384;
   
   final String sourceText;
-  final Map<String, Integer> externalsMap = new LinkedHashMap<>();
-  final ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
-  GeneratorAdapter gen;
-  
   final Map<String,Method> functions;
   
   /**
@@ -189,19 +183,18 @@ public class JavascriptCompiler {
    * @throws ParseException on failure to compile
    */
   private Expression compileExpression(ClassLoader parent) throws ParseException {
+    final Map<String, Integer> externalsMap = new LinkedHashMap<>();
+    final ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
+    
+    generateClass(getAntlrParseTree(), classWriter, externalsMap);
+    
     try {
-      ParseTree parseTree = getAntlrParseTree();
-
-      beginCompile();
-      internalCompile(parseTree);
-      endCompile();
-      
       final Class<? extends Expression> evaluatorClass = new Loader(parent)
         .define(COMPILED_EXPRESSION_CLASS, classWriter.toByteArray());
       final Constructor<? extends Expression> constructor = evaluatorClass.getConstructor(String.class, String[].class);
 
       return constructor.newInstance(sourceText, externalsMap.keySet().toArray(new String[externalsMap.size()]));
-    } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException exception) {
+    } catch (ReflectiveOperationException exception) {
       throw new IllegalStateException("An internal error occurred attempting to compile the expression (" + sourceText + ").", exception);
     }
   }
@@ -229,16 +222,16 @@ public class JavascriptCompiler {
     }
   }
 
-  private void beginCompile() {
+  private void generateClass(final ParseTree parseTree, final ClassWriter classWriter, final Map<String, Integer> externalsMap) {
     classWriter.visit(CLASSFILE_VERSION,
         Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC,
         COMPILED_EXPRESSION_INTERNAL,
         null, EXPRESSION_TYPE.getInternalName(), null);
-    String clippedSourceText = (sourceText.length() <= MAX_SOURCE_LENGTH) ?
+    final String clippedSourceText = (sourceText.length() <= MAX_SOURCE_LENGTH) ?
         sourceText : (sourceText.substring(0, MAX_SOURCE_LENGTH - 3) + "...");
     classWriter.visitSource(clippedSourceText, null);
     
-    GeneratorAdapter constructor = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC,
+    final GeneratorAdapter constructor = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC,
         EXPRESSION_CTOR, null, null, classWriter);
     constructor.loadThis();
     constructor.loadArgs();
@@ -246,13 +239,10 @@ public class JavascriptCompiler {
     constructor.returnValue();
     constructor.endMethod();
     
-    gen = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC,
+    final GeneratorAdapter gen = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC,
         EVALUATE_METHOD, null, null, classWriter);
-  }
 
-  // internalCompile is used to create an anonymous inner class around the ANTLR listener
-  // to completely hide the implementation details of expression compilation
-  private void internalCompile(ParseTree parseTree) {
+    // to completely hide the ANTLR visitor we use an anonymous impl:
     new JavascriptBaseVisitor<Void>() {
       private final Deque<Type> typeStack = new ArrayDeque<>();
 
@@ -674,9 +664,7 @@ public class JavascriptCompiler {
         }
       }
     }.visit(parseTree);
-  }
-  
-  private void endCompile() {
+    
     gen.returnValue();
     gen.endMethod();