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}