The case conversion single character test uses ~128K constants when the new
limit is ~64K (at least for the time being). Rework the test to use JSON
decoding for the large constant tables to avoid the const limit.
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.
* Plain buffers still inherit from ArrayBuffer.prototype.
* Plain buffers won't object coerce, so Object(plainBuffer) fails.
* All buffer object related methods throw an error; their function bodies
are essentially empty. Note that this includes bindings such as
String.fromBuffer(), ArrayBuffer.allocPlain(), ArrayBuffer.plainOf(),
and so on. In essence, you can index plain buffers in Ecmascript but
the buffer values must be created via the C API.
* Duktape custom bindings like Duktape.dec('hex', 'deadbeef') still work
and produce plain buffers.
Duktape internal InitJS is no longer needed, and user InitJS is not really a
full solution: it's not possible to run native initialization code which would
often be necessary for custom bindings.