Exception Compiler Baojian Hua [email protected].

37
Exception Compiler Baojian Hua [email protected]

Transcript of Exception Compiler Baojian Hua [email protected].

Page 1: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Exception

CompilerBaojian Hua

[email protected]

Page 2: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Exception Exception is for error-handling

Invalid input Invalid resource state

file not exists, network error, … error execution condition

divide-by-zero, …

In real production code, error-handling code may be a large part 30%-50% or more

Page 3: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Scale SLP with Exceptionsfunc -> id(args){ s }

s -> x := e

| print (e)

| return e

| throw

| try s catch s

// Example:

try {x := 3} catch { print(5);}

try {throw; print(4);} catch 5

Page 4: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Semanticsthrow:// abort the current execution, and notify the // system some bad things happen!

try s1 catch s2:// first execute s1, // 1. if s1 runs smoothly, then // the statement finished executing; // 2. else, some exception is thrown in s1, // then run s2.// Q: what about s2 “throw”?

Page 5: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Two strategies

Setjmp/longjmp-based global “goto” C’s primitive exception (poor-man meth

od) Table-driven method

faster but more complex, use more space

Page 6: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Setjmp/longjmp#include <setjmp.h> // C standard libraryjmp_buf buf;

void f () { if (0==setjmp (buf)) g (); else;}void g () { h ();}void h () { longjmp (buf, 1);}

Page 7: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Setjmp/longjmp// What’s going on under the hood?struct context { int ebx; int edi; int esi; int ebp; int esp; int eip;};

typedef struct context jmp_buf[1];

Callee-saved registers!

Saved pc!

Page 8: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Setjmp/longjmpjmp_buf buf;

void f () { if (0==setjmp (buf)) g (); else;}void g () { h ();}void h () { longjmp (buf, 1);}

frame f

ebxediesiebpespeip

buf

frame g

Page 9: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Setjmp/longjmpjmp_buf buf;

void f () { if (0==setjmp (buf)) g (); else;}void g () { h ();}void h () { longjmp (buf, 1);}

frame f

ebxediesiebpespeip

buf

frame g

frame h

movl $1, %eax

movl buf->eip, -4(buf->esp)

// restore ebx, edi, …

Page 10: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Setjmp/longjmpjmp_buf buf;

void f () { if (0==setjmp (buf)) g (); else;}void g () { h ();}void h () { longjmp (buf, 1);}

frame f

ebxediesiebpespeip

buf

frame g

frame h

movl $1, %eax

movl buf->eip, -4(buf->esp)

// restore ebx, edi, …

Page 11: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Compiling to setjmp/longjmp Basic idea:

try s1 catch s2 ==> setjmp save the context (callee-saved registers, s2’s code la

bel, etc.) the context is also called a handler

throw ==> longjmp pop the topmost handler, restore machine states from

the handler and jump to the handler’s saved pc “Try” may nest, so all handlers should be

organized as a stack

Page 12: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Machine configuration M = (C, S, X):

C: code heap S: operand stack

pointed by “top”

as we did for the stack machine

X: exception handler stack

pointed by “xsp”

“top” points to top of some frame

“eip” points to code heap

eiptopold_xsp

eiptopold_xsp

old_top

xsp

top

old_top

Page 13: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Compiling “throw”eiptopold_xsp

eiptopold_xsp

old_top

xsp

top

old_top

gen_s (throw) =

top = xsp->top

jmp xsp->eip

// Essentially the same as

// “longjmp”.

// To simplify things, we omit

// the callee-saved regs here.

Page 14: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Compiling “try…catch…”eiptopold_xsp

eiptopold_xsp

old_topxsp

top

gen_s (try s1 catch s2) =

push a new handler

xsp->eip = .Handler

xsp->top = top

gen_s (s1)

pop a handler

jmp .End

.Handler:

pop a handler

gen_s (s2)

jmp .End

.End:

Page 15: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Compiling “try…catch…”eiptopold_xsp

eiptopold_xsp

old_top

xsp

top

gen_s (try s1 catch s2) =

push a new handler

xsp->eip = .Handler

xsp->top = top

gen_s (s1)

pop a handler

jmp .End

.Handler:

pop a handler

gen_s (s2)

jmp .End

.End:

if s1 does NOT throw

Page 16: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Compiling “try…catch…”eiptopold_xsp

eiptopold_xsp

old_top

xsp

top

gen_s (try s1 catch s2) =

push a new handler

xsp->eip = .Handler

xsp->top = top

gen_s (s1)

pop a handler

jmp .End

.Handler:

pop a handler

gen_s (s2)

jmp .End

.End:

if s1 does NOT throw

Page 17: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Compiling “try…catch…”eiptopold_xsp

old_topxsp

top

gen_s (try s1 catch s2) =

push a new handler

xsp->eip = .Handler

xsp->top = top

gen_s (s1)

pop a handler

jmp .End

.Handler:

pop a handler

gen_s (s2)

jmp .End

.End:

if s1 does NOT throw

Page 18: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Compiling “try…catch…”eiptopold_xsp

eiptopold_xsp

old_top

xsp

top

gen_s (try s1 catch s2) =

push a new handler

xsp->eip = .Handler

xsp->top = top

gen_s (s1)

pop a handler

jmp .End

.Handler:

pop a handler

gen_s (s2)

jmp .End

.End:

if s1 does throw!

gen_s (throw) =

top = xsp->top

jmp xsp->eip

Page 19: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Compiling “try…catch…”eiptopold_xsp

eiptopold_xsp

old_top

xsp

top

gen_s (try s1 catch s2) =

push a new handler

xsp->eip = .Handler

xsp->top = top

gen_s (s1)

pop a handler

jmp .End

.Handler:

pop a handler

gen_s (s2)

jmp .End

.End:

if s1 does throw!

gen_s (throw) =

top = xsp->top

jmp xsp->eip

Page 20: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

eiptopold_xsp

eiptopold_xsp

old_topxsp

top

gen_s (try {x:=3;}

catch {print(5);}) =

push a new handler

xsp->eip = .Handler

xsp->top = top

push 3

store x

pop a handler

jmp .End

.Handler:

pop a handler

push 5

call print

jmp .End

.End:

3

Example #1

Page 21: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

eiptopold_xsp

eiptopold_xsp

old_top

xsptop

gen_s (try {x:=3;}

catch {print(5);}) =

push a new handler

xsp->eip = .Handler

xsp->top = top

push 3

store x

pop a handler

jmp .End

.Handler:

pop a handler

push 5

call print

jmp .End

.End:

Example #1

Page 22: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

eiptopold_xsp

eiptopold_xsp

old_topxsp

top

gen_s (try {throw;}

catch {print(5);}) =

push a new handler

xsp->eip = .Handler

xsp->top = top

top = xsp->top

jmp xsp->eip

pop a handler

jmp .End

.Handler:

pop a handler

push 5

call print

jmp .End

.End: gen_s (throw) =

top = xsp->top

jmp xsp->eip

Example #2

Page 23: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

eiptopold_xsp

eiptopold_xsp

old_top

xsp

top

gen_s (try {throw;}

catch {print(5);}) =

push a new handler

xsp->eip = .Handler

xsp->top = top

top = xsp->top

jmp xsp->eip

pop a handler

jmp .End

.Handler:

pop a handler

push 5

call print

jmp .End

.End: gen_s (throw) =

top = xsp->top

jmp xsp->eip

Example #2

5

Page 24: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

eiptopold_xsp

eiptopold_xsp

old_topxsp

top

gen_s (try {f();}

catch {print(5);}) =

push a new handler

xsp->eip = .Handler

xsp->top = top

f()

pop a handler

jmp .End

.Handler:

pop a handler

push 5

call print

jmp .End

.End:

Example #3

f(){

g();

print(6);

}

g(){

throw;

}

old_top

Page 25: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

eiptopold_xsp

eiptopold_xsp

old_top

xsp

top

gen_s (try {f();}

catch {print(5);}) =

push a new handler

xsp->eip = .Handler

xsp->top = top

f()

pop a handler

jmp .End

.Handler:

pop a handler

push 5

call print

jmp .End

.End:

Example #3

f(){

g();

print(6);

}

g(){

throw;

}

old_top

old_top

Page 26: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

eiptopold_xsp

eiptopold_xsp

old_top

xsp

top

gen_s (try {f();}

catch {print(5);}) =

push a new handler

xsp->eip = .Handler

xsp->top = top

f()

pop a handler

jmp .End

.Handler:

pop a handler

push 5

call print

jmp .End

.End:

Example #3

f(){

g();

print(6);

}

g(){

throw;

}

old_top

old_top

5

Page 27: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

eiptopold_xsp

old_topxsp

top

// What about a wild

// “throw”?

main(){

throw;

}

gen_f (main(){throw;}) =

main:

top = xsp->top

jmp xsp->eip

// Where does xsp->eip

// point to?

// Do the assigned homework!

Example #4

Page 28: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Moral Relatively easy to implement

Many C++ compilers use this scheme, e.g. VC from MS (the so-called SEH)

the exception handler stack can be combined with operand stack (and further with the call stack)

Disadvantage: performance penalty at each “try”

even if the try body does not “throw” an exception slogan: “pay as you go”

Page 29: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Table-driven approachgen_s (try s1 catch s2) =

.L1:

gen_s (s1)

jmp .End

.L2

gen_s (s2)

jmp .End

.L3

gen_s (throw) =

search_table(eip)

From To Handler

.L1 .L2 .L2

.L2 .L3 ?

Page 30: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

old_top

top

gen_s (try {x:=3;}

catch {print(5);}) =

.L1

push 3

store x

jmp .End

.L2:

push 5

call print

jmp .End

.End:

From To Handler

.L1 .L2 .L2

.L2 .L3 ?

Example #1

Page 31: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

old_top

top

gen_s (try {throw;}

catch {print(5);}) =

.L1

search_table(eip)

jmp .End

.L2:

push 5

call print

jmp .End

.End:

From To Handler

.L1 .L2 .L2

.L2 .L3 ?

Example #2

Page 32: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

old_top

top

gen_s (try {f();}

catch {print(5);}) =

.L1

f()

jmp .End

.L2:

push 5

call print

jmp .End

.End:

From To Handler

.L1 .L2 .L2

.L2 .L3 ?

Example #3

f(){

g();

print(6);

}

g(){

throw;

}

old_top

old_top

Ooops!! Current eip is not in the table!!It’s time to unwind the stack!

Page 33: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

old_top

top

gen_s (try {f();}

catch {print(5);}) =

.L1

f()

jmp .End

.L2:

push 5

call print

jmp .End

.End:

From To Handler

.L1 .L2 .L2

.L2 .L3 ?

Example #3

f(){

g();

print(6);

}

g(){

throw;

}

old_top

old_top

Ooops!! Current eip is not in the table!!It’s time to unwind the stack!Saved eip still not in stack

Page 34: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

old_top

top

gen_s (try {f();}

catch {print(5);}) =

.L1

f()

jmp .End

.L2:

push 5

call print

jmp .End

.End:

From To Handler

.L1 .L2 .L2

.L2 .L3 ?

Example #3

f(){

g();

print(6);

}

g(){

throw;

}

old_top

Ooops!! Current eip is not in the table!!It’s time to unwind the stack!Saved eip still not in stack

Page 35: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Moral

Compilers produce an exception table, which is referred to when an exception is raised based on the value of current and saved

“eip”s Normal execution can proceed at full

speed

Page 36: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

Moral

Table-driven scheme has no cost with normal execution exceptions are exceptional, pay as you go both Sun’s HotSpot JVM and GNU g++ u

se this scheme Disadvantage:

exception table takes extra space

Page 37: Exception Compiler Baojian Hua bjhua@ustc.edu.cn.

try…finally…

A little bit tricky Sun’s old version JDK compiler uses a f

ancy but wrong technique---subroutine has been fixed in JDK version after 1.4

Read the assigned paper: The Costs and Benefits of Java Bytecode

Subroutines