Mercurial > hg > graal-compiler
diff agent/src/share/classes/sun/jvm/hotspot/utilities/soql/SOQLEngine.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | c18cbe5936b8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/SOQLEngine.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,265 @@ +/* + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.utilities.soql; + +import java.util.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.memory.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.utilities.*; + +/** + * This is SOQL (Simple Object Query Language) engine. This + * uses JavaScript engine for the "select" and "where" expression + * parts. + */ +public class SOQLEngine extends JSJavaScriptEngine { + public static synchronized SOQLEngine getEngine() { + if (soleInstance == null) { + soleInstance = new SOQLEngine(); + } + return soleInstance; + } + + /** + Query is of the form + + select <java script code to select> + [ from [instanceof] <class name> [<identifier>] + [ where <java script boolean expression> ] + ] + */ + public synchronized void executeQuery(String query, ObjectVisitor visitor) + throws SOQLException { + debugPrint("query : " + query); + StringTokenizer st = new StringTokenizer(query); + if (st.hasMoreTokens()) { + String first = st.nextToken(); + if (! first.equals("select") ) { + throw new SOQLException("query syntax error: no 'select' clause"); + } + } else { + throw new SOQLException("query syntax error: no 'select' clause"); + } + + int selectStart = query.indexOf("select"); + int fromStart = query.indexOf("from"); + + String selectExpr = null; + String className = null; + boolean isInstanceOf = false; + String whereExpr = null; + String identifier = null; + + if (fromStart != -1) { + selectExpr = query.substring(selectStart + "select".length(), fromStart); + st = new StringTokenizer(query.substring(fromStart + "from".length())); + + if (st.hasMoreTokens()) { + String tmp = st.nextToken(); + if (tmp.equals("instanceof")) { + isInstanceOf = true; + if (! st.hasMoreTokens()) { + throw new SOQLException("no class name after 'instanceof'"); + } + className = st.nextToken(); + } else { + className = tmp; + } + } else { + throw new SOQLException("query syntax error: class name must follow 'from'"); + } + + if (st.hasMoreTokens()) { + identifier = st.nextToken(); + if (identifier.equals("where")) { + throw new SOQLException("query syntax error: identifier should follow class name"); + } + if (st.hasMoreTokens()) { + String tmp = st.nextToken(); + if (! tmp.equals("where")) { + throw new SOQLException("query syntax error: 'where' clause expected after 'from' clause"); + } + int whereEnd = query.lastIndexOf("where") + 5; // "where".length + whereExpr = query.substring(whereEnd); + } + } else { + throw new SOQLException("query syntax error: identifier should follow class name"); + } + } else { // no from clause + selectExpr = query.substring(selectStart + "select".length(), query.length()); + } + + executeQuery(new SOQLQuery(selectExpr, isInstanceOf, className, identifier, whereExpr), visitor); + } + + private void executeQuery(SOQLQuery q, ObjectVisitor visitor) throws SOQLException { + InstanceKlass kls = null; + if (q.className != null) { + kls = SystemDictionaryHelper.findInstanceKlass(q.className); + if (kls == null) { + throw new SOQLException(q.className + " is not found!"); + } + } + + + StringBuffer buf = new StringBuffer(); + buf.append("function result("); + if (q.identifier != null) { + buf.append(q.identifier); + } + buf.append(") { return "); + buf.append(q.selectExpr.replace('\n', ' ')); + buf.append("; }"); + + String selectCode = buf.toString(); + debugPrint(selectCode); + String whereCode = null; + if (q.whereExpr != null) { + buf = new StringBuffer(); + buf.append("function filter("); + buf.append(q.identifier); + buf.append(") { return "); + buf.append(q.whereExpr.replace('\n', ' ')); + buf.append("; }"); + whereCode = buf.toString(); + debugPrint(whereCode); + } else { + whereCode = "filter = null;"; + } + + beginQuery(); + // compile select expression and where condition + evalString(selectCode, "", 1); + evalString(whereCode, "", 1); + + // iterate thru heap, if needed + if (q.className != null) { + try { + iterateOops(kls, visitor, q.isInstanceOf); + } finally { + endQuery(); + } + } else { + // simple "select <expr>" query + try { + Object select = call("result", new Object[] {}); + visitor.visit(select); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void dispatchObject(Oop oop, ObjectVisitor visitor, boolean filterExists) { + JSJavaObject jsObj = factory.newJSJavaObject(oop); + Object[] args = new Object[] { jsObj }; + boolean b = true; + + try { + if (filterExists) { + Object res = call("filter", args); + if (res instanceof Boolean) { + b = ((Boolean)res).booleanValue(); + } else if (res instanceof Number) { + b = ((Number)res).intValue() != 0; + } else { + b = (res != null); + } + } + + if (b) { + Object select = call("result", args); + visitor.visit(select); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void iterateOops(final InstanceKlass ik, final ObjectVisitor visitor, + boolean includeSubtypes) { + ObjectHeap oh = VM.getVM().getObjectHeap(); + oh.iterateObjectsOfKlass(new HeapVisitor() { + boolean filterExists; + public void prologue(long usedSize) { + filterExists = getScriptEngine().get("filter") != null; + } + public boolean doObj(Oop obj) { + dispatchObject(obj, visitor, filterExists); + return false; + } + public void epilogue() {} + }, ik, includeSubtypes); + } + + // we create fresh ObjectReader and factory to avoid + // excessive cache across queries. + private void beginQuery() { + objReader = new ObjectReader(); + factory = new JSJavaFactoryImpl(); + } + + // at the end of query we clear object reader cache + // and factory cache + private void endQuery() { + objReader = null; + factory = null; + } + + protected ObjectReader getObjectReader() { + return objReader; + } + + protected JSJavaFactory getJSJavaFactory() { + return factory; + } + + protected boolean isQuitting() { + return false; + } + + protected void quit() { + // do nothing + } + + private static void debugPrint(String msg) { + if (debug) System.out.println(msg); + } + + private static final boolean debug; + static { + debug = System.getProperty("sun.jvm.hotspot.utilities.soql.SOQLEngine.debug") != null; + } + + protected SOQLEngine() { + super(debug); + start(); + } + + private ObjectReader objReader; + private JSJavaFactory factory; + private static SOQLEngine soleInstance; +}