Change dispatch to use an 8-bit main opcode instead of a 6-bit one.
This removes the need for "EXTRA" opcodes and a secondary switch
clause in the executor dispatch loop.
The new opcode layout uses four 8-bit fields: opcode, A, B, C. The
previous reg/const concept which used 9-bit B and C fields, with the
top bit reserved to denote reg vs const, is now implemented by using
four consecutive opcode slots and moving the B and C reg/const flags
into the opcode. For example:
ADD_RR reg(A) <- reg(B) + reg(C)
ADD_CR reg(A) <- const(B) + reg(C)
ADD_RC reg(A) <- reg(B) + const(C)
ADD_CC reg(A) <- const(B) + const(C)
From a footprint standpoint this allows the executor to remain roughly
the same size: four dispatched opcodes (each a function pointer in a
compiled jump table) point to the same case clause handler, which does
the reg/const decision based on an instruction bit test as before.
However, when performance is more important than footprint, each reg/const
case can be handled separately in the executor so that there's no longer
a reg/const check when the opcode executes.
Note that not all opcodes require a reg/const qualifier, so that opcode
space is effectively increased even if reg/const opcodes consume multiple
entries from the opcode table.
Other minor changes:
* Optimize behavior of several opcodes to e.g. avoid unnecessary support
for shuffling/indirection when wider register arguments are now
available.
* Remove CSPROP(I) opcode. CSPROP usually leads to three opcodes, e.g.
LDREG + LDCONST + CSPROP. Direct loads for 'base[key]' and 'base' has
the same effect with one opcode shorter bytecode and no need for a
separate CSPROP opcode.
* Remove CSREGI (indirect) opcode, simplify CSREG opcode a bit. Extend
CSREG base register argument to be wider (BC) so that shuffling is not
needed in practice.
* Remove CSVARI (indirect) opcode and handle its equivalent by using explicit
shuffling in the compiler. This removes one opcode, and indirect target
check from CSVAR.
* Remove NEWI and extend base register argument of NEW to be wider (BC) so
that shuffling is not needed in practice.
* Remove CALLI, and split CALL into CALL, TAILCALL, and EVALCALL. This
eliminates the flags field (A) and allows the base register to be wider
(BC), eliminating the need for shuffling in practice.
* Maximum argument count to constructor and ordinary calls drops from 511
to 255 with this change.
Instead of decoding a field (say A) and then computing DUK__REGP which
involves further shifting of the value, add macros such as DUK__REGP_A(ins)
which operate directly on the 32-bit 'ins' and use a single shift+mask to
get the byte offset (rather than element offset) for the target reg/const.
Technically the compiler should be able to do this, but in practice at
least gcc -O2 won't.
Also remove mostly unused old debug code.
Debug code doesn't have access to 'heap' so it cannot decode pointers.
Cause an #error for now if both debug prints and pointer compression
are enabled at the same time.
Remove duk_debug_hobject.c from make and dist. It was out of date and
not used in practice anymore.