-
Bug
-
Resolution: Fixed
-
P3
-
1.0
-
1.0beta
-
sparc
-
solaris_2.4
-
Not verified
From ###@###.### Wed May 24 04:08 PDT 1995
To: ###@###.###
Subject: Compiler bug report
Date: Wed, 24 May 95 07:05:04 -0400
From: Andrew Sudduth <###@###.###>
Hi,
When you folks can talk about debugger interfaces to the interpreter,
I'd like to discuss the contents of this file, but for now it is just
a compiler bug report.
The following file causes the following exception:
jupiter% javac JavaInterp.java
java.lang.NullPointerException
at java.tools.tree.BinaryExpression.eval(BinaryExpression.java)
at java.tools.tree.ConditionalExpression.inline(ConditionalExpression.java)
at java.tools.tree.ExpressionStatement.inline(ExpressionStatement.java)
at java.tools.tree.VarDeclarationStatement.inline(VarDeclarationStatement.java)
at java.tools.tree.CompoundStatement.inline(CompoundStatement.java)
at java.tools.tree.DeclarationStatement.inline(DeclarationStatement.java)
at java.tools.tree.CompoundStatement.inline(CompoundStatement.java)
at java.tools.tree.CompoundStatement.inline(CompoundStatement.java)
at java.tools.javac.SourceField.inline(SourceField.java)
at java.tools.javac.SourceField.code(SourceField.java)
andy
JavaInterp.java:
/**
* The interface description for the debugging support within the Java
* interpreter. All of the methods in this class are declared static and
* native, and are implemented in the interpreter.
* <P>
* <I>
* On Solaris, the dynamic loading conventions allow access to the main
* program's symbol table, so the appropriate stub and implementation code
* can be directly compiled into the interpreter binary. I don't that
* the Windows or Mac dynamic loading will allow this.
* </I>
*/
public class JavaInterp {
public static final int ACC_PUBLIC = 0x001;
public static final int ACC_PRIVATE = 0x002;
public static final int ACC_PROTECTED = 0x004;
public static final int ACC_STATIC = 0x008;
public static final int ACC_FINAL = 0x010;
public static final int ACC_SYNCHRONIZED = 0x020;
public static final int ACC_THREADSAFE = 0x040;
public static final int ACC_TRANSIENT = 0x080;
public static final int ACC_NATIVE = 0x100;
public static final int ACC_INTERFACE = 0x200;
public static final int ACC_ABSTRACT = 0x400;
/** test that we can call into the interpreter */
native static void hello();
/** get the current process ID */
native static int getPid();
/** access to termio et. al. to get raw input from terminal */
native public static void set_tty_raw(int fd);
/** access to termio et. al. to restore terminal */
native public static void unset_tty_raw(int fd);
/** access to blocking/nonblocking controls on file descriptor */
native public static void set_fd_blocking(int fd);
/** access to blocking/nonblocking controls on file descriptor */
native public static void set_fd_nonblocking(int fd);
/** access to the kill command <I>(could it also be System.kill() ??)</I> */
native public static void kill(int pid, int sig);
/** read, either blocking or non-blocking from the given file descriptor */
native public static int read(int fd, boolean block);
/** suspend the thread in a non-blocking read() */
native public static int read_suspend();
/** resume the suspended thread in a non-blocking read() */
native public static int read_resume();
/**
* install the bpt callback. Currently, will call JavaDebugger.bptCallback
*/
native public static int install_handler();
/** call into the older builtin debugger commands */
native public static int exec_cmdline(byte str[]);
/** return a handle to the previous frame, return 0 if at top of stack */
native public static int frame_get_prev(int frame);
/** return the lastpc executed by this frame */
native public static int frame_get_lastpc(int frame);
/** return the return point for this frame */
native public static int frame_get_returnpc(int frame);
/** return a handle to the method executing in this frame */
native public static int frame_get_method(int frame);
/** return a handle to the monitor entered by this frame */
native public static int frame_get_monitor(int frame);
native public static Class get_class_list()[];
native public static int class_get_methods(Class cl)[];
native public static int class_get_fields(Class cl)[];
native public static int class_get_access(Class cl);
native public static String pc_get_location(int pc);
native public static String pc_get_file(int pc);
native public static Class pc_get_class(int pc);
native public static int pc_get_line(int pc);
native public static int pc_get_method(int pc);
native public static int get_pc_for_class(Class cl, Method m);
native public static int get_pc_for_file(String file, int line);
native public static String method_get_name(int method);
native public static String method_get_signature(int method);
native public static int method_get_access(int method);
native public static int get_method(String name);
native public static String field_get_name(int field);
native public static String field_get_type(int field);
native public static int field_get_access(int field);
native public static int field_get_statval(int field);
native public static int get_monitor_list()[];
native public static String monitor_get_name(int monitor);
native public static Thread monitor_get_owner(int monitor);
native public static Thread monitor_get_wait(int monitor)[];
native public static Thread monitor_get_suspend(int monitor)[];
native public static Thread monitor_get_cvwait(int monitor)[];
native public static int get_regmon_list()[];
native public static String regmon_get_name(int monitor);
native public static Thread regmon_get_owner(int monitor);
native public static Thread regmon_get_wait(int monitor)[];
native public static Thread regmon_get_suspend(int monitor)[];
native public static Thread regmon_get_cvwait(int monitor)[];
native public static Thread get_thread_list()[];
/** execute the main method for the given class */
native public static void exec_class_main(Class cl, String av[]);
/** register an event handler for a given event */
native public static Handler register_event(Event event);
/** return a list of all registered Handlers */
native public static Handler list_handlers()[];
/** delete a handler */
native public static void delete_handler(Handler handler);
}
/** Provide a Java-level handle to an interpreter method */
class Method {
int cookie;
Method(int cookie) { this.cookie = cookie; }
Method(String name) { this.cookie = JavaInterp.get_method(name); }
int getCookie() { return cookie; }
String getName() { return JavaInterp.method_get_name(cookie); }
String getSignature() { return JavaInterp.method_get_signature(cookie); }
}
/** Provide a Java-level handle to an interpreter method */
class Field {
int cookie;
Field(int cookie) { this.cookie = cookie; }
int getCookie() { return cookie; }
String getName() { return JavaInterp.field_get_name(cookie); }
String getType() { return JavaInterp.field_get_type(cookie); }
}
/** Provide a Java-level handle to an interpreter monitor */
class Monitor {
int cookie;
boolean registered;
Monitor(int cookie, boolean registered) {
this.cookie = cookie;
this.registered = registered;
}
int getCookie() { return cookie; }
String getName() {
if (registered)
return JavaInterp.regmon_get_name(cookie);
else
return JavaInterp.monitor_get_name(cookie);
}
Thread getOwner() {
if (registered)
return JavaInterp.regmon_get_owner(cookie);
else
return JavaInterp.monitor_get_owner(cookie);
}
}
/** Provide a Java-level handle to an interpreter stack frame */
class Frame {
int cookie;
Frame(int cookie) { this.cookie = cookie; }
public Frame getPrev() {
return new Frame(JavaInterp.frame_get_prev(cookie));
}
public int getLastPC() { return JavaInterp.frame_get_lastpc(cookie); }
public int getReturnPC() { return JavaInterp.frame_get_returnpc(cookie);}
public Method getMethod() {
return new Method(JavaInterp.frame_get_method(cookie));
}
public Monitor getMonitor() {
return new Monitor(JavaInterp.frame_get_monitor(cookie), false);
}
}
/** Provide a container for all of the information about a location in text */
class PC {
String file;
int line;
Class cl;
Method method;
int pc;
PC(int p, String f, int l, Class c, Method m) {
pc = p;
file = f;
line = l;
cl = c;
method = m;
}
PC(int p) {
pc = p;
file = JavaInterp.pc_get_file(pc);
line = JavaInterp.pc_get_line(pc);
cl = JavaInterp.pc_get_class(pc);
method = new Method(JavaInterp.pc_get_method(pc));
}
PC(String f, int l) {
pc = JavaInterp.get_pc_for_file(f, l);
file = f;
line = l;
cl = JavaInterp.pc_get_class(pc);
method = new Method(JavaInterp.pc_get_method(pc));
}
PC(String loc) {
int i = loc.lastIndexOf('.');
String clss = (i > 0) ? loc.substring(0, i) : "";
String meth = loc.substring(i+1);
cl = JavaInterp.pc_get_class(pc);
method = new Method(meth);
pc = JavaInterp.get_pc_for_class(cl, method);
file = JavaInterp.pc_get_file(pc);
line = JavaInterp.pc_get_line(pc);
}
public int getPC() { return pc; }
public String getFile() { return file; }
public int getLine() { return line; }
public Class getCl() { return cl; }
public Method getMethod() { return method; }
public String getLoc() {
String signature, mname, cname;
if (method != null) {
signature = method.getSignature();
mname = method.getName();
} else {
mname = "???";
signature = "()";
}
if (file == null) return "";
if (cl == null)
cname = "<null>";
else
cname = cl.getName();
return file + ":" + line + " ("
+ cname + "." + mname + signature + ")";
}
}
/** This is the object that is returned to debugger Java code to represent
* the handler that was registered for a specific event. It's main purpose
* is to enable the deletion of the registered action from the interpreter.
*/
class Handler {
int id;
Event event;
Handler(int i, Event e) {
id = i;
event = e;
}
/** This method will remove the handler from the interpreter */
public void Delete() {
JavaInterp.delete_handler(this);
}
};
/** The abstract base class for describing events that can trigger actions
* Specific subclasses will have information that appropriately describes
* the cause of the event.
*/
class Event {
/** what type of event is this. If the operations on an Event are
* standard enough, this could be done by subclassing, but I think
* with the various ways of specifying location of events, a type
* discriminator is easier to implement.
*/
int type;
EventAction action;
/** type specific flags */
int flags;
static String describe_all_events()[] {
return null;
}
public Handler Register(EventAction action) {
this.action = action;
return JavaInterp.register_event(this);
}
public int getType() { return type; }
public void reset() { } /** called to reset internal state */
public abstract String getDesc();
};
class DefaultEvent extends Event {
public String getDesc() { return "DefaultEvent"; }
}
/** The event of executing a specific instruction. Used for
* breakpoints and tracing
*/
class PCEvent extends Event {
int count; /** how many times has it been hit */
int tmp_count; /** when should it be pulled (0 == infinity) */
public String getDesc() { return "PC execution event"; }
}
/** The object passed to register_event_handler must implement this
* interface. When the event is triggered, the interpreter will
* execute the run method of the registered object.
*/
interface EventAction {
/** Called by the interpreter when the currently running thread
* executes the event that this Action was registered for
*/
public void run(EventEnviron environ);
};
class EventActionStop implements EventAction {
public void run(EventEnviron e) {
// JavaDebugger.debug("DefaultEventAction::run(" + e + "): called");
// JavaDebugger.debug("DEA::run(): Thread: '" + e.getThread().getName()
// + "', PC: " + e.getPC()
// + ", Frame: " + e.getFrame()
// + ", Top: " + e.getTop()
// + ", Env: " + e.getEnv());
// JavaDebugger.bptCallback(e.getPC(), e.getEnv(),
// e.getFrame(), e.getThread());
}
}
/** Every Action is called with a handle into the current environment
* this object should provide all of the information about the
* execution environment that the Action needs. Other interfaces,
* such as threadSelf() should be avoided.
*/
interface EventEnviron {
Event getEventType();
int getPC();
int getFrame();
int getTop();
int getEnv();
Thread getThread();
// Method getMethod();
};
class BptEventEnviron implements EventEnviron {
Thread thread;
int pc;
int frame;
int top;
int env;
BptEventEnviron(Thread t, int pc, int frame, int top, int env) {
this.thread = t;
this.pc = pc;
this.frame = frame;
this.top = top;
this.env = env;
}
public Event getEventType() { return null; }
public int getPC() { return pc; }
public Thread getThread() { return thread; }
public int getFrame() { return frame; }
public int getTop() { return top; }
public int getEnv() { return env; }
}
To: ###@###.###
Subject: Compiler bug report
Date: Wed, 24 May 95 07:05:04 -0400
From: Andrew Sudduth <###@###.###>
Hi,
When you folks can talk about debugger interfaces to the interpreter,
I'd like to discuss the contents of this file, but for now it is just
a compiler bug report.
The following file causes the following exception:
jupiter% javac JavaInterp.java
java.lang.NullPointerException
at java.tools.tree.BinaryExpression.eval(BinaryExpression.java)
at java.tools.tree.ConditionalExpression.inline(ConditionalExpression.java)
at java.tools.tree.ExpressionStatement.inline(ExpressionStatement.java)
at java.tools.tree.VarDeclarationStatement.inline(VarDeclarationStatement.java)
at java.tools.tree.CompoundStatement.inline(CompoundStatement.java)
at java.tools.tree.DeclarationStatement.inline(DeclarationStatement.java)
at java.tools.tree.CompoundStatement.inline(CompoundStatement.java)
at java.tools.tree.CompoundStatement.inline(CompoundStatement.java)
at java.tools.javac.SourceField.inline(SourceField.java)
at java.tools.javac.SourceField.code(SourceField.java)
andy
JavaInterp.java:
/**
* The interface description for the debugging support within the Java
* interpreter. All of the methods in this class are declared static and
* native, and are implemented in the interpreter.
* <P>
* <I>
* On Solaris, the dynamic loading conventions allow access to the main
* program's symbol table, so the appropriate stub and implementation code
* can be directly compiled into the interpreter binary. I don't that
* the Windows or Mac dynamic loading will allow this.
* </I>
*/
public class JavaInterp {
public static final int ACC_PUBLIC = 0x001;
public static final int ACC_PRIVATE = 0x002;
public static final int ACC_PROTECTED = 0x004;
public static final int ACC_STATIC = 0x008;
public static final int ACC_FINAL = 0x010;
public static final int ACC_SYNCHRONIZED = 0x020;
public static final int ACC_THREADSAFE = 0x040;
public static final int ACC_TRANSIENT = 0x080;
public static final int ACC_NATIVE = 0x100;
public static final int ACC_INTERFACE = 0x200;
public static final int ACC_ABSTRACT = 0x400;
/** test that we can call into the interpreter */
native static void hello();
/** get the current process ID */
native static int getPid();
/** access to termio et. al. to get raw input from terminal */
native public static void set_tty_raw(int fd);
/** access to termio et. al. to restore terminal */
native public static void unset_tty_raw(int fd);
/** access to blocking/nonblocking controls on file descriptor */
native public static void set_fd_blocking(int fd);
/** access to blocking/nonblocking controls on file descriptor */
native public static void set_fd_nonblocking(int fd);
/** access to the kill command <I>(could it also be System.kill() ??)</I> */
native public static void kill(int pid, int sig);
/** read, either blocking or non-blocking from the given file descriptor */
native public static int read(int fd, boolean block);
/** suspend the thread in a non-blocking read() */
native public static int read_suspend();
/** resume the suspended thread in a non-blocking read() */
native public static int read_resume();
/**
* install the bpt callback. Currently, will call JavaDebugger.bptCallback
*/
native public static int install_handler();
/** call into the older builtin debugger commands */
native public static int exec_cmdline(byte str[]);
/** return a handle to the previous frame, return 0 if at top of stack */
native public static int frame_get_prev(int frame);
/** return the lastpc executed by this frame */
native public static int frame_get_lastpc(int frame);
/** return the return point for this frame */
native public static int frame_get_returnpc(int frame);
/** return a handle to the method executing in this frame */
native public static int frame_get_method(int frame);
/** return a handle to the monitor entered by this frame */
native public static int frame_get_monitor(int frame);
native public static Class get_class_list()[];
native public static int class_get_methods(Class cl)[];
native public static int class_get_fields(Class cl)[];
native public static int class_get_access(Class cl);
native public static String pc_get_location(int pc);
native public static String pc_get_file(int pc);
native public static Class pc_get_class(int pc);
native public static int pc_get_line(int pc);
native public static int pc_get_method(int pc);
native public static int get_pc_for_class(Class cl, Method m);
native public static int get_pc_for_file(String file, int line);
native public static String method_get_name(int method);
native public static String method_get_signature(int method);
native public static int method_get_access(int method);
native public static int get_method(String name);
native public static String field_get_name(int field);
native public static String field_get_type(int field);
native public static int field_get_access(int field);
native public static int field_get_statval(int field);
native public static int get_monitor_list()[];
native public static String monitor_get_name(int monitor);
native public static Thread monitor_get_owner(int monitor);
native public static Thread monitor_get_wait(int monitor)[];
native public static Thread monitor_get_suspend(int monitor)[];
native public static Thread monitor_get_cvwait(int monitor)[];
native public static int get_regmon_list()[];
native public static String regmon_get_name(int monitor);
native public static Thread regmon_get_owner(int monitor);
native public static Thread regmon_get_wait(int monitor)[];
native public static Thread regmon_get_suspend(int monitor)[];
native public static Thread regmon_get_cvwait(int monitor)[];
native public static Thread get_thread_list()[];
/** execute the main method for the given class */
native public static void exec_class_main(Class cl, String av[]);
/** register an event handler for a given event */
native public static Handler register_event(Event event);
/** return a list of all registered Handlers */
native public static Handler list_handlers()[];
/** delete a handler */
native public static void delete_handler(Handler handler);
}
/** Provide a Java-level handle to an interpreter method */
class Method {
int cookie;
Method(int cookie) { this.cookie = cookie; }
Method(String name) { this.cookie = JavaInterp.get_method(name); }
int getCookie() { return cookie; }
String getName() { return JavaInterp.method_get_name(cookie); }
String getSignature() { return JavaInterp.method_get_signature(cookie); }
}
/** Provide a Java-level handle to an interpreter method */
class Field {
int cookie;
Field(int cookie) { this.cookie = cookie; }
int getCookie() { return cookie; }
String getName() { return JavaInterp.field_get_name(cookie); }
String getType() { return JavaInterp.field_get_type(cookie); }
}
/** Provide a Java-level handle to an interpreter monitor */
class Monitor {
int cookie;
boolean registered;
Monitor(int cookie, boolean registered) {
this.cookie = cookie;
this.registered = registered;
}
int getCookie() { return cookie; }
String getName() {
if (registered)
return JavaInterp.regmon_get_name(cookie);
else
return JavaInterp.monitor_get_name(cookie);
}
Thread getOwner() {
if (registered)
return JavaInterp.regmon_get_owner(cookie);
else
return JavaInterp.monitor_get_owner(cookie);
}
}
/** Provide a Java-level handle to an interpreter stack frame */
class Frame {
int cookie;
Frame(int cookie) { this.cookie = cookie; }
public Frame getPrev() {
return new Frame(JavaInterp.frame_get_prev(cookie));
}
public int getLastPC() { return JavaInterp.frame_get_lastpc(cookie); }
public int getReturnPC() { return JavaInterp.frame_get_returnpc(cookie);}
public Method getMethod() {
return new Method(JavaInterp.frame_get_method(cookie));
}
public Monitor getMonitor() {
return new Monitor(JavaInterp.frame_get_monitor(cookie), false);
}
}
/** Provide a container for all of the information about a location in text */
class PC {
String file;
int line;
Class cl;
Method method;
int pc;
PC(int p, String f, int l, Class c, Method m) {
pc = p;
file = f;
line = l;
cl = c;
method = m;
}
PC(int p) {
pc = p;
file = JavaInterp.pc_get_file(pc);
line = JavaInterp.pc_get_line(pc);
cl = JavaInterp.pc_get_class(pc);
method = new Method(JavaInterp.pc_get_method(pc));
}
PC(String f, int l) {
pc = JavaInterp.get_pc_for_file(f, l);
file = f;
line = l;
cl = JavaInterp.pc_get_class(pc);
method = new Method(JavaInterp.pc_get_method(pc));
}
PC(String loc) {
int i = loc.lastIndexOf('.');
String clss = (i > 0) ? loc.substring(0, i) : "";
String meth = loc.substring(i+1);
cl = JavaInterp.pc_get_class(pc);
method = new Method(meth);
pc = JavaInterp.get_pc_for_class(cl, method);
file = JavaInterp.pc_get_file(pc);
line = JavaInterp.pc_get_line(pc);
}
public int getPC() { return pc; }
public String getFile() { return file; }
public int getLine() { return line; }
public Class getCl() { return cl; }
public Method getMethod() { return method; }
public String getLoc() {
String signature, mname, cname;
if (method != null) {
signature = method.getSignature();
mname = method.getName();
} else {
mname = "???";
signature = "()";
}
if (file == null) return "";
if (cl == null)
cname = "<null>";
else
cname = cl.getName();
return file + ":" + line + " ("
+ cname + "." + mname + signature + ")";
}
}
/** This is the object that is returned to debugger Java code to represent
* the handler that was registered for a specific event. It's main purpose
* is to enable the deletion of the registered action from the interpreter.
*/
class Handler {
int id;
Event event;
Handler(int i, Event e) {
id = i;
event = e;
}
/** This method will remove the handler from the interpreter */
public void Delete() {
JavaInterp.delete_handler(this);
}
};
/** The abstract base class for describing events that can trigger actions
* Specific subclasses will have information that appropriately describes
* the cause of the event.
*/
class Event {
/** what type of event is this. If the operations on an Event are
* standard enough, this could be done by subclassing, but I think
* with the various ways of specifying location of events, a type
* discriminator is easier to implement.
*/
int type;
EventAction action;
/** type specific flags */
int flags;
static String describe_all_events()[] {
return null;
}
public Handler Register(EventAction action) {
this.action = action;
return JavaInterp.register_event(this);
}
public int getType() { return type; }
public void reset() { } /** called to reset internal state */
public abstract String getDesc();
};
class DefaultEvent extends Event {
public String getDesc() { return "DefaultEvent"; }
}
/** The event of executing a specific instruction. Used for
* breakpoints and tracing
*/
class PCEvent extends Event {
int count; /** how many times has it been hit */
int tmp_count; /** when should it be pulled (0 == infinity) */
public String getDesc() { return "PC execution event"; }
}
/** The object passed to register_event_handler must implement this
* interface. When the event is triggered, the interpreter will
* execute the run method of the registered object.
*/
interface EventAction {
/** Called by the interpreter when the currently running thread
* executes the event that this Action was registered for
*/
public void run(EventEnviron environ);
};
class EventActionStop implements EventAction {
public void run(EventEnviron e) {
// JavaDebugger.debug("DefaultEventAction::run(" + e + "): called");
// JavaDebugger.debug("DEA::run(): Thread: '" + e.getThread().getName()
// + "', PC: " + e.getPC()
// + ", Frame: " + e.getFrame()
// + ", Top: " + e.getTop()
// + ", Env: " + e.getEnv());
// JavaDebugger.bptCallback(e.getPC(), e.getEnv(),
// e.getFrame(), e.getThread());
}
}
/** Every Action is called with a handle into the current environment
* this object should provide all of the information about the
* execution environment that the Action needs. Other interfaces,
* such as threadSelf() should be avoided.
*/
interface EventEnviron {
Event getEventType();
int getPC();
int getFrame();
int getTop();
int getEnv();
Thread getThread();
// Method getMethod();
};
class BptEventEnviron implements EventEnviron {
Thread thread;
int pc;
int frame;
int top;
int env;
BptEventEnviron(Thread t, int pc, int frame, int top, int env) {
this.thread = t;
this.pc = pc;
this.frame = frame;
this.top = top;
this.env = env;
}
public Event getEventType() { return null; }
public int getPC() { return pc; }
public Thread getThread() { return thread; }
public int getFrame() { return frame; }
public int getTop() { return top; }
public int getEnv() { return env; }
}