diff options
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r-- | erts/emulator/beam/beam_debug.c | 44 | ||||
-rw-r--r-- | erts/emulator/beam/beam_load.c | 68 | ||||
-rw-r--r-- | erts/emulator/beam/select_instrs.tab | 6 |
3 files changed, 100 insertions, 18 deletions
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c index 39e96126bf..9ba65e2464 100644 --- a/erts/emulator/beam/beam_debug.c +++ b/erts/emulator/beam/beam_debug.c @@ -54,6 +54,7 @@ void dbg_where(BeamInstr* addr, Eterm x0, Eterm* reg); static int print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr); static void print_bif_name(fmtfn_t to, void* to_arg, BifFunction bif); static BeamInstr* f_to_addr(BeamInstr* base, int op, BeamInstr* ap); +static BeamInstr* f_to_addr_packed(BeamInstr* base, int op, Sint32* ap); BIF_RETTYPE erts_debug_same_2(BIF_ALIST_2) @@ -634,6 +635,7 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr) { int n = ap[-1]; int ix = n; + Sint32* jump_tab = (Sint32 *)(ap + n); while (ix--) { erts_print(to, to_arg, "%T ", (Eterm) ap[0]); @@ -642,11 +644,11 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr) } ix = n; while (ix--) { - BeamInstr* target = f_to_addr(addr, op, ap); + BeamInstr* target = f_to_addr_packed(addr, op, jump_tab); erts_print(to, to_arg, "f(" HEXF ") ", target); - ap++; - size++; + jump_tab++; } + size += (n+1) / 2; } break; case op_i_select_val_bins_xfI: @@ -668,6 +670,7 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr) { int n = ap[-1]; int ix = n - 1; /* without sentinel */ + Sint32* jump_tab = (Sint32 *)(ap + n); while (ix--) { Uint arity = arityval(ap[0]); @@ -681,34 +684,38 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr) size++; ix = n; while (ix--) { - BeamInstr* target = f_to_addr(addr, op, ap); + BeamInstr* target = f_to_addr_packed(addr, op, jump_tab); erts_print(to, to_arg, "f(" HEXF ") ", target); - ap++; - size++; + jump_tab++; } + size += (n+1) / 2; } break; case op_i_jump_on_val_xfIW: case op_i_jump_on_val_yfIW: { - int n; - for (n = ap[-2]; n > 0; n--) { - BeamInstr* target = f_to_addr(addr, op, ap); + int n = ap[-2]; + Sint32* jump_tab = (Sint32 *) ap; + + size += (n+1) / 2; + while (n-- > 0) { + BeamInstr* target = f_to_addr_packed(addr, op, jump_tab); erts_print(to, to_arg, "f(" HEXF ") ", target); - ap++; - size++; + jump_tab++; } } break; case op_i_jump_on_val_zero_xfI: case op_i_jump_on_val_zero_yfI: { - int n; - for (n = ap[-1]; n > 0; n--) { - BeamInstr* target = f_to_addr(addr, op, ap); + int n = ap[-1]; + Sint32* jump_tab = (Sint32 *) ap; + + size += (n+1) / 2; + while (n-- > 0) { + BeamInstr* target = f_to_addr_packed(addr, op, jump_tab); erts_print(to, to_arg, "f(" HEXF ") ", target); - ap++; - size++; + jump_tab++; } } break; @@ -810,6 +817,11 @@ static BeamInstr* f_to_addr(BeamInstr* base, int op, BeamInstr* ap) return base - 1 + opc[op].adjust + (Sint32) *ap; } +static BeamInstr* f_to_addr_packed(BeamInstr* base, int op, Sint32* ap) +{ + return base - 1 + opc[op].adjust + *ap; +} + /* * Dirty BIF testing. diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 2acf3a2c1c..9bb5866cb3 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -1976,6 +1976,9 @@ load_code(LoaderState* stp) GenOp** last_op_next = NULL; int arity; int retval = 1; +#if defined(BEAM_WIDE_SHIFT) + int num_trailing_f; /* Number of extra 'f' arguments in a list */ +#endif /* * The size of the loaded func_info instruction is needed @@ -2661,7 +2664,17 @@ load_code(LoaderState* stp) * Load any list arguments using the primitive tags. */ +#if defined(BEAM_WIDE_SHIFT) + num_trailing_f = 0; +#endif for ( ; arg < tmp_op->arity; arg++) { +#if defined(BEAM_WIDE_SHIFT) + if (tmp_op->a[arg].type == TAG_f) { + num_trailing_f++; + } else { + num_trailing_f = 0; + } +#endif switch (tmp_op->a[arg].type) { case TAG_i: CodeNeed(1); @@ -2701,6 +2714,61 @@ load_code(LoaderState* stp) } } + /* + * If all the extra arguments were 'f' operands, + * and the wordsize is 64 bits, pack two 'f' operands + * into each word. + */ + +#if defined(BEAM_WIDE_SHIFT) + if (num_trailing_f >= 1) { + Uint src_index = ci - num_trailing_f; + Uint src_limit = ci; + Uint dst_limit = src_index + (num_trailing_f+1)/2; + + ci = src_index; + while (ci < dst_limit) { + Uint w[2]; + BeamInstr packed = 0; + int wi; + + w[0] = code[src_index]; + if (src_index+1 < src_limit) { + w[1] = code[src_index+1]; + } else { + w[1] = 0; + } + for (wi = 0; wi < 2; wi++) { + Uint lbl = w[wi]; + LabelPatch* lp = stp->labels[lbl].patches; + int num_patches = stp->labels[lbl].num_patches; + +#if defined(WORDS_BIGENDIAN) + packed <<= BEAM_WIDE_SHIFT; + packed |= lbl & BEAM_WIDE_MASK; +#else + packed >>= BEAM_WIDE_SHIFT; + packed |= lbl << BEAM_WIDE_SHIFT; +#endif + while (num_patches-- > 0) { + if (lp->pos == src_index + wi) { + lp->pos = ci; +#if defined(WORDS_BIGENDIAN) + lp->packed = 2 - wi; +#else + lp->packed = wi + 1; +#endif + break; + } + lp++; + } + } + code[ci++] = packed; + src_index += 2; + } + } +#endif + /* * Handle a few special cases. */ diff --git a/erts/emulator/beam/select_instrs.tab b/erts/emulator/beam/select_instrs.tab index da6b7dbe62..6b59f02925 100644 --- a/erts/emulator/beam/select_instrs.tab +++ b/erts/emulator/beam/select_instrs.tab @@ -150,7 +150,8 @@ select_val_lin.execute(N) { } if (vs[ix] == select_val) { - Eterm offset = *($NEXT_INSTRUCTION + $N + ix); + Sint32* jump_tab = (Sint32 *) ($NEXT_INSTRUCTION + $N); + Eterm offset = jump_tab[ix]; $JUMP(offset); } else { $JUMP(*select_fail); @@ -161,7 +162,8 @@ JUMP_ON_VAL(Fail, Index, N, Base) { if (is_small($Index)) { $Index = (Uint) (signed_val($Index) - $Base); if ($Index < $N) { - $JUMP((($NEXT_INSTRUCTION)[$Index])); + Sint32* jump_tab = (Sint32 *) ($NEXT_INSTRUCTION); + $JUMP(jump_tab[$Index]); } } $FAIL($Fail); |