1 21 package com.db4o.nativequery.optimization; 22 23 import EDU.purdue.cs.bloat.editor.*; 24 import EDU.purdue.cs.bloat.reflect.*; 25 26 import com.db4o.foundation.*; 27 import com.db4o.inside.query.*; 28 import com.db4o.nativequery.expr.*; 29 import com.db4o.nativequery.expr.cmp.*; 30 import com.db4o.query.*; 31 32 public class SODABloatMethodBuilder { 33 private final static boolean LOG_BYTECODE=false; 34 35 private MethodEditor methodEditor; 36 37 private MemberRef descendRef; 38 private MemberRef constrainRef; 39 private MemberRef greaterRef; 40 private MemberRef smallerRef; 41 private MemberRef containsRef; 42 private MemberRef startsWithRef; 43 private MemberRef endsWithRef; 44 private MemberRef notRef; 45 private MemberRef andRef; 46 private MemberRef orRef; 47 private Type queryType; 48 49 private class SODABloatMethodVisitor implements ExpressionVisitor { 50 51 private Class predicateClass; 52 private Class candidateClass; 53 54 public SODABloatMethodVisitor(Class predicateClass, ClassLoader classLoader) { 55 this.predicateClass=predicateClass; 56 } 57 58 public void visit(AndExpression expression) { 59 expression.left().accept(this); 60 expression.right().accept(this); 61 methodEditor.addInstruction(Opcode.opc_invokeinterface,andRef); 62 } 63 64 public void visit(BoolConstExpression expression) { 65 methodEditor.addInstruction(Opcode.opc_aload,new LocalVariable("query",queryType,1)); 66 } 68 69 public void visit(OrExpression expression) { 70 expression.left().accept(this); 71 expression.right().accept(this); 72 methodEditor.addInstruction(Opcode.opc_invokeinterface,orRef); 73 } 74 75 public void visit(final ComparisonExpression expression) { 76 methodEditor.addInstruction(Opcode.opc_aload,new LocalVariable("query",queryType,1)); 77 Iterator4 fieldNames = fieldNames(expression.left()); 78 while(fieldNames.moveNext()) { 79 methodEditor.addInstruction(Opcode.opc_ldc,(String )fieldNames.current()); 80 methodEditor.addInstruction(Opcode.opc_invokeinterface,descendRef); 81 } 82 expression.right().accept(new ComparisonBytecodeGeneratingVisitor(methodEditor,predicateClass,candidateClass)); 83 methodEditor.addInstruction(Opcode.opc_invokeinterface,constrainRef); 84 if(!expression.op().equals(ComparisonOperator.EQUALS)) { 85 if(expression.op().equals(ComparisonOperator.GREATER)) { 86 methodEditor.addInstruction(Opcode.opc_invokeinterface,greaterRef); 87 } 88 else if(expression.op().equals(ComparisonOperator.SMALLER)) { 89 methodEditor.addInstruction(Opcode.opc_invokeinterface,smallerRef); 90 } 91 else if(expression.op().equals(ComparisonOperator.CONTAINS)) { 92 methodEditor.addInstruction(Opcode.opc_invokeinterface,containsRef); 93 } 94 else if(expression.op().equals(ComparisonOperator.STARTSWITH)) { 95 methodEditor.addInstruction(Opcode.opc_ldc, new Integer (1)); 96 methodEditor.addInstruction(Opcode.opc_invokeinterface,startsWithRef); 97 } 98 else if(expression.op().equals(ComparisonOperator.ENDSWITH)) { 99 methodEditor.addInstruction(Opcode.opc_ldc, new Integer (1)); 100 methodEditor.addInstruction(Opcode.opc_invokeinterface,endsWithRef); 101 } 102 else { 103 throw new RuntimeException ("Cannot interpret constraint: "+expression.op()); 104 } 105 } 106 } 107 108 public void visit(NotExpression expression) { 109 expression.expr().accept(this); 110 methodEditor.addInstruction(Opcode.opc_invokeinterface,notRef); 111 } 112 113 private Iterator4 fieldNames(FieldValue fieldValue) { 114 Collection4 coll=new Collection4(); 115 ComparisonOperand curOp=fieldValue; 116 while(curOp instanceof FieldValue) { 117 FieldValue curField=(FieldValue)curOp; 118 coll.prepend(curField.fieldName()); 119 curOp=curField.parent(); 120 } 121 return coll.iterator(); 122 } 123 } 124 125 public SODABloatMethodBuilder() { 126 buildMethodReferences(); 127 } 128 129 public MethodEditor injectOptimization(Expression expr, ClassEditor classEditor,ClassLoader classLoader) { 130 classEditor.addInterface(Db4oEnhancedFilter.class); 131 methodEditor=new MethodEditor(classEditor,Modifiers.PUBLIC,Void.TYPE,"optimizeQuery",new Class []{Query.class},new Class []{}); 132 methodEditor.addLabel(new Label(0,true)); 133 try { 134 Class predicateClass = classLoader.loadClass(classEditor.name().replace('/','.')); 135 expr.accept(new SODABloatMethodVisitor(predicateClass,classLoader)); 136 methodEditor.addInstruction(Opcode.opc_pop); 137 methodEditor.addLabel(new Label(1,false)); 138 methodEditor.addInstruction(Opcode.opc_return); 139 methodEditor.addLabel(new Label(2,true)); 140 if(LOG_BYTECODE) { 141 methodEditor.print(System.out); 142 } 143 return methodEditor; 144 } catch (ClassNotFoundException exc) { 145 throw new RuntimeException (exc.getMessage()); 146 } 147 } 148 149 private void buildMethodReferences() { 150 queryType = createType(Query.class); 151 descendRef=createMethodReference(Query.class,"descend",new Class []{String .class},Query.class); 152 constrainRef=createMethodReference(Query.class,"constrain",new Class []{Object .class},Constraint.class); 153 greaterRef=createMethodReference(Constraint.class,"greater",new Class []{},Constraint.class); 154 smallerRef=createMethodReference(Constraint.class,"smaller",new Class []{},Constraint.class); 155 containsRef=createMethodReference(Constraint.class,"contains",new Class []{},Constraint.class); 156 startsWithRef=createMethodReference(Constraint.class,"startsWith",new Class []{Boolean.TYPE},Constraint.class); 157 endsWithRef=createMethodReference(Constraint.class,"endsWith",new Class []{Boolean.TYPE},Constraint.class); 158 notRef=createMethodReference(Constraint.class,"not",new Class []{},Constraint.class); 159 andRef=createMethodReference(Constraint.class,"and",new Class []{Constraint.class},Constraint.class); 160 orRef=createMethodReference(Constraint.class,"or",new Class []{Constraint.class},Constraint.class); 161 } 162 163 private MemberRef createMethodReference(Class parent,String name,Class [] args,Class ret) { 164 Type[] argTypes=new Type[args.length]; 165 for (int argIdx = 0; argIdx < args.length; argIdx++) { 166 argTypes[argIdx]=createType(args[argIdx]); 167 } 168 NameAndType nameAndType=new NameAndType(name,Type.getType(argTypes,createType(ret))); 169 return new MemberRef(createType(parent),nameAndType); 170 } 171 172 private Type createType(Class clazz) { 173 return Type.getType(clazz); 174 } 175 } 176 | Popular Tags |