Mercurial > hg > graal-compiler
diff src/share/tools/MakeDeps/Database.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | 8b48a7bd2bf7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/MakeDeps/Database.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,544 @@ +/* + * Copyright 1999-2005 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. + * + */ + +import java.io.*; +import java.util.*; + +public class Database { + private MacroDefinitions macros; + // allFiles is kept in lexicographically sorted order. See get(). + private FileList allFiles; + // files that have implicit dependency on platform files + // e.g. os.hpp: os_<os_family>.hpp os_<os_arch>.hpp but only + // recorded if the platform file was seen. + private FileList platformFiles; + private FileList outerFiles; + private FileList indivIncludes; + private FileList grandInclude; // the results for the grand include file + private long threshold; + private int nOuterFiles; + private int nPrecompiledFiles; + private boolean missingOk; + private Platform plat; + /** These allow you to specify files not in the include database + which are prepended and appended to the file list, allowing + you to have well-known functions at the start and end of the + text segment (allows us to find out in a portable fashion + whether the current PC is in VM code or not upon a crash) */ + private String firstFile; + private String lastFile; + + public Database(Platform plat, long t) { + this.plat = plat; + macros = new MacroDefinitions(); + allFiles = new FileList("allFiles", plat); + platformFiles = new FileList("platformFiles", plat); + outerFiles = new FileList("outerFiles", plat); + indivIncludes = new FileList("IndivIncludes", plat); + grandInclude = new FileList(plat.getGIFileTemplate().nameOfList(), plat); + + threshold = t; + nOuterFiles = 0; + nPrecompiledFiles = 0; + missingOk = false; + firstFile = null; + lastFile = null; + }; + + public FileList getAllFiles() { + return allFiles; + } + + public Iterator getMacros() { + return macros.getMacros(); + } + + public void canBeMissing() { + missingOk = true; + } + + public boolean hfileIsInGrandInclude(FileList hfile, FileList cfile) { + return ((hfile.getCount() >= threshold) && (cfile.getUseGrandInclude())); + } + + /** These allow you to specify files not in the include database + which are prepended and appended to the file list, allowing + you to have well-known functions at the start and end of the + text segment (allows us to find out in a portable fashion + whether the current PC is in VM code or not upon a crash) */ + public void setFirstFile(String fileName) { + firstFile = fileName; + } + + public void setLastFile(String fileName) { + lastFile = fileName; + } + + public void get(String platFileName, String dbFileName) + throws FileFormatException, IOException, FileNotFoundException { + macros.readFrom(platFileName, missingOk); + + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(dbFileName)); + } catch (FileNotFoundException e) { + if (missingOk) { + return; + } else { + throw(e); + } + } + System.out.println("\treading database: " + dbFileName); + String line; + int lineNo = 0; + do { + line = reader.readLine(); + lineNo++; + if (line != null) { + StreamTokenizer tokenizer = + new StreamTokenizer(new StringReader(line)); + tokenizer.slashSlashComments(true); + tokenizer.wordChars('_', '_'); + tokenizer.wordChars('<', '>'); + // NOTE: if we didn't have to do this line by line, + // we could trivially recognize C-style comments as + // well. + // tokenizer.slashStarComments(true); + int numTok = 0; + int res; + String unexpandedIncluder = null; + String unexpandedIncludee = null; + do { + res = tokenizer.nextToken(); + if (res != StreamTokenizer.TT_EOF) { + if (numTok == 0) { + unexpandedIncluder = tokenizer.sval; + } else if (numTok == 1) { + unexpandedIncludee = tokenizer.sval; + } else { + throw new FileFormatException( + "invalid line: \"" + line + + "\". Error position: line " + lineNo + ); + } + numTok++; + } + } while (res != StreamTokenizer.TT_EOF); + + if ((numTok != 0) && (numTok != 2)) { + throw new FileFormatException( + "invalid line: \"" + line + + "\". Error position: line " + lineNo + ); + } + + if (numTok == 2) { + // Non-empty line + String includer = macros.expand(unexpandedIncluder); + String includee = macros.expand(unexpandedIncludee); + + if (includee.equals(plat.generatePlatformDependentInclude())) { + MacroDefinitions localExpander = macros.copy(); + MacroDefinitions localExpander2 = macros.copy(); + localExpander.setAllMacroBodiesTo("pd"); + localExpander2.setAllMacroBodiesTo(""); + + // unexpanded_includer e.g. thread_<os_arch>.hpp + // thread_solaris_i486.hpp -> _thread_pd.hpp.incl + + FileName pdName = + plat.getInclFileTemplate().copyStem( + localExpander.expand(unexpandedIncluder) + ); + + // derive generic name from platform specific name + // e.g. os_<arch_os>.hpp => os.hpp. We enforce the + // restriction (imperfectly) noted in includeDB_core + // that platform specific files will have an underscore + // preceding the macro invocation. + + // First expand macro as null string. + + String newIncluder_temp = + localExpander2.expand(unexpandedIncluder); + + // Now find "_." and remove the underscore. + + String newIncluder = ""; + + int len = newIncluder_temp.length(); + int count = 0; + + for ( int i = 0; i < len - 1 ; i++ ) { + if (newIncluder_temp.charAt(i) == '_' && newIncluder_temp.charAt(i+1) == '.') { + count++; + } else { + newIncluder += newIncluder_temp.charAt(i); + } + } + newIncluder += newIncluder_temp.charAt(len-1); + + if (count != 1) { + throw new FileFormatException( + "Unexpected filename format for platform dependent file.\nline: \"" + line + + "\".\nError position: line " + lineNo + ); + } + + FileList p = allFiles.listForFile(includer); + p.setPlatformDependentInclude(pdName.dirPreStemSuff()); + + // Add an implicit dependency on platform + // specific file for the generic file + + p = platformFiles.listForFile(newIncluder); + + // if this list is empty then this is 1st + // occurance of a platform dependent file and + // we need a new version of the include file. + // Otherwise we just append to the current + // file. + + PrintWriter pdFile = + new PrintWriter( + new FileWriter(pdName.dirPreStemSuff(), + !p.isEmpty()) + ); + pdFile.println("# include \"" + includer + "\""); + pdFile.close(); + + // Add the platform specific file to the list + // for this generic file. + + FileList q = allFiles.listForFile(includer); + p.addIfAbsent(q); + } else { + FileList p = allFiles.listForFile(includer); + if (isOuterFile(includer)) + outerFiles.addIfAbsent(p); + + if (includee.equals(plat.noGrandInclude())) { + p.setUseGrandInclude(false); + } else { + FileList q = allFiles.listForFile(includee); + p.addIfAbsent(q); + } + } + } + } + } while (line != null); + reader.close(); + + // Keep allFiles in well-known order so we can easily determine + // whether the known files are the same + allFiles.sortByName(); + + // Add first and last files differently to prevent a mistake + // in ordering in the include databases from breaking the + // error reporting in the VM. + if (firstFile != null) { + FileList p = allFiles.listForFile(firstFile); + allFiles.setFirstFile(p); + outerFiles.setFirstFile(p); + } + + if (lastFile != null) { + FileList p = allFiles.listForFile(lastFile); + allFiles.setLastFile(p); + outerFiles.setLastFile(p); + } + } + + public void compute() { + System.out.println("\tcomputing closures\n"); + // build both indiv and grand results + for (Iterator iter = outerFiles.iterator(); iter.hasNext(); ) { + indivIncludes.add(((FileList) iter.next()).doCFile()); + ++nOuterFiles; + } + + if (!plat.haveGrandInclude()) + return; // nothing in grand include + + // count how many times each include is included & add em to grand + for (Iterator iter = indivIncludes.iterator(); iter.hasNext(); ) { + FileList indivInclude = (FileList) iter.next(); + if (!indivInclude.getUseGrandInclude()) { + continue; // do not bump count if my files cannot be + // in grand include + } + indivInclude.doFiles(grandInclude); // put em on + // grand_include list + for (Iterator incListIter = indivInclude.iterator(); + incListIter.hasNext(); ) { + ((FileList) incListIter.next()).incrementCount(); + } + } + } + + // Not sure this is necessary in Java + public void verify() { + for (Iterator iter = indivIncludes.iterator(); iter.hasNext(); ) { + if (iter.next() == null) { + plat.abort(); + } + } + } + + public void put() throws IOException { + writeIndividualIncludes(); + + if (plat.haveGrandInclude()) + writeGrandInclude(); + + writeGrandUnixMakefile(); + } + + private void writeIndividualIncludes() throws IOException { + System.out.println("\twriting individual include files\n"); + + for (Iterator iter = indivIncludes.iterator(); iter.hasNext(); ) { + FileList list = (FileList) iter.next(); + System.out.println("\tcreating " + list.getName()); + list.putInclFile(this); + } + } + + private void writeGrandInclude() throws IOException { + System.out.println("\twriting grand include file\n"); + PrintWriter inclFile = + new PrintWriter(new FileWriter(plat.getGIFileTemplate().dirPreStemSuff())); + plat.writeGIPragma(inclFile); + for (Iterator iter = grandInclude.iterator(); iter.hasNext(); ) { + FileList list = (FileList) iter.next(); + if (list.getCount() >= threshold) { + inclFile.println("# include \"" + + plat.getGIFileTemplate().getInvDir() + + list.getName() + + "\""); + nPrecompiledFiles += 1; + } + } + inclFile.println(); + inclFile.close(); + } + + private void writeGrandUnixMakefile() throws IOException { + if (!plat.writeDeps()) + return; + + System.out.println("\twriting dependencies file\n"); + PrintWriter gd = + new PrintWriter(new FileWriter( + plat.getGDFileTemplate().dirPreStemSuff()) + ); + gd.println("# generated by makeDeps"); + gd.println(); + + + // HACK ALERT. The compilation of ad_<arch> files is very slow. + // We want to start compiling them as early as possible. The compilation + // order on unix is dependant on the order we emit files here. + // By sorting the output before emitting it, we expect + // that ad_<arch> will be compiled early. + boolean shouldSortObjFiles = true; + + if (shouldSortObjFiles) { + ArrayList sortList = new ArrayList(); + + // We need to preserve the ordering of the first and last items + // in outerFiles. + int size = outerFiles.size() - 1; + String firstName = removeSuffixFrom(((FileList)outerFiles.get(0)).getName()); + String lastName = removeSuffixFrom(((FileList)outerFiles.get(size)).getName()); + + for (int i=1; i<size; i++) { + FileList anOuterFile = (FileList)outerFiles.get(i); + String stemName = removeSuffixFrom(anOuterFile.getName()); + sortList.add(stemName); + } + Collections.sort(sortList); + + // write Obj_Files = ... + gd.println("Obj_Files = \\"); + gd.println(firstName + plat.objFileSuffix() + " \\"); + for (Iterator iter = sortList.iterator(); iter.hasNext(); ) { + gd.println(iter.next() + plat.objFileSuffix() + " \\"); + } + gd.println(lastName + plat.objFileSuffix() + " \\"); + gd.println(); + gd.println(); + } else { + // write Obj_Files = ... + gd.println("Obj_Files = \\"); + for (Iterator iter = outerFiles.iterator(); iter.hasNext(); ) { + FileList anOuterFile = (FileList) iter.next(); + + String stemName = removeSuffixFrom(anOuterFile.getName()); + gd.println(stemName + plat.objFileSuffix() + " \\"); + } + gd.println(); + gd.println(); + } + + if (nPrecompiledFiles > 0) { + // write Precompiled_Files = ... + gd.println("Precompiled_Files = \\"); + for (Iterator iter = grandInclude.iterator(); iter.hasNext(); ) { + FileList list = (FileList) iter.next(); + gd.println(list.getName() + " \\"); + } + gd.println(); + gd.println(); + } + + gd.println("DTraced_Files = \\"); + for (Iterator iter = outerFiles.iterator(); iter.hasNext(); ) { + FileList anOuterFile = (FileList) iter.next(); + + if (anOuterFile.hasListForFile("dtrace.hpp")) { + String stemName = removeSuffixFrom(anOuterFile.getName()); + gd.println(stemName + plat.objFileSuffix() + " \\"); + } + } + gd.println(); + gd.println(); + + { + // write each dependency + + for (Iterator iter = indivIncludes.iterator(); iter.hasNext(); ) { + + FileList anII = (FileList) iter.next(); + + String stemName = removeSuffixFrom(anII.getName()); + String inclFileName = + plat.getInclFileTemplate().copyStem(anII.getName()). + preStemSuff(); + + gd.println(stemName + plat.objFileSuffix() + " " + + stemName + plat.asmFileSuffix() + ": \\"); + + printDependentOn(gd, anII.getName()); + // this gets the include file that includes all that + // this file needs (first level) since nested includes + // are skipped to avoid cycles. + printDependentOn(gd, inclFileName); + + if ( plat.haveGrandInclude() ) { + printDependentOn(gd, + plat.getGIFileTemplate().preStemSuff()); + } + + for (Iterator iiIter = anII.iterator(); iiIter.hasNext(); ) { + FileList hfile = (FileList) iiIter.next(); + if (!hfileIsInGrandInclude(hfile, anII) || + plat.writeDependenciesOnHFilesFromGI()) { + printDependentOn(gd, hfile.getName()); + } + if (platformFiles.hasListForFile(hfile.getName())) { + FileList p = + platformFiles.listForFile(hfile.getName());; + for (Iterator hiIter = p.iterator(); + hiIter.hasNext(); ) { + FileList hi2 = (FileList) hiIter.next(); + if (!hfileIsInGrandInclude(hi2, p)) { + printDependentOn(gd, hi2.getName()); + } + } + } + } + + if (plat.includeGIDependencies() + && nPrecompiledFiles > 0 + && anII.getUseGrandInclude()) { + gd.println(" $(Precompiled_Files) \\"); + } + gd.println(); + gd.println(); + } + } + + gd.close(); + } + + public void putDiffs(Database previous) throws IOException { + System.out.println("\tupdating output files\n"); + + if (!indivIncludes.compareLists(previous.indivIncludes) + || !grandInclude.compareLists(previous.grandInclude)) { + System.out.println("The order of .c or .s has changed, or " + + "the grand include file has changed."); + put(); + return; + } + + Iterator curIter = indivIncludes.iterator(); + Iterator prevIter = previous.indivIncludes.iterator(); + + try { + while (curIter.hasNext()) { + FileList newCFileList = (FileList) curIter.next(); + FileList prevCFileList = (FileList) prevIter.next(); + if (!newCFileList.compareLists(prevCFileList)) { + System.out.println("\tupdating " + newCFileList.getName()); + newCFileList.putInclFile(this); + } + } + } + catch (Exception e) { + throw new InternalError("assertion failure: cur and prev " + + "database lists changed unexpectedly."); + } + + writeGrandUnixMakefile(); + } + + private void printDependentOn(PrintWriter gd, String name) { + gd.print(" "); + gd.print(plat.dependentPrefix() + name); + } + + private boolean isOuterFile(String s) { + int len = s.length(); + String[] suffixes = plat.outerSuffixes(); + for (int i = 0; i < suffixes.length; i++) { + String suffix = suffixes[i]; + int suffLen = suffix.length(); + if ((len >= suffLen) && + (plat.fileNameStringEquality(s.substring(len - suffLen), + suffix))) { + return true; + } + } + return false; + } + + private String removeSuffixFrom(String s) { + int idx = s.lastIndexOf('.'); + if (idx <= 0) + plat.abort(); + return s.substring(0, idx); + } +}