[
https://issues.apache.org/jira/browse/DRILL-5116?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15800202#comment-15800202
]
ASF GitHub Bot commented on DRILL-5116:
---------------------------------------
Github user Ben-Zvi commented on a diff in the pull request:
https://github.com/apache/drill/pull/716#discussion_r94706789
--- Diff:
exec/java-exec/src/main/java/org/apache/drill/exec/expr/ClassGenerator.java ---
@@ -374,6 +388,124 @@ public HoldingContainer declare(MajorType t, boolean
includeNewInstance) {
return this.workspaceVectors;
}
+ /**
+ * Prepare the generated class for use as a plain-old Java class
+ * (to be compiled by a compiler and directly loaded without a
+ * byte-code merge. Three additions are necessary:
+ * <ul>
+ * <li>The class must extend its template as we won't merge byte
+ * codes.</li>
+ * <li>A constructor is required to call the <tt>__DRILL_INIT__</tt>
+ * method. If this is a nested class, then the constructor must
+ * include parameters defined by the base class.</li>
+ * <li>For each nested class, create a method that creates an
+ * instance of that nested class using a well-defined name. This
+ * method overrides the base class method defined for this purpose.</li>
+ */
+
+ public void preparePlainJava() {
+
+ // If this generated class uses the "straight Java" technique
+ // (no byte code manipulation), then the class must extend the
+ // template so it plays by normal Java rules for finding the
+ // template methods via inheritance rather than via code injection.
+
+ Class<?> baseClass = sig.getSignatureClass();
+ clazz._extends(baseClass);
+
+ // Create a constuctor for the class: either a default one,
+ // or (for nested classes) one that passes along arguments to
+ // the super class constructor.
+
+ Constructor<?>[] ctors = baseClass.getConstructors();
+ for (Constructor<?> ctor : ctors) {
+ addCtor(ctor.getParameterTypes());
+ }
+
+ // Some classes have no declared constructor, but we need to generate
one
+ // anyway.
+
+ if ( ctors.length == 0 ) {
+ addCtor( new Class<?>[] {} );
+ }
+
+ // Repeat for inner classes.
+
+ for(ClassGenerator<T> child : innerClasses.values()) {
+ child.preparePlainJava();
+
+ // If there are inner classes, then we need to generate a "shim"
method
+ // to instantiate that class.
+ //
+ // protected TemplateClass.TemplateInnerClass newTemplateInnerClass(
args... ) {
+ // return new GeneratedClass.GeneratedInnerClass( args... );
+ // }
+ //
+ // The name is special, it is "new" + inner class name. The template
must
+ // provide a method of this name that creates the inner class
instance.
+
+ String innerClassName = child.clazz.name();
+ JMethod shim = clazz.method(JMod.PROTECTED,
child.sig.getSignatureClass(), "new" + innerClassName);
+ JInvocation childNew = JExpr._new(child.clazz);
+ Constructor<?>[] childCtors =
child.sig.getSignatureClass().getConstructors();
+ Class<?>[] params;
+ if (childCtors.length==0) {
+ params = new Class<?>[0];
+ } else {
+ params = childCtors[0].getParameterTypes();
+ }
+ for (int i = 1; i < params.length; i++) {
+ Class<?> p = params[i];
+ childNew.arg(shim.param(model._ref(p), "arg" + i));
+ }
+ shim.body()._return(childNew);
+ }
+ }
+
+ /**
+ * The code generator creates a method called __DRILL_INIT__ which takes
the
+ * place of the constructor when the code goes though the byte code
merge.
+ * For Plain-old Java, we call the method from a constructor created for
+ * that purpose. (Generated code, fortunately, never includes a
constructor,
+ * so we can create one.) Since the init block throws an exception (which
+ * should never occur), the generated constructor converts the checked
+ * exception into an unchecked one so as to not require changes to the
+ * various places that create instances of the generated classes.
+ *
+ * Example:<code><pre>
+ * public StreamingAggregatorGen1() {
+ * try {
+ * __DRILL_INIT__();
+ * } catch (SchemaChangeException e) {
+ * throw new UnsupportedOperationException(e);
+ * }
+ * }</pre></code>
+ *
+ * Note: in Java 8 we'd use the <tt>Parameter</tt> class defined in
Java's
+ * introspection package. But, Drill prefers Java 7 which only provides
+ * parameter types.
+ */
+
+ private void addCtor(Class<?>[] parameters) {
+ JMethod ctor = clazz.constructor(JMod.PUBLIC);
+ JInvocation superCall = null;
--- End diff --
A minor suggestion: Write all the code between lines 491-502 inclusive
inside a single if statement:
```
// if there are parameters, need to pass them to the super class
if ( parameters.length > 0 ) {
JInvocation superCall = JExpr.invoke("super");
......
}
```
> Enable generated code debugging in each Drill operator
> ------------------------------------------------------
>
> Key: DRILL-5116
> URL: https://issues.apache.org/jira/browse/DRILL-5116
> Project: Apache Drill
> Issue Type: Improvement
> Affects Versions: 1.9.0
> Reporter: Paul Rogers
> Assignee: Paul Rogers
> Priority: Minor
>
> DRILL-5052 adds the ability to debug generated code. Some of the code
> generated by Drill's operators has minor problems when compiled directly
> using the new technique. These issues are ignore by the byte-code-merge
> technique uses in production. This ticket asks to try the DRILL-5052 feature
> in each operator, clean up any minor problems, and ensure each operator
> generates code suitable for debugging. Use the new
> {{CodeGenerator.plainOldJavaCapable()}} method to mark each generated class
> as ready for "plain-old Java" code gen.
> The advantages of this feature are two:
> 1. Ability to step through the generated code to increase understanding of
> existing operators and to ease development of improvements to existing
> operators and of any new operators we choose to create.
> 2. Open the door to experimenting with how to improve performance of the
> generated code.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)