]> Cypherpunks repositories - gostls13.git/commitdiff
move abortChan into Thread.
authorRuss Cox <rsc@golang.org>
Wed, 2 Sep 2009 21:11:40 +0000 (14:11 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 2 Sep 2009 21:11:40 +0000 (14:11 -0700)
reuse Thread in function calls.

R=austin
DELTA=59  (8 added, 7 deleted, 44 changed)
OCL=34266
CL=34266

usr/austin/eval/abort.go
usr/austin/eval/expr.go
usr/austin/eval/expr1.go
usr/austin/eval/func.go
usr/austin/eval/gen.go
usr/austin/eval/stmt.go
usr/austin/eval/stmt_test.go

index 521e51652b540d51c06315d1c487039c335cbed3..53747f3e1b44fc95105677167d2ff052105cad82 100644 (file)
@@ -10,33 +10,29 @@ import (
        "runtime";
 )
 
-// TODO(austin) This is not thread-safe.  We could include the abort
-// channel in the Frame structure, but then the Value methods need to
-// take the Frame.  However, passing something to the Value methods
-// might be necessary to generate back traces.
-var abortChan = make(chan os.Error)
-
-// Abort aborts the current computation.  If this is called within the
-// extent of a Try call, this immediately returns to the Try with the
-// given error.  If not, then this panic's.
-func Abort(e os.Error) {
-       if abortChan == nil {
-               panic("Abort: " + e.String());
+// Abort aborts the thread's current computation,
+// causing the innermost Try to return err.
+func (t *Thread) Abort(err os.Error) {
+       if t.abort == nil {
+               panicln("abort:", err.String());
        }
-       abortChan <- e;
+       t.abort <- err;
        runtime.Goexit();
 }
 
-// Try executes a computation with the ability to Abort.
-func Try(f func()) os.Error {
-       abortChan = make(chan os.Error);
+// Try executes a computation; if the computation
+// Aborts, Try returns the error passed to abort.
+func (t *Thread) Try(f func(t *Thread)) os.Error {
+       oc := t.abort;
+       c := make(chan os.Error);
+       t.abort = c;
        go func() {
-               f();
-               abortChan <- nil;
+               f(t);
+               c <- nil;
        }();
-       res := <-abortChan;
-       abortChan = nil;
-       return res;
+       err := <-c;
+       t.abort = oc;
+       return err;
 }
 
 type DivByZeroError struct {}
index 4415c84ed28ba117a220f8fea25a2907a58a3f9c..cacfc61e12601cf2650217157b198a2d7ce14161 100644 (file)
@@ -967,7 +967,7 @@ func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
                expr.genValue(func(t *Thread) Value {
                        l, r := lf(t), rf(t);
                        if r < 0 || r >= bound {
-                               Abort(IndexError{r, bound});
+                               t.Abort(IndexError{r, bound});
                        }
                        return l.Elem(r);
                });
@@ -978,10 +978,10 @@ func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
                expr.genValue(func(t *Thread) Value {
                        l, r := lf(t), rf(t);
                        if l.Base == nil {
-                               Abort(NilPointerError{});
+                               t.Abort(NilPointerError{});
                        }
                        if r < 0 || r >= l.Len {
-                               Abort(IndexError{r, l.Len});
+                               t.Abort(IndexError{r, l.Len});
                        }
                        return l.Base.Elem(r);
                });
@@ -994,7 +994,7 @@ func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
                expr.eval = func(t *Thread) uint64 {
                        l, r := lf(t), rf(t);
                        if r < 0 || r >= int64(len(l)) {
-                               Abort(IndexError{r, int64(len(l))});
+                               t.Abort(IndexError{r, int64(len(l))});
                        }
                        return uint64(l[r]);
                }
@@ -1006,11 +1006,11 @@ func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
                        m := lf(t);
                        k := rf(t);
                        if m == nil {
-                               Abort(NilPointerError{});
+                               t.Abort(NilPointerError{});
                        }
                        e := m.Elem(k);
                        if e == nil {
-                               Abort(KeyError{k});
+                               t.Abort(KeyError{k});
                        }
                        return e;
                });
@@ -1228,13 +1228,13 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                                // XXX(Spec) What if len or cap is
                                // negative?  The runtime panics.
                                if l < 0 {
-                                       Abort(NegativeLengthError{l});
+                                       t.Abort(NegativeLengthError{l});
                                }
                                c := l;
                                if capf != nil {
                                        c = capf(t);
                                        if c < 0 {
-                                               Abort(NegativeCapacityError{c});
+                                               t.Abort(NegativeCapacityError{c});
                                        }
                                        // XXX(Spec) What happens if
                                        // len > cap?  The runtime
@@ -1293,7 +1293,7 @@ func (a *exprInfo) compileStarExpr(v *expr) *expr {
                expr.genValue(func(t *Thread) Value {
                        v := vf(t);
                        if v == nil {
-                               Abort(NilPointerError{});
+                               t.Abort(NilPointerError{});
                        }
                        return v;
                });
@@ -1863,7 +1863,7 @@ func (expr *Expr) Eval(f *Frame) (Value, os.Error) {
        }
        v := expr.e.t.Zero();
        eval := genAssign(expr.e.t, expr.e);
-       err := Try(func() {eval(v, t)});
+       err := t.Try(func(t *Thread){eval(v, t)});
        return v, err;
 }
 
index dce004f40fbab450dedcf7cbbb02d82cf5641c94..e07ce86f3919b339cd1f3087222aef6af6e05725 100644 (file)
@@ -379,11 +379,11 @@ func (a *expr) genBinOpQuo(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l / r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l / r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l / r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l / r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -392,7 +392,7 @@ func (a *expr) genBinOpQuo(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l / r }
+               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l / r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
@@ -408,11 +408,11 @@ func (a *expr) genBinOpRem(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l % r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l % r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l % r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l % r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
index d13fbbed4054d9deb16586bc264a08a4ebc10074..3bf52871dc97d7f6f3447c82110c490722bd15a4 100644 (file)
@@ -4,11 +4,14 @@
 
 package eval
 
+import "os"
+
 /*
  * Virtual machine
  */
 
 type Thread struct {
+       abort chan os.Error;
        pc uint;
        // The execution frame of this function.  This remains the
        // same throughout a function invocation.
@@ -18,13 +21,15 @@ type Thread struct {
 type code []func(*Thread)
 
 func (i code) exec(t *Thread) {
-       v := Thread{0, t.f};    // TODO: reuse t
+       opc := t.pc;
+       t.pc = 0;
        l := uint(len(i));
-       for v.pc < l {
-               pc := v.pc;
-               v.pc++;
-               i[pc](&v);
+       for t.pc < l {
+               pc := t.pc;
+               t.pc++;
+               i[pc](t);
        }
+       t.pc = opc;
 }
 
 /*
index a9d088db8c395a0c84011b5250f462348733737d..a09ecfa70aeb2554038d255388753236d6246e96 100644 (file)
@@ -91,12 +91,12 @@ var binOps = []Op{
        Op{ Name: "Sub", Expr: "l - r", ConstExpr: "l.Sub(r)", Types: numbers },
        Op{ Name: "Mul", Expr: "l * r", ConstExpr: "l.Mul(r)", Types: numbers },
        Op{ Name: "Quo",
-               Body: "if r == 0 { Abort(DivByZeroError{}) } return l / r",
+               Body: "if r == 0 { t.Abort(DivByZeroError{}) } return l / r",
                ConstExpr: "l.Quo(r)",
                Types: numbers,
        },
        Op{ Name: "Rem",
-               Body: "if r == 0 { Abort(DivByZeroError{}) } return l % r",
+               Body: "if r == 0 { t.Abort(DivByZeroError{}) } return l % r",
                ConstExpr: "l.Rem(r)",
                Types: integers,
        },
index 50a776e35e4547b7abc58337a028dea821ab0e8e..e0d6ebeb30e5240e8ba86032ef8f38622fad8666 100644 (file)
@@ -1281,7 +1281,7 @@ type Stmt struct {
 func (s *Stmt) Exec(f *Frame) os.Error {
        t := new(Thread);
        t.f = f;
-       return Try(func() {s.code.exec(t)});
+       return t.Try(func(t *Thread){s.code.exec(t)});
 }
 
 func CompileStmts(scope *Scope, stmts []ast.Stmt) (*Stmt, os.Error) {
index f701d27f7aad04094cd54cf4597822f509b12455..9a62b2e0f34c4ec5c20f0a0b9e43b2c104b342c9 100644 (file)
@@ -302,7 +302,7 @@ var stmtTests = []test {
        SErr("type T struct { x int }; type U struct { x int }; var y struct { T; U }; y.x = 42", "ambiguous.*\tT\\.x\n\tU\\.x"),
        SErr("type T struct { *T }; var x T; x.foo", "no field"),
 
-       //Val1("fib := func(int) int{return 0;}; fib = func(v int) int { if v < 2 { return 1 } return fib(v-1)+fib(v-2) }; i = fib(20)", "i", 0),
+       Val1("fib := func(int) int{return 0;}; fib = func(v int) int { if v < 2 { return 1 } return fib(v-1)+fib(v-2) }; i = fib(20)", "i", 10946),
 
        // Make slice
        Val2("x := make([]int, 2); x[0] = 42; i, i2 = x[0], x[1]", "i", 42, "i2", 0),