/* * Copyright 1999-2006 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. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * 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. */ //todo: one might eliminate uninits.andSets when monotonic package com.sun.tools.javac.comp; import com.sun.tools.javac.code.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.JCTree.*; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTags.*; /** This pass implements boilerplate FJTask parallelization * transformations for DPJ programs. */ public class FJTaskHarness extends TreeScanner { protected static final Context.Key<FJTaskHarness> harnessKey = new Context.Key<FJTaskHarness>(); private final Name.Table names; private final Log log; private final Symtab syms; private final Types types; private final Check chk; private TreeMaker make; private Lint lint; private boolean classCanBeRun; public static FJTaskHarness instance(Context context) { FJTaskHarness instance = context.get(harnessKey); if (instance == null) instance = new FJTaskHarness(context); return instance; } protected FJTaskHarness(Context context) { context.put(harnessKey, this); names = Name.Table.instance(context); log = Log.instance(context); syms = Symtab.instance(context); types = Types.instance(context); chk = Check.instance(context); make = TreeMaker.instance(context); lint = Lint.instance(context); classCanBeRun = false; } /* *********************************************************************** * Visitor methods for statements and definitions *************************************************************************/ /* ------------ Visitor methods for various sorts of trees -------------*/ public void visitSpawn(DPJSpawn that) {} public void visitFinish(DPJFinish that) {} public void visitCobegin(DPJCobegin that) {} public void visitDPJForLoop(DPJForLoop that) {} public void visitClassDef(JCClassDecl tree) { boolean oldClassCanBeRun = classCanBeRun; classCanBeRun = false; super.visitClassDef(tree); if(classCanBeRun & (tree.mods.flags & INTERFACE)==0) { // We need to create a new class to handle FJTask // Make class extend FJTask if it does not already extend a class JCTree extending = make.Ident(names.fromString("RecursiveAction")); JCExpression originalMain = make.Ident(names.fromString("__dpj_run")); originalMain.setType(new Type(TypeTags.CLASS,null)); JCExpressionStatement dpjrun = make.Exec(make.App(originalMain)); List<JCExpression> thrown = List.<JCExpression>nil(). append(make.Ident(names.fromString("InterruptedException"))); // Create a boilerplate main method to invoke the main class // Add "private static String args" to class variable list tree.defs = tree.defs.prepend(make.VarDef( make.Modifiers(PRIVATE | STATIC), names.fromString("args"), null, make.TypeArray( make.Ident(names.fromString("String")), null, null), null)); // Add boilerplate "public static void main()" method to method list List<JCExpression> literalList = List.<JCExpression>nil(); JCFieldAccess runSelect = make.Select(make.Ident( names.fromString("DPJRuntime")), names.fromString("RuntimeState")); /*WHY IS THE FOLLOWING LINE NECESSARY???*/ runSelect.setType(new Type(TypeTags.CLASS,null)); // Assign statement JCFieldAccess initSelect = make.Select(runSelect, names.fromString("initialize")); initSelect.setType(new Type(TypeTags.CLASS,null)); JCExpressionStatement assign = make.Exec( make.Assign( make.Select(make.Ident(tree.name),names.fromString("args")), make.App(initSelect, List.<JCExpression>nil().append( make.Ident(names.fromString("args")))))); JCFieldAccess poolVar = make.Select(runSelect, names.fromString("pool")); runSelect = make.Select(runSelect, names.fromString("dpjNumThreads")); /*AGAIN: WHY IS THE FOLLOWING LINE NECESSARY???*/ runSelect.setType(new Type(TypeTags.CLASS,null)); literalList = literalList.append(runSelect); JCNewClass poolInstance = make.NewClass(null, null, null, null, make.Ident(names.fromString("ForkJoinPool")), literalList,null); JCExpressionStatement invocation = make.Exec(make.Assign(poolVar,poolInstance)); List<JCVariableDecl> params = List.<JCVariableDecl>nil(); params = params.append(make.VarDef( make.Modifiers(0), names.fromString("args"), null, make.TypeArray( make.Ident(names.fromString("String")), null, null), null)); thrown = List.<JCExpression>nil().append( make.Ident(names.fromString("Throwable"))); List<JCStatement> block = List.<JCStatement>nil(); block = block.append(assign); block = block.append(invocation); block = block.append(dpjrun); tree.defs = tree.defs.append(make.MethodDef( make.Modifiers(PUBLIC | STATIC), names.fromString("main"), make.TypeIdent(TypeTags.VOID), null, List.<JCTypeParameter>nil(), params, thrown, make.Block(0, block), null, null)); } classCanBeRun = oldClassCanBeRun; } public void visitMethodDef(JCMethodDecl tree) { //change public static void main() to public void run() if(tree.name.equals(names.fromString("main"))) { classCanBeRun = true; tree.name = names.fromString("__dpj_run"); tree.params = List.<JCVariableDecl>nil(); } super.visitMethodDef(tree); } public void visitTopLevel(JCCompilationUnit tree) { // Import FJTask library tree.defs = tree.defs.prepend(make.Import(make.Select(make.Select( make.Ident(names.fromString("jsr166y")), names.fromString("forkjoin")), names.asterisk),false)); super.visitTopLevel(tree); } }