001/* 002 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot.logging; 024 025import java.io.*; 026import java.lang.reflect.*; 027import java.util.*; 028 029import com.oracle.graal.debug.*; 030 031import jdk.internal.jvmci.hotspot.*; 032 033/** 034 * Scoped logging class used to display the call hierarchy of {@link CompilerToVM} calls. 035 */ 036public class Logger { 037 038 public static final boolean ENABLED = Boolean.valueOf(System.getProperty("jvmci.debug")); 039 private static final int SPACING = 4; 040 private static final ThreadLocal<Logger> loggerTL; 041 042 private Deque<Boolean> openStack = new LinkedList<>(); 043 private boolean open = false; 044 private int level = 0; 045 046 private static final PrintStream out; 047 048 static { 049 if (ENABLED) { 050 loggerTL = new ThreadLocal<Logger>() { 051 052 @Override 053 protected Logger initialValue() { 054 return new Logger(); 055 } 056 }; 057 } else { 058 loggerTL = null; 059 } 060 061 PrintStream ps = null; 062 String filename = System.getProperty("jvmci.info_file"); 063 if (filename != null && !"".equals(filename)) { 064 try { 065 ps = new PrintStream(new FileOutputStream(filename)); 066 } catch (FileNotFoundException e) { 067 e.printStackTrace(); 068 ps = null; 069 } 070 } 071 out = ps; 072 if (out != null) { 073 out.println("start: " + new Date()); 074 } 075 } 076 077 public static void info(String message) { 078 if (ENABLED) { 079 log(message); 080 } else { 081 TTY.println(message); 082 } 083 if (out != null) { 084 out.println(message); 085 out.flush(); 086 } 087 } 088 089 public static void log(String message) { 090 if (ENABLED) { 091 Logger logger = loggerTL.get(); 092 for (String line : message.split("\n")) { 093 if (logger.open) { 094 TTY.println("..."); 095 logger.open = false; 096 } 097 TTY.print(space(logger.level)); 098 TTY.println(line); 099 } 100 } 101 } 102 103 public static void startScope(String message) { 104 if (ENABLED) { 105 Logger logger = loggerTL.get(); 106 if (logger.open) { 107 TTY.println("..."); 108 logger.open = false; 109 } 110 TTY.print(space(logger.level)); 111 TTY.print(message); 112 logger.openStack.push(logger.open); 113 logger.open = true; 114 logger.level++; 115 } 116 } 117 118 public static void endScope(String message) { 119 if (ENABLED) { 120 Logger logger = loggerTL.get(); 121 logger.level--; 122 if (logger.open) { 123 TTY.println(message); 124 } else { 125 TTY.println(space(logger.level) + "..." + message); 126 } 127 logger.open = logger.openStack.pop(); 128 } 129 } 130 131 private static String[] spaces = new String[50]; 132 133 private static String space(int count) { 134 assert count >= 0; 135 String result; 136 if (count >= spaces.length || spaces[count] == null) { 137 StringBuilder str = new StringBuilder(); 138 for (int i = 0; i < count * SPACING; i++) { 139 str.append(' '); 140 } 141 result = str.toString(); 142 if (count < spaces.length) { 143 spaces[count] = result; 144 } 145 } else { 146 result = spaces[count]; 147 } 148 return result; 149 } 150 151 public static String pretty(Object value) { 152 if (value == null) { 153 return "null"; 154 } 155 156 Class<?> klass = value.getClass(); 157 if (value instanceof Void) { 158 return "void"; 159 } else if (value instanceof String) { 160 return "\"" + value + "\""; 161 } else if (value instanceof Method) { 162 return "method \"" + ((Method) value).getName() + "\""; 163 } else if (value instanceof Class<?>) { 164 return "class \"" + ((Class<?>) value).getSimpleName() + "\""; 165 } else if (value instanceof Integer) { 166 if ((Integer) value < 10) { 167 return value.toString(); 168 } 169 return value + " (0x" + Integer.toHexString((Integer) value) + ")"; 170 } else if (value instanceof Long) { 171 if ((Long) value < 10 && (Long) value > -10) { 172 return value + "l"; 173 } 174 return value + "l (0x" + Long.toHexString((Long) value) + "l)"; 175 } else if (klass.isArray()) { 176 StringBuilder str = new StringBuilder(); 177 int dimensions = 0; 178 while (klass.isArray()) { 179 dimensions++; 180 klass = klass.getComponentType(); 181 } 182 int length = Array.getLength(value); 183 str.append(klass.getSimpleName()).append('[').append(length).append(']'); 184 for (int i = 1; i < dimensions; i++) { 185 str.append("[]"); 186 } 187 str.append(" {"); 188 for (int i = 0; i < length; i++) { 189 str.append(pretty(Array.get(value, i))); 190 if (i < length - 1) { 191 str.append(", "); 192 } 193 } 194 str.append('}'); 195 return str.toString(); 196 } 197 198 return value.toString(); 199 } 200}