• R/O
  • SSH

quipu: Commit

quipu mercurial repository


Commit MetaInfo

Revisiónd52ca309f785f7983ebe10a1c90ac18a23a151bc (tree)
Tiempo2017-12-15 08:13:52
AutorAgustina Arzille <avarzille@rise...>
CommiterAgustina Arzille

Log Message

Implement exceptions

Cambiar Resumen

Diferencia incremental

diff -r dd15b27cd53c -r d52ca309f785 bytecode.h
--- a/bytecode.h Wed Dec 13 03:42:20 2017 +0000
+++ b/bytecode.h Thu Dec 14 23:13:52 2017 +0000
@@ -27,7 +27,6 @@
2727 OP_LOAD0,
2828 OP_LOAD1,
2929 OP_LOADI8,
30- OP_TRY,
3130 OP_LOADA0,
3231 OP_LOADA1,
3332 OP_LOADC00,
@@ -37,7 +36,7 @@
3736 OP_KWARGS,
3837 OP_MKCONT,
3938 OP_CAPTENV,
40- OP_CAPTSETENV,
39+ OP_TRYEND,
4140 // Opcodes with long forms.
4241 OP_ARGC,
4342 OP_ARGCL,
@@ -80,7 +79,9 @@
8079 OP_MKFRAME,
8180 OP_MKFRAMEL,
8281 OP_UNWIND,
83- OP_UNWINDL
82+ OP_UNWINDL,
83+ OP_TRYBEGIN,
84+ OP_TRYBEGINL
8485 };
8586
8687 QP_DECLS_END
diff -r dd15b27cd53c -r d52ca309f785 compiler.cpp
--- a/compiler.cpp Wed Dec 13 03:42:20 2017 +0000
+++ b/compiler.cpp Thu Dec 14 23:13:52 2017 +0000
@@ -47,7 +47,8 @@
4747 static bool
4848 brform_p (object inst)
4949 {
50- return (inst >= OPX_(JMP) && inst <= OPX_(BRNEQL));
50+ return ((inst >= OPX_(JMP) && inst <= OPX_(BRNEQL)) ||
51+ inst == OPX_(TRYBEGIN) || inst == OPX_(TRYBEGINL));
5152 }
5253
5354 #if defined (QP_ARCH_I386) || defined (QP_ARCH_X8664) || \
@@ -348,6 +349,7 @@
348349 void compile_app (object env, bool tail, object expr);
349350 void compile_recur (object env, bool tail, object expr);
350351 bool compile_index_seq (object env, bool tail, object expr);
352+ void compile_try (object env, bool tail, object expr);
351353 int compile_in (object env, bool tail, object expr);
352354 void emit_optargs_init (object env, object opta, object vars, int idx);
353355
@@ -1083,6 +1085,18 @@
10831085 return (true);
10841086 }
10851087
1088+void bc_emitter::compile_try (object env, bool tail, object expr)
1089+{
1090+ int clbl = this->next_label (), end = this->next_label ();
1091+ this->emit (OPX_(TRYBEGIN), intobj (clbl));
1092+ this->compile_in (env, false, xcadr (expr));
1093+ this->emit (OPX_(JMP), intobj (end));
1094+ this->mark_label (clbl);
1095+ this->compile_in (env, false, xcar (xcddr (expr)));
1096+ this->emit (OPX_(TRYEND));
1097+ this->mark_label (end);
1098+}
1099+
10861100 static const object LOAD_OPS[] =
10871101 {
10881102 OPX_(LOADA), OPX_(LOADC), OPX_(LOADG), OPX_(LOADAP)
@@ -1297,7 +1311,10 @@
12971311 break;
12981312 }
12991313
1300- // XXX: SF_TRY here.
1314+ case SF_TRY:
1315+ this->compile_try (env, tail, expr);
1316+ break;
1317+
13011318 default:
13021319 this->compile_app (env, tail, expr);
13031320 break;
@@ -1931,8 +1948,71 @@
19311948 return (as_array(interp->retval)->data[ix]);
19321949 }
19331950
1951+// Dynamic frames.
1952+
1953+/* Inside a dynamic frame, we store some data that is used during
1954+ * runtime execution. This includes exception information,
1955+ * dynamic let bindings and dynamic locals from '%putd'. */
1956+
1957+static const int dynframe_size = 2;
1958+static const int edata_size = 3;
1959+
1960+static void
1961+dynframe_make (interpreter *interp, object& dst)
1962+{
1963+ if (array_p (dst))
1964+ return;
1965+
1966+ object prev = dst;
1967+ array *fp = as_array (alloc_array (interp, dynframe_size, NIL));
1968+ fp->data[0] = prev;
1969+ dst = fp->as_obj ();
1970+}
1971+
1972+static void
1973+edata_make (interpreter *interp, object& dst, uint32_t off)
1974+{
1975+ dynframe_make (interp, dst);
1976+ object ed = alloc_array (interp, edata_size, NIL);
1977+
1978+ as_array(ed)->data[0] = intobj (interp->sp);
1979+ as_array(ed)->data[1] = intobj (off);
1980+ as_array(ed)->data[2] = as_array(dst)->data[1];
1981+
1982+ as_array(dst)->data[1] = ed;
1983+}
1984+
1985+static void
1986+edata_pop (object& dst)
1987+{
1988+ object& tmp = as_array(dst)->data[1];
1989+ tmp = as_array(tmp)->data[edata_size - 1];
1990+}
1991+
1992+static inline bool
1993+dynframe_captured_p (object ed)
1994+{
1995+ return (intobj (1) == (int_p (ed) ? ed : as_array(ed)->data[0]));
1996+}
1997+
1998+static inline void
1999+dynframe_set_captured (object& dst)
2000+{
2001+ if (int_p (dst))
2002+ dst = intobj (1);
2003+ else
2004+ as_array(dst)->data[0] = intobj (1);
2005+}
2006+
2007+// Additional data used in function calls.
2008+struct call_data
2009+{
2010+ uint32_t ip_offset;
2011+ uint32_t topf;
2012+};
2013+
19342014 static object __attribute__((hot))
1935-apply_n (interpreter *interp, uint32_t nargs, object cont = UNBOUND)
2015+run_bytecode (interpreter *interp, uint32_t nargs, const call_data *cdp = 0)
19362016 {
19372017 uint32_t lastf, top_frame = interp->cur_frame;
19382018 uint32_t n = 0, bp, ix;
@@ -1952,26 +2032,23 @@
19522032 uint32_t op;
19532033 #endif
19542034
1955- if (cont != UNBOUND)
2035+ if (cdp != 0)
19562036 {
1957- continuation *cnp = as_continuation (cont);
1958- const array *argv = as_array (cnp->argv);
1959-
1960- interp->growstk (argv->len);
1961- copy_objs (&stack[sp], argv->data, argv->len);
1962- sp += argv->len;
1963-
1964- nargs = as_int (argv->data[argv->len - 3]);
1965- fn = argv->data[argv->len - nargs - 6];
1966- ip = as_bvector(fct_bcode (fn))->data + cnp->ip_offset;
1967- bp = sp - nargs - 5;
1968- captured = array_p (stack[bp + nargs]);
1969-
1970- // Continuations always stem from non-artificial functions.
1971- ++interp->call_depth;
1972- // Include the recently evaluated continuation in the stack.
1973- interp->push (cont);
1974- interp->cur_frame = sp - 1;
2037+ top_frame = cdp->topf;
2038+ captured = dynframe_captured_p (stack[interp->cur_frame - 1]);
2039+ nargs = as_int (stack[interp->cur_frame - 3]);
2040+ bp = interp->cur_frame - 5 - nargs;
2041+ fn = stack[bp - 1];
2042+ ip = as_bvector(fct_bcode (fn))->data + cdp->ip_offset;
2043+
2044+ for (lastf = interp->cur_frame; lastf > 0 ; )
2045+ if (!(fn & EXTRA_BIT))
2046+ break;
2047+ else
2048+ {
2049+ lastf = stack[lastf - 4];
2050+ fn = stack[lastf - 5 - as_int (stack[lastf - 3])];
2051+ }
19752052 }
19762053 else
19772054 {
@@ -1979,7 +2056,6 @@
19792056 captured = false;
19802057 fn = stack[sp - nargs - 1];
19812058 ip = as_bvector(fct_bcode (fn))->data;
1982- ++interp->call_depth;
19832059
19842060 bp = sp - nargs;
19852061 interp->push (as_fct(fn)->env);
@@ -2157,7 +2233,6 @@
21572233 OP_(RET):
21582234 interp->pop ();
21592235 sp = interp->cur_frame;
2160- --interp->call_depth;
21612236
21622237 if ((interp->cur_frame = as_int (stack[sp - 4])) == top_frame)
21632238 return (retval);
@@ -2166,8 +2241,8 @@
21662241 sp -= 5 + nargs;
21672242 nargs = as_int (stack[interp->cur_frame - 3]);
21682243
2169- bp = interp->cur_frame - 5 - nargs;
2170- captured = stack[interp->cur_frame - 1] != intobj (0);
2244+ bp = interp->cur_frame - (5 + nargs);
2245+ captured = dynframe_captured_p (stack[interp->cur_frame - 1]);
21712246 stack[sp - 1] = retval;
21722247
21732248 ip = as_bvector(fct_bcode (stack[bp - 1]))->data +
@@ -2368,7 +2443,20 @@
23682443 loadc_setc_helper(interp, ip, bp, nargs) = stack[sp - 1];
23692444 NEXT_OP;
23702445
2371- // XXX: try-catch here.
2446+ OP_(TRYBEGIN):
2447+ OP_(TRYBEGINL):
2448+ if (*(ip - 1) == OP_TRYBEGIN)
2449+ sx = get16 (ip) - sizeof (int16_t), ip += sizeof (int16_t);
2450+ else
2451+ sx = fetch32 (ip) - sizeof (int32_t);
2452+
2453+ sx = (ip - as_bvector(fct_bcode (stack[bp - 1]))->data) + sx;
2454+ edata_make (interp, stack[interp->cur_frame - 1], sx);
2455+ NEXT_OP;
2456+
2457+ OP_(TRYEND):
2458+ edata_pop (stack[interp->cur_frame - 1]);
2459+ NEXT_OP;
23722460
23732461 OP_(OPTARGS):
23742462 ix = fetch32 (ip);
@@ -2471,12 +2559,11 @@
24712559
24722560 stack[sp - n - 1] = fn = stack[bp - 1] | EXTRA_BIT;
24732561 ix = bp, bp = sp - n;
2474- captured = false;
24752562 interp->push (stack[ix]);
24762563 interp->push (intobj (interp->cur_frame));
24772564 interp->push (intobj (n));
24782565 interp->push (intobj (sx)); // Actually the SP.
2479- interp->push (intobj (0)); // captured?
2566+ interp->push (stack[interp->cur_frame - 1]);
24802567 interp->cur_frame = sp;
24812568 nargs = n;
24822569 NEXT_OP;
@@ -2496,7 +2583,7 @@
24962583 lastf = interp->cur_frame;
24972584 nargs = as_int (stack[interp->cur_frame - 3]);
24982585 bp = sp - 5 - nargs;
2499- captured = stack[interp->cur_frame - 1] != intobj (0);
2586+ captured = dynframe_captured_p (stack[interp->cur_frame - 1]);
25002587 interp->push (retval);
25012588 NEXT_OP;
25022589
@@ -2505,9 +2592,9 @@
25052592 {
25062593 alloc_array (interp, nargs + 1, UNBOUND);
25072594 copy_objs (as_array(interp->alval)->data, &stack[bp], nargs + 1);
2595+ stack[bp] = interp->alval;
25082596 captured = true;
2509- stack[interp->cur_frame - 1] = intobj (1);
2510- stack[bp] = interp->alval;
2597+ dynframe_set_captured (stack[interp->cur_frame - 1]);
25112598 }
25122599
25132600 {
@@ -2532,6 +2619,59 @@
25322619 #endif
25332620 }
25342621
2622+// Test if we can handle an exception in a particular stack frame.
2623+static bool
2624+eh_inframe (interpreter *interp, uint32_t frame)
2625+{
2626+ object ed = interp->stack[frame - 1];
2627+ if (!array_p (ed) || !array_p (as_array(ed)->data[1]))
2628+ return (false);
2629+
2630+ array *edp = as_array (ed);
2631+ interp->aux = edp->data[1];
2632+ edp->data[1] = as_array(interp->aux)->data[edata_size - 1];
2633+ return (true);
2634+}
2635+
2636+static bool
2637+exc_handled (interpreter *interp)
2638+{
2639+ for (uint32_t cf = interp->cur_frame; cf > 0;
2640+ cf = as_int (interp->stack[cf - 4]))
2641+ if (eh_inframe (interp, cf))
2642+ {
2643+ interp->cur_frame = cf;
2644+ return (true);
2645+ }
2646+
2647+ return (false);
2648+}
2649+
2650+static object
2651+apply_n (interpreter *interp, uint32_t nargs)
2652+{
2653+ call_data cd, *cdp = 0;
2654+ cd.topf = interp->cur_frame;
2655+
2656+ while (true)
2657+ {
2658+ try
2659+ {
2660+ return (run_bytecode (interp, nargs, cdp));
2661+ }
2662+ catch (object obj)
2663+ {
2664+ if (!exc_handled (interp))
2665+ throw;
2666+
2667+ const array *edp = as_array (interp->aux);
2668+ interp->sp = as_int (edp->data[0]);
2669+ cd.ip_offset = as_int (edp->data[1]);
2670+ cdp = &cd;
2671+ }
2672+ }
2673+}
2674+
25352675 object call_fct (interpreter *interp, object fct, uint32_t n, ...)
25362676 {
25372677 uint32_t saved_sp = interp->sp;
@@ -2630,14 +2770,6 @@
26302770 return (interp->retval);
26312771 }
26322772
2633-object call_continuation (interpreter *interp, object cont)
2634-{
2635- uint32_t sp = interp->sp;
2636- apply_n (interp, 0, cont);
2637- interp->sp = sp;
2638- return (interp->retval);
2639-}
2640-
26412773 static object
26422774 lookup_ctv (object env, object sym)
26432775 {
@@ -2760,25 +2892,26 @@
27602892 }
27612893
27622894 // Disassembly.
2763-static const char OPC_NAMES[] =
2895+static const char OPC_NAMES[] =
27642896 "nop\0dup\0pop\0ret\0is\0not\0cons\0list\0car\0cdr\0cadr\0nputcar\0nputcdr\0"
2765- "apply\0tapply\0loadt\0loadnil\0load0\0load1\0loadi8\0try\0loada0\0loada1\0"
2766- "loadc00\0loadc01\0optargs\0brbound\0kwargs\0mkcont\0captenv\0captsetenv\0"
2767- "argc\0argc.l\0vargc\0vargc.l\0jmp\0jmp.l\0brt\0brt.l\0brn\0brn.l\0brneq\0"
2897+ "apply\0tapply\0loadt\0loadnil\0load0\0load1\0loadi8\0loada0\0loada1\0"
2898+ "loadc00\0loadc01\0optargs\0brbound\0kwargs\0mkcont\0captenv\0tryend\0argc\0"
2899+ "argc.l\0vargc\0vargc.l\0jmp\0jmp.l\0brt\0brt.l\0brn\0brn.l\0brneq\0"
27682900 "brneq.l\0tcall\0tcall.l\0call\0call.l\0setc\0setc.l\0seta\0seta.l\0setap\0"
27692901 "setap.l\0setg\0setg.l\0loadc\0loadc.l\0loada\0loada.l\0loadap\0loadap.l\0"
27702902 "loadg\0loadg.l\0loadv\0loadv.l\0recur\0recur.l\0trecur\0trecur.l\0mkframe\0"
2771- "mkframe.l\0unwind\0unwind.l\0";
2772-
2773-static const uint16_t OPC_NAMESLEN[] =
2903+ "mkframe.l\0unwind\0unwind.l\0trybegin\0trybegin.l\0";
2904+
2905+static const uint16_t OPC_NAMESLEN[] =
27742906 {
2775- 0, 4, 8, 12, 16, 19, 23, 28, 33, 37, 41, 46, 54, 62, 68, 75, 81, 89, 95,
2776- 101, 108, 112, 119, 126, 134, 142, 150, 158, 165, 172, 180, 191, 196, 203,
2777- 209, 217, 221, 227, 231, 237, 241, 247, 253, 261, 267, 275, 280, 287, 292,
2778- 299, 304, 311, 317, 325, 330, 337, 343, 351, 357, 365, 372, 381, 387, 395,
2779- 401, 409, 415, 423, 430, 439, 447, 457
2907+ 0, 4, 8, 12, 16, 19, 23, 28, 33, 37, 41, 46, 54, 62, 68, 75, 81, 89,
2908+ 95, 101, 108, 115, 122, 130, 138, 146, 154, 161, 168, 176, 183, 188, 195,
2909+ 201, 209, 213, 219, 223, 229, 233, 239, 245, 253, 259, 267, 272, 279, 284,
2910+ 291, 296, 303, 309, 317, 322, 329, 335, 343, 349, 357, 364, 373, 379, 387,
2911+ 393, 401, 407, 415, 422, 431, 439, 449, 456, 465, 474
27802912 };
27812913
2914+
27822915 static void disasm_aux (interpreter *, object, stream *, int);
27832916
27842917 static void
@@ -2796,6 +2929,25 @@
27962929 }
27972930 }
27982931
2932+static int
2933+endoftry_p (std::vector<int>& offs, const unsigned char* code, int ix)
2934+{
2935+ if (offs.empty () || (code[ix] != OP_JMP && code[ix] != OP_JMPL))
2936+ return (-1);
2937+
2938+ int r;
2939+
2940+ if (code[ix] == OP_JMP && ix + 3 == offs.back ())
2941+ r = 3;
2942+ else if (code[ix] == OP_JMPL && ix + 5 == offs.back ())
2943+ r = 5;
2944+ else
2945+ return (-1);
2946+
2947+ offs.pop_back ();
2948+ return (r);
2949+}
2950+
27992951 static void
28002952 disasm_aux (interpreter *interp, object fn, stream *strm, int lv)
28012953 {
@@ -2815,13 +2967,24 @@
28152967 const array *vals = as_array (fct_vals (fn));
28162968 int sx, width = bc->nbytes < 0xff ? 2 :
28172969 bc->nbytes < 0xffff ? 4 : 8;
2970+ std::vector<int> troff;
28182971
28192972 for (int i = 0; i < bc->nbytes; )
28202973 {
2821- if (lv > 0)
2822- strm->nputb (interp, lv * 2, ' ');
2823-
28242974 char buf[64];
2975+ int tr = endoftry_p (troff, code, i);
2976+ if (tr > 0)
2977+ {
2978+ strm->nputb (interp, (lv - 1) * 2, ' ');
2979+ strm->write (interp, buf, sprintf (buf, "%0*x: catch\n", width, i));
2980+ i += tr;
2981+ continue;
2982+ }
2983+ else if (code[i] == OP_TRYEND)
2984+ --lv;
2985+
2986+ strm->nputb (interp, lv * 2, ' ');
2987+
28252988 strm->write (interp, buf, sprintf (buf, "%0*x: %s",
28262989 width, i, OPC_NAMES + OPC_NAMESLEN[code[i]]));
28272990
@@ -2898,6 +3061,16 @@
28983061 i += lform_p (code[i - 1]) ? sizeof (int32_t) : sizeof (int16_t);
28993062 break;
29003063
3064+ case OP_TRYBEGIN: case OP_TRYBEGINL:
3065+ if (lform_p (code[i - 1]))
3066+ sx = get32 (&code[i]) + i, i += sizeof (int32_t);
3067+ else
3068+ sx = get16 (&code[i]) + i, i += sizeof (int16_t);
3069+
3070+ troff.push_back (sx);
3071+ ++lv;
3072+ break;
3073+
29013074 default:
29023075 break;
29033076 }
diff -r dd15b27cd53c -r d52ca309f785 stream.cpp
--- a/stream.cpp Wed Dec 13 03:42:20 2017 +0000
+++ b/stream.cpp Thu Dec 14 23:13:52 2017 +0000
@@ -239,7 +239,9 @@
239239
240240 int stream::nputb (interpreter *interp, unsigned int n, int byte)
241241 {
242- if (this->need_rflush () && !this->rflush (interp))
242+ if (n == 0)
243+ return (0);
244+ else if (this->need_rflush () && !this->rflush (interp))
243245 return (-1);
244246
245247 int off = n, cnt = min (this->wrbuf.left (), off);
Show on old repository browser