DumpBytecode.java revision 1350:3cb11f4d617e
11541Srgrimes/* 21541Srgrimes * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 31541Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41541Srgrimes * 551138Salfred * This code is free software; you can redistribute it and/or modify it 685891Sphk * under the terms of the GNU General Public License version 2 only, as 71541Srgrimes * published by the Free Software Foundation. Oracle designates this 81541Srgrimes * particular file as subject to the "Classpath" exception as provided 91541Srgrimes * by Oracle in the LICENSE file that accompanied this code. 101541Srgrimes * 1164002Speter * This code is distributed in the hope that it will be useful, but WITHOUT 121541Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 131541Srgrimes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 141541Srgrimes * version 2 for more details (a copy is included in the LICENSE file that 151541Srgrimes * accompanied this code). 161541Srgrimes * 171541Srgrimes * You should have received a copy of the GNU General Public License version 181541Srgrimes * 2 along with this work; if not, write to the Free Software Foundation, 191541Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 201541Srgrimes * 211541Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 221541Srgrimes * or visit www.oracle.com if you need additional information or have any 231541Srgrimes * questions. 241541Srgrimes */ 251541Srgrimes 261541Srgrimespackage jdk.nashorn.internal.codegen; 271541Srgrimes 281541Srgrimesimport java.io.File; 291541Srgrimesimport java.io.FileOutputStream; 301541Srgrimesimport java.io.IOException; 311541Srgrimesimport java.io.PrintWriter; 321541Srgrimesimport jdk.nashorn.internal.runtime.ECMAErrors; 331541Srgrimesimport jdk.nashorn.internal.runtime.ScriptEnvironment; 341541Srgrimesimport jdk.nashorn.internal.runtime.logging.DebugLogger; 351541Srgrimes 361541Srgrimes/** 371541Srgrimes * Class that facilitates printing bytecode and dumping it to disk. 381541Srgrimes */ 391541Srgrimespublic final class DumpBytecode { 401541Srgrimes /** 411541Srgrimes * Dump bytecode to console and potentially disk. 421541Srgrimes * @param env the script environment defining options for printing bytecode 431541Srgrimes * @param logger a logger used to write diagnostics about bytecode dumping 441541Srgrimes * @param bytecode the actual code to dump 451541Srgrimes * @param className the name of the class being dumped 461541Srgrimes */ 471541Srgrimes public static void dumpBytecode(final ScriptEnvironment env, final DebugLogger logger, final byte[] bytecode, final String className) { 481541Srgrimes File dir = null; 491541Srgrimes try { 501541Srgrimes // should could be printed to stderr for generate class? 511541Srgrimes if (env._print_code) { 521541Srgrimes 531541Srgrimes final StringBuilder sb = new StringBuilder(); 541541Srgrimes sb.append("class: ").append(className). 551541Srgrimes append('\n'). 5652150Smarcel append(ClassEmitter.disassemble(bytecode)). 571541Srgrimes append("====="); 5852150Smarcel 591541Srgrimes if (env._print_code_dir != null) { 601541Srgrimes 611541Srgrimes String name = className; 6252150Smarcel final int dollar = name.lastIndexOf('$'); 631541Srgrimes if (dollar != -1) { 641541Srgrimes name = name.substring(dollar + 1); 651541Srgrimes } 661541Srgrimes 671541Srgrimes dir = new File(env._print_code_dir); 681541Srgrimes if (!dir.exists() && !dir.mkdirs()) { 691541Srgrimes throw new IOException(dir.toString()); 701541Srgrimes } 711541Srgrimes 721541Srgrimes File file; 731541Srgrimes String fileName; 741541Srgrimes int uniqueId = 0; 751541Srgrimes do { 761541Srgrimes fileName = name + (uniqueId == 0 ? "" : "_" + uniqueId) + ".bytecode"; 771541Srgrimes file = new File(env._print_code_dir, fileName); 781541Srgrimes uniqueId++; 791541Srgrimes } while (file.exists()); 801541Srgrimes 811541Srgrimes try (final PrintWriter pw = new PrintWriter(new FileOutputStream(file))) { 821541Srgrimes pw.print(sb.toString()); 831541Srgrimes pw.flush(); 841541Srgrimes } 851541Srgrimes } else { 861541Srgrimes env.getErr().println(sb); 871541Srgrimes } 881541Srgrimes } 891541Srgrimes 901541Srgrimes 911541Srgrimes // should code be dumped to disk 921541Srgrimes if (env._dest_dir != null) { 931541Srgrimes final String fileName = className.replace('.', File.separatorChar) + ".class"; 941541Srgrimes final int index = fileName.lastIndexOf(File.separatorChar); 951541Srgrimes 961541Srgrimes if (index != -1) { 971541Srgrimes dir = new File(env._dest_dir, fileName.substring(0, index)); 981541Srgrimes } else { 991541Srgrimes dir = new File(env._dest_dir); 1001541Srgrimes } 1011541Srgrimes 1021541Srgrimes if (!dir.exists() && !dir.mkdirs()) { 1031541Srgrimes throw new IOException(dir.toString()); 1041541Srgrimes } 1051541Srgrimes final File file = new File(env._dest_dir, fileName); 1061541Srgrimes try (final FileOutputStream fos = new FileOutputStream(file)) { 1071541Srgrimes fos.write(bytecode); 1081541Srgrimes } 1091541Srgrimes logger.info("Wrote class to '" + file.getAbsolutePath() + '\''); 1101541Srgrimes } 1111541Srgrimes } catch (final IOException e) { 1121541Srgrimes logger.warning("Skipping class dump for ", 11352150Smarcel className, 1141541Srgrimes ": ", 1151541Srgrimes ECMAErrors.getMessage( 1161541Srgrimes "io.error.cant.write", 1171541Srgrimes dir.toString())); 1181541Srgrimes } 1191541Srgrimes } 1201541Srgrimes} 12152150Smarcel