Debug.java revision 1429:b4eb53200105
1/*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.nashorn.internal.runtime;
27
28import static jdk.nashorn.internal.parser.TokenType.EOF;
29
30import jdk.nashorn.api.scripting.NashornException;
31import jdk.nashorn.internal.parser.Lexer;
32import jdk.nashorn.internal.parser.Token;
33import jdk.nashorn.internal.parser.TokenStream;
34import jdk.nashorn.internal.parser.TokenType;
35
36/**
37 * Utilities for debugging Nashorn.
38 *
39 */
40public final class Debug {
41    private Debug() {
42    }
43
44    /**
45     * Return the topmost JavaScript frame in a stack trace
46     * @param t throwable that contains the stack trace
47     * @return line describing the topmost JavaScript frame
48     */
49    public static String firstJSFrame(final Throwable t) {
50        for (final StackTraceElement ste : t.getStackTrace()) {
51            if (ECMAErrors.isScriptFrame(ste)) {
52                return ste.toString();
53            }
54        }
55        return "<native code>";
56    }
57
58    /**
59     * Return the topmost JavaScript frame from the current
60     * continuation
61     * @return line describing the topmost JavaScript frame
62     */
63    public static String firstJSFrame() {
64        return firstJSFrame(new Throwable());
65    }
66
67    /**
68     * Return a formatted script stack trace string with frames information separated by '\n'.
69     * This is a shortcut for {@code NashornException.getScriptStackString(new Throwable())}.
70     * @return formatted stack trace string
71     */
72    public static String scriptStack() {
73        return NashornException.getScriptStackString(new Throwable());
74    }
75
76    /**
77     * Return the system identity hashcode for an object as a human readable
78     * string
79     *
80     * @param x object
81     * @return system identity hashcode as string
82     */
83    public static String id(final Object x) {
84        return String.format("0x%08x", System.identityHashCode(x));
85    }
86
87    /**
88     * Same as {@link Debug#id} but returns the identity hashcode as
89     * an integer
90     *
91     * @param x object
92     * @return system identity hashcode
93     */
94    public static int intId(final Object x) {
95        return System.identityHashCode(x);
96    }
97
98    /**
99     * Return a stack trace element description at a depth from where we are not
100     *
101     * @param depth depth
102     * @return stack trace element as string
103     */
104    public static String stackTraceElementAt(final int depth) {
105        return new Throwable().getStackTrace()[depth + 1].toString(); // add 1 to compensate for this method
106    }
107
108    /**
109     * Determine caller for tracing purposes.
110     * @param depth depth to trace
111     * @param count max depth
112     * @param ignores elements to ignore in stack trace
113     * @return caller
114     */
115    public static String caller(final int depth, final int count, final String... ignores) {
116        String result = "";
117        final StackTraceElement[] callers = Thread.currentThread().getStackTrace();
118
119        int c = count;
120loop:
121        for (int i = depth + 1; i < callers.length && c != 0; i++) {
122            final StackTraceElement element = callers[i];
123            final String method = element.getMethodName();
124
125            for (final String ignore : ignores) {
126                if (method.compareTo(ignore) == 0) {
127                    continue loop;
128                }
129            }
130
131            result += (method + ":" + element.getLineNumber() +
132                       "                              ").substring(0, 30);
133            c--;
134        }
135
136        return result.isEmpty() ? "<no caller>" : result;
137    }
138
139    /**
140     * Dump a token stream to stdout
141     *
142     * TODO: most other bugging goes to stderr, change?
143     *
144     * @param source the source
145     * @param lexer  the lexer
146     * @param stream the stream to dump
147     */
148    public static void dumpTokens(final Source source, final Lexer lexer, final TokenStream stream) {
149        TokenType type;
150        int k = 0;
151        do {
152            while (k > stream.last()) {
153                // Get more tokens.
154                lexer.lexify();
155            }
156
157            final long token = stream.get(k);
158            type = Token.descType(token);
159            System.out.println("" + k + ": " + Token.toString(source, token, true));
160            k++;
161        } while(type != EOF);
162    }
163
164}
165