diff options
author | Björn Gustavsson <[email protected]> | 2017-08-18 08:27:51 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2017-08-23 05:57:39 +0200 |
commit | 0848894878ef90b1c6d81e4a6e2741508d0b99f5 (patch) | |
tree | c3852f78520af8802d251fc2147a5a0b1b0c77f5 | |
parent | 8f2646de9a74d82d8527782bdb58584c60e99742 (diff) | |
download | otp-0848894878ef90b1c6d81e4a6e2741508d0b99f5.tar.gz otp-0848894878ef90b1c6d81e4a6e2741508d0b99f5.tar.bz2 otp-0848894878ef90b1c6d81e4a6e2741508d0b99f5.zip |
Pack instructions using 'q', 'c', and 's'
Update the pack engine to safely push literal operands to the pack
stack and to safely pop them back to another code address. That
will allow packing of more instructions.
-rw-r--r-- | erts/emulator/beam/beam_load.c | 39 | ||||
-rwxr-xr-x | erts/emulator/utils/beam_makeops | 12 |
2 files changed, 31 insertions, 20 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 98701db558..982f998ae3 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -2495,16 +2495,32 @@ load_code(LoaderState* stp) * The packing engine. */ if (opc[stp->specific_op].pack[0]) { - char* prog; /* Program for packing engine. */ - BeamInstr stack[8]; /* Stack. */ - BeamInstr* sp = stack; /* Points to next free position. */ - BeamInstr packed = 0; /* Accumulator for packed operations. */ + char* prog; /* Program for packing engine. */ + struct pack_stack { + BeamInstr instr; + LiteralPatch* patch; + } stack[8]; /* Stack. */ + struct pack_stack* sp = stack; /* Points to next free position. */ + BeamInstr packed = 0; /* Accumulator for packed operations. */ for (prog = opc[stp->specific_op].pack; *prog; prog++) { switch (*prog) { case 'g': /* Get instruction; push on stack. */ - *sp++ = code[--ci]; - break; + { + LiteralPatch* lp; + + ci--; + sp->instr = code[ci]; + sp->patch = 0; + for (lp = stp->literal_patches; lp && lp->pos > ci-MAX_OPARGS; lp = lp->next) { + if (lp->pos == ci) { + sp->patch = lp; + break; + } + } + sp++; + } + break; case 'i': /* Initialize packing accumulator. */ packed = code[--ci]; break; @@ -2520,10 +2536,17 @@ load_code(LoaderState* stp) break; #endif case 'p': /* Put instruction (from stack). */ - code[ci++] = *--sp; + --sp; + code[ci] = sp->instr; + if (sp->patch) { + sp->patch->pos = ci; + } + ci++; break; case 'P': /* Put packed operands. */ - *sp++ = packed; + sp->instr = packed; + sp->patch = 0; + sp++; packed = 0; break; default: diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops index 2a957d2c9d..5f8395a289 100755 --- a/erts/emulator/utils/beam_makeops +++ b/erts/emulator/utils/beam_makeops @@ -1475,18 +1475,6 @@ sub do_pack { if (defined $bits_needed{$arg}) { $packable_args++; push @bits_needed, $bits_needed{$arg}; - } elsif ($arg =~ /^[scq]/ and $packable_args > 0) { - # When packing, this operand will be picked up from the - # code array, put onto the packing stack, and later put - # back into a different location in the code. The problem - # is that if this operand is a literal, the original - # location in the code would have been remembered in a - # literal patch. For packing to work, we would have to - # adjust the position in the literal patch. For the - # moment, adding additional instructions to the packing - # engine to handle this does not seem worth it, so we will - # just turn off packing. - return ('', '', @args); } else { push @bits_needed, 0; } |