KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > nativequery > optimization > SODABloatMethodBuilder


1 /* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com
2
3 This file is part of the db4o open source object database.
4
5 db4o is free software; you can redistribute it and/or modify it under
6 the terms of version 2 of the GNU General Public License as published
7 by the Free Software Foundation and as clarified by db4objects' GPL
8 interpretation policy, available at
9 http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
10 Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
11 Suite 350, San Mateo, CA 94403, USA.
12
13 db4o is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */

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 JavaDoc predicateClass;
52         private Class JavaDoc candidateClass;
53         
54         public SODABloatMethodVisitor(Class JavaDoc predicateClass, ClassLoader JavaDoc 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             //throw new RuntimeException("No boolean constants expected in parsed expression tree");
67
}
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 JavaDoc)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 JavaDoc(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 JavaDoc(1));
100                     methodEditor.addInstruction(Opcode.opc_invokeinterface,endsWithRef);
101                 }
102                 else {
103                     throw new RuntimeException JavaDoc("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 JavaDoc classLoader) {
130         classEditor.addInterface(Db4oEnhancedFilter.class);
131         methodEditor=new MethodEditor(classEditor,Modifiers.PUBLIC,Void.TYPE,"optimizeQuery",new Class JavaDoc[]{Query.class},new Class JavaDoc[]{});
132         methodEditor.addLabel(new Label(0,true));
133         try {
134             Class JavaDoc 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 JavaDoc exc) {
145             throw new RuntimeException JavaDoc(exc.getMessage());
146         }
147     }
148     
149     private void buildMethodReferences() {
150         queryType = createType(Query.class);
151         descendRef=createMethodReference(Query.class,"descend",new Class JavaDoc[]{String JavaDoc.class},Query.class);
152         constrainRef=createMethodReference(Query.class,"constrain",new Class JavaDoc[]{Object JavaDoc.class},Constraint.class);
153         greaterRef=createMethodReference(Constraint.class,"greater",new Class JavaDoc[]{},Constraint.class);
154         smallerRef=createMethodReference(Constraint.class,"smaller",new Class JavaDoc[]{},Constraint.class);
155         containsRef=createMethodReference(Constraint.class,"contains",new Class JavaDoc[]{},Constraint.class);
156         startsWithRef=createMethodReference(Constraint.class,"startsWith",new Class JavaDoc[]{Boolean.TYPE},Constraint.class);
157         endsWithRef=createMethodReference(Constraint.class,"endsWith",new Class JavaDoc[]{Boolean.TYPE},Constraint.class);
158         notRef=createMethodReference(Constraint.class,"not",new Class JavaDoc[]{},Constraint.class);
159         andRef=createMethodReference(Constraint.class,"and",new Class JavaDoc[]{Constraint.class},Constraint.class);
160         orRef=createMethodReference(Constraint.class,"or",new Class JavaDoc[]{Constraint.class},Constraint.class);
161     }
162     
163     private MemberRef createMethodReference(Class JavaDoc parent,String JavaDoc name,Class JavaDoc[] args,Class JavaDoc 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 JavaDoc clazz) {
173         return Type.getType(clazz);
174     }
175 }
176
Popular Tags