1
2
3
4 package joeq.Runtime;
5
6 import joeq.Allocator.CodeAllocator;
7 import joeq.Class.PrimordialClassLoader;
8 import joeq.Class.jq_Class;
9 import joeq.Class.jq_CompiledCode;
10 import joeq.Class.jq_Method;
11 import joeq.Class.jq_Reference;
12 import joeq.Class.jq_StaticMethod;
13 import joeq.Class.jq_TryCatch;
14 import joeq.Debugger.OnlineDebugger;
15 import joeq.Memory.CodeAddress;
16 import joeq.Memory.StackAddress;
17 import joeq.Scheduler.jq_Thread;
18 import joeq.UTF.Utf8;
19 import jwutil.strings.Strings;
20 import jwutil.util.Assert;
21
22
23
24
25
26 public abstract class ExceptionDeliverer {
27
28 public static
29
30 public static void abstractMethodError() throws AbstractMethodError {
31 SystemInterface.debugwriteln("Unimplemented abstract method!");
32 throw new AbstractMethodError();
33 }
34
35 public static void nativeMethodError() throws LinkageError {
36 SystemInterface.debugwriteln("Unimplemented native method!");
37 throw new LinkageError();
38 }
39
40 public static void athrow(Throwable k) {
41 CodeAddress ip = (CodeAddress) StackAddress.getBasePointer().offset(StackAddress.size()).peek();
42 StackAddress fp = (StackAddress) StackAddress.getBasePointer().peek();
43 ExceptionDeliverer.deliverToCurrentThread(k, ip, fp);
44 Assert.UNREACHABLE();
45 }
46
47 public static void trap_handler(int code) {
48 switch (code) {
49 case 0: throw new NullPointerException();
50 case 1: throw new ArrayIndexOutOfBoundsException();
51 case 2: throw new ArithmeticException();
52 case 3: throw new StackOverflowError();
53 default: throw new InternalError("unknown hardware exception type: "+code);
54 }
55 }
56 public static void debug_trap_handler(int code) {
57 boolean pass = OnlineDebugger.debuggerEntryPoint();
58 if (pass) {
59 SystemInterface.debugwriteln(">>> Passing on exception code "+code);
60 trap_handler(code);
61 Assert.UNREACHABLE();
62 }
63 }
64
65 public abstract void deliverToStackFrame(jq_CompiledCode cc, Throwable x, jq_TryCatch tc, CodeAddress ip, StackAddress fp);
66 public abstract Object getThisPointer(jq_CompiledCode cc, CodeAddress ip, StackAddress fp);
67
68 public static void deliverToCurrentThread(Throwable x, CodeAddress ip, StackAddress fp) {
69 jq_Thread t = Unsafe.getThreadBlock();
70 Assert._assert(t != null && !t.is_delivering_exception);
71 t.is_delivering_exception = true;
72
73 jq_Class x_type = (jq_Class) jq_Reference.getTypeOf(x);
74 if (TRACE) SystemInterface.debugwriteln("Delivering exception of type "+x_type+" to ip="+ip.stringRep()+" fp="+fp.stringRep());
75 for (;;) {
76 jq_CompiledCode cc = CodeAllocator.getCodeContaining(ip);
77 if (TRACE) SystemInterface.debugwriteln("Checking compiled code "+cc);
78 if ((cc == null) || (fp.isNull())) {
79
80 System.out.println("Exception in thread \""+Unsafe.getThreadBlock()+"\" "+x);
81 x.printStackTrace(System.out);
82 t.is_delivering_exception = false;
83 SystemInterface.die(-1);
84 Assert.UNREACHABLE();
85 return;
86 } else {
87 jq_TryCatch tc = cc.findCatchBlock(ip, x_type);
88 if (tc != null) {
89 CodeAddress address = (CodeAddress) cc.getStart().offset(tc.getHandlerEntry());
90
91
92 if (TRACE) SystemInterface.debugwriteln("Jumping to catch block at "+address.stringRep());
93 t.is_delivering_exception = false;
94 cc.deliverException(tc, fp, x);
95 Assert.UNREACHABLE();
96 return;
97 }
98 if (cc.getMethod() != null && cc.getMethod().isSynchronized()) {
99
100 Object o;
101 if (cc.getMethod().isStatic()) {
102 o = Reflection.getJDKType(cc.getMethod().getDeclaringClass());
103 if (TRACE) SystemInterface.debugwriteln("Performing monitorexit on static method "+cc.getMethod()+": object "+o);
104 } else {
105 o = cc.getThisPointer(ip, fp);
106 if (TRACE) SystemInterface.debugwriteln("Performing monitorexit on instance method "+cc.getMethod()+": object "+o.getClass()+"@"+Strings.hex(System.identityHashCode(o)));
107 }
108 Monitor.monitorexit(o);
109 }
110 ip = (CodeAddress) fp.offset(StackAddress.size()).peek();
111 fp = (StackAddress) fp.peek();
112 }
113 }
114 }
115
116 public static void printStackTrace(Object backtrace, java.io.PrintWriter pw) {
117 StackFrame sf = (StackFrame)backtrace;
118 while (sf.next != null) {
119 CodeAddress ip = sf.ip;
120 jq_CompiledCode cc = CodeAllocator.getCodeContaining(ip);
121 String s;
122 if (cc != null) {
123 jq_Method m = cc.getMethod();
124 int code_offset = ip.difference(cc.getStart());
125 if (m != null) {
126 Utf8 sourcefile = m.getDeclaringClass().getSourceFile();
127 int bc_index = cc.getBytecodeIndex(ip);
128 int line_num = m.getLineNumber(bc_index);
129 s = "\tat "+m+" ("+sourcefile+":"+line_num+" bc:"+bc_index+" off:"+Strings.hex(code_offset)+")";
130 } else {
131 s = "\tat <unknown cc> (start:"+cc.getStart().stringRep()+" off:"+Strings.hex(code_offset)+")";
132 }
133 } else {
134 s = "\tat <unknown addr> (ip:"+ip.stringRep()+")";
135 }
136 pw.println(s.toCharArray());
137 sf = sf.next;
138 }
139 }
140
141 public static void printStackTrace(Object backtrace, java.io.PrintStream pw) {
142 StackFrame sf = (StackFrame)backtrace;
143 while (sf.next != null) {
144 CodeAddress ip = sf.ip;
145 jq_CompiledCode cc = CodeAllocator.getCodeContaining(ip);
146 String s;
147 if (cc != null) {
148 jq_Method m = cc.getMethod();
149 int code_offset = ip.difference(cc.getStart());
150 if (m != null) {
151 Utf8 sourcefile = m.getDeclaringClass().getSourceFile();
152 int bc_index = cc.getBytecodeIndex(ip);
153 int line_num = m.getLineNumber(bc_index);
154 s = "\tat "+m+" ("+sourcefile+":"+line_num+" bc:"+bc_index+" off:"+Strings.hex(code_offset)+")";
155 } else {
156 s = "\tat <unknown cc> (start:"+cc.getStart().stringRep()+" off:"+Strings.hex(code_offset)+")";
157 }
158 } else {
159 s = "\tat <unknown addr> (ip:"+ip.stringRep()+")";
160 }
161 pw.println(s.toCharArray());
162 sf = sf.next;
163 }
164 }
165
166 public static void printStackTrace(Object backtrace) {
167 StackFrame sf = (StackFrame)backtrace;
168 while (sf.next != null) {
169 CodeAddress ip = sf.ip;
170 jq_CompiledCode cc = CodeAllocator.getCodeContaining(ip);
171 String s;
172 if (cc != null) {
173 jq_Method m = cc.getMethod();
174 int code_offset = ip.difference(cc.getStart());
175 if (m != null) {
176 Utf8 sourcefile = m.getDeclaringClass().getSourceFile();
177 int bc_index = cc.getBytecodeIndex(ip);
178 int line_num = m.getLineNumber(bc_index);
179 s = "\tat "+m+" ("+sourcefile+":"+line_num+" bc:"+bc_index+" off:"+Strings.hex(code_offset)+")";
180 } else {
181 s = "\tat <unknown cc> (start:"+cc.getStart().stringRep()+" off:"+Strings.hex(code_offset)+")";
182 }
183 } else {
184 s = "\tat <unknown addr> (ip:"+ip.stringRep()+")";
185 }
186 SystemInterface.debugwriteln(s);
187 sf = sf.next;
188 }
189 }
190
191 public static Object getStackTrace() {
192
193 CodeAddress ip = (CodeAddress) StackAddress.getBasePointer().offset(StackAddress.size()).peek();
194 StackAddress fp = (StackAddress) StackAddress.getBasePointer().peek();
195 StackFrame sf = new StackFrame(fp, ip);
196 sf.fillInStackTrace();
197 return sf;
198 }
199
200 public static class StackFrame {
201 protected StackAddress fp;
202 protected CodeAddress ip;
203 protected StackFrame next;
204
205 public StackFrame(StackAddress fp, CodeAddress ip) {
206 this.fp = fp; this.ip = ip;
207 }
208
209 public void fillInStackTrace() {
210 StackFrame dis = this;
211 while (!dis.fp.isNull()) {
212 CodeAddress ip2 = (CodeAddress) dis.fp.offset(StackAddress.size()).peek();
213 StackAddress fp2 = (StackAddress) dis.fp.peek();
214 dis.next = new StackFrame(fp2, ip2);
215 dis = dis.next;
216 }
217 }
218
219 public int getSize() {
220 StackFrame p = this; int s = 0;
221 while (p != null) {
222 p = p.next; ++s;
223 }
224 return s;
225 }
226 public StackFrame getNext() { return next; }
227 public StackAddress getFP() { return fp; }
228 public CodeAddress getIP() { return ip; }
229
230 public String toString() {
231 return CodeAllocator.getCodeContaining(ip)+" ip="+ip.stringRep()+" fp="+fp.stringRep();
232 }
233 }
234
235 public static final jq_Class _class;
236 public static final jq_StaticMethod _athrow;
237 public static final jq_StaticMethod _trap_handler;
238 public static final jq_StaticMethod _debug_trap_handler;
239 public static final jq_StaticMethod _abstractMethodError;
240 public static final jq_StaticMethod _nativeMethodError;
241 static {
242 _class = (jq_Class)PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Runtime/ExceptionDeliverer;");
243 _athrow = _class.getOrCreateStaticMethod("athrow", "(Ljava/lang/Throwable;)V");
244 _trap_handler = _class.getOrCreateStaticMethod("trap_handler", "(I)V");
245 _debug_trap_handler = _class.getOrCreateStaticMethod("debug_trap_handler", "(I)V");
246 _abstractMethodError = _class.getOrCreateStaticMethod("abstractMethodError", "()V");
247 _nativeMethodError = _class.getOrCreateStaticMethod("nativeMethodError", "()V");
248 }
249 }