Exception
This presentation is the property of its rightful owner.
Sponsored Links
1 / 37

Exception PowerPoint PPT Presentation


  • 114 Views
  • Uploaded on
  • Presentation posted in: General

Exception. Compiler Baojian Hua [email protected] 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

Download Presentation

Exception

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Exception

Exception

Compiler

Baojian Hua

[email protected]


Exception1

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


Scale slp with exceptions

Scale SLP with Exceptions

func -> 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


Semantics

Semantics

throw:

// 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”?


Two strategies

Two strategies

  • Setjmp/longjmp-based

    • global “goto”

    • C’s primitive exception (poor-man method)

  • Table-driven method

    • faster

    • but more complex, use more space


Setjmp longjmp

Setjmp/longjmp

#include <setjmp.h> // C standard library

jmp_buf buf;

void f () {

if (0==setjmp (buf))

g ();

else;

}

void g () {

h ();

}

void h () {

longjmp (buf, 1);

}


Setjmp longjmp1

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!


Setjmp longjmp2

Setjmp/longjmp

buf

jmp_buf buf;

void f () {

if (0==setjmp (buf))

g ();

else;

}

void g () {

h ();

}

void h () {

longjmp (buf, 1);

}

frame f

frame g


Setjmp longjmp3

Setjmp/longjmp

buf

jmp_buf buf;

void f () {

if (0==setjmp (buf))

g ();

else;

}

void g () {

h ();

}

void h () {

longjmp (buf, 1);

}

frame f

frame g

frame h

movl $1, %eax

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

// restore ebx, edi, …


Setjmp longjmp4

Setjmp/longjmp

buf

jmp_buf buf;

void f () {

if (0==setjmp (buf))

g ();

else;

}

void g () {

h ();

}

void h () {

longjmp (buf, 1);

}

frame f

frame g

frame h

movl $1, %eax

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

// restore ebx, edi, …


Compiling to setjmp longjmp

Compiling to setjmp/longjmp

  • Basic idea:

    • try s1 catch s2 ==> setjmp

      • save the context (callee-saved registers, s2’s code label, 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


Machine configuration

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

old_top

xsp

old_top

top


Compiling throw

Compiling “throw”

gen_s (throw) =

top = xsp->top

jmp xsp->eip

// Essentially the same as

// “longjmp”.

// To simplify things, we omit

// the callee-saved regs here.

old_top

xsp

old_top

top


Compiling try catch

Compiling “try…catch…”

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:

old_top

xsp

top


Compiling try catch1

Compiling “try…catch…”

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

old_top

top

xsp


Compiling try catch2

Compiling “try…catch…”

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

old_top

top

xsp


Compiling try catch3

Compiling “try…catch…”

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

old_top

xsp

top


Compiling try catch4

Compiling “try…catch…”

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!

old_top

top

xsp

gen_s (throw) =

top = xsp->top

jmp xsp->eip


Compiling try catch5

Compiling “try…catch…”

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!

old_top

top

xsp

gen_s (throw) =

top = xsp->top

jmp xsp->eip


Example 1

Example #1

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

old_top

xsp

top


Example 11

Example #1

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:

old_top

top

xsp


Example 2

Example #2

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:

old_top

xsp

top

gen_s (throw) =

top = xsp->top

jmp xsp->eip


Example 21

Example #2

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:

5

old_top

top

xsp

gen_s (throw) =

top = xsp->top

jmp xsp->eip


Example 3

Example #3

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:

old_top

xsp

f(){

g();

print(6);

}

g(){

throw;

}

top

old_top


Example 31

Example #3

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:

old_top

f(){

g();

print(6);

}

g(){

throw;

}

old_top

xsp

top

old_top


Example 32

Example #3

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:

5

old_top

f(){

g();

print(6);

}

g(){

throw;

}

old_top

xsp

old_top

top


Example 4

Example #4

// 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!

old_top

xsp

top


Moral

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”


Table driven approach

Table-driven approach

gen_s (try s1 catch s2) =

.L1:

gen_s (s1)

jmp .End

.L2

gen_s (s2)

jmp .End

.L3

gen_s (throw) =

search_table(eip)


Example 12

Example #1

gen_s (try {x:=3;}

catch {print(5);}) =

.L1

push 3

store x

jmp .End

.L2:

push 5

call print

jmp .End

.End:

old_top

top


Example 22

Example #2

gen_s (try {throw;}

catch {print(5);}) =

.L1

search_table(eip)

jmp .End

.L2:

push 5

call print

jmp .End

.End:

old_top

top


Example 33

Example #3

f(){

g();

print(6);

}

g(){

throw;

}

gen_s (try {f();}

catch {print(5);}) =

.L1

f()

jmp .End

.L2:

push 5

call print

jmp .End

.End:

Ooops!! Current eip is not in the table!!

old_top

It’s time to unwind the stack!

top

old_top

old_top


Example 34

Example #3

f(){

g();

print(6);

}

g(){

throw;

}

gen_s (try {f();}

catch {print(5);}) =

.L1

f()

jmp .End

.L2:

push 5

call print

jmp .End

.End:

Ooops!! Current eip is not in the table!!

old_top

It’s time to unwind the stack!

Saved eip still not in stack

old_top

old_top

top


Example 35

Example #3

f(){

g();

print(6);

}

g(){

throw;

}

gen_s (try {f();}

catch {print(5);}) =

.L1

f()

jmp .End

.L2:

push 5

call print

jmp .End

.End:

Ooops!! Current eip is not in the table!!

old_top

It’s time to unwind the stack!

Saved eip still not in stack

old_top

top


Moral1

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


Moral2

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++ use this scheme

  • Disadvantage:

    • exception table takes extra space


Try finally

try…finally…

  • A little bit tricky

    • Sun’s old version JDK compiler uses a fancy 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


  • Login