This is a subset of #21484: Type 2 CFFs never use the special subrs,
so stop doing them for type 2 at least for now.
Fixes an assert in 0000064.pdf in 0000.zip in the pdfa dataset
(a stack underflow because a subr is supposed to push a bunch of
stuff, but instead it ran one of the built-in routines instead of
the subr from the font file).
As discussed in #21484, this isn't right for type 1 CFFs either,
but just removing the code there regresses Tests/LibPDF/type1.pdf.
A slightly more involved thing is needed there; I added a FIXME
for that here.
Previously, an xref stream with a field with larger than 8 would
result in an undefined shift occurring. We now ensure that each field
width is a number and is less than or equal to 8.
The current helpers assume that a valid URL is a full URL (i.e. contains
the "://" separator between the scheme and domain). This isn't true, as
"file:" alone is parsed as a valid URL.
We must also avoid simply searching for the parsed public suffix in the
original URL string. For example, "com" is a public suffix. If we search
for that in the URL "com.com", we will think the public suffix starts at
index 0.
Instead of pushing and popping every single caller-saved registers,
we can optimize code size (and speed!) by only pushing the one register
we actually care about: RDI (since it holds our VM&).
This means that native calls may clobber every other caller-saved
register, so this is something that you have to be aware of when
emitting native calls in the JIT.
This reduces code size on Kraken/ai-astar.js by 553 KiB and makes
execution time ~6% faster as well! :^)
Instead of JIT::Assembler making the decision for everyone and forcing
out every caller-saved register in the ABI onto the stack, we now leave
that decision to users of JIT::Assembler.
Instead of emitting the "restore callee-saved registers and return"
sequence again and again, just emit it once at the end of the generated
code, and have everyone jump to it.
This is a code size optimization that saves 207KiB on Kraken/ai-astar.js
This restores the bytecode interpreter's original call exception
throwing behaviour to the JIT.
This also fixes 8 of the 10 failing test-js tests when running with the
JIT enabled.
Instead of adjusting the stack pointer before/after making native calls,
just make sure we come out of enter() with the stack pointer aligned
for making calls.
This is strictly a code size reduction. :^)
This replaces the existing sized immediate operands with a unified
immediate operand that leaves the size handling to the assembler,
instead of the user.
This has 2 benefits:
1. The user doesn't need to know which specific operand size the
instruction expects when using it
2. The assembler automatically chooses the minimal operand size that
fits the given value, resulting in smaller code size without any
additional effort from the user. While the change is small, it still
has a noticeable effect on performance (since it increases the I$ hit
rate), resulting in 5% speedup on kraken a-star.
Move TabPosition into its own file, and using it into the global
namespace the same way we do for Gfx::Orientation. This unbreaks the gn
build, and out of tree builds.
All the MOVs in the B8-BF range can use the REX.W prefix, not just B8.
Previously instructions like `48 B9... mov rcx, imm64` were interpreted
as `mov rcx, imm32` because the REX.W prefix was only applied to
`48 B8... mov rax, imm64`.
MAX_GENERATED_VALUES_PER_TEST is now the --randomized_runs flag:
$ ./Build/lagom/bin/TestGenerator --randomized_runs 1000
It's sometimes useful to try larger numbers for it instead of the
default of 100.
MAX_GEN_ATTEMPTS_PER_VALUE is now a constexpr. It's not usually needed
to tweak this value; we can recompile with a different value on the rare
occasion.
unsigned_int(0) doesn't need to draw bits from RandomnessSource.
An expression for getting INT_MAX for u32 didn't need to be
special-cased over the general formula.
This is a follow-up on a few comments
As it turns out, cxx_to_boolean() may return "bool" as other values
than just 0 or 1. This happens when the C++ compiler decides to only
update the AL portion of the RAX return value register instead of
the whole thing.
If a mov instruction is meant to be patchable, we don't want to rewrite
it as a xor, since that removes the slot where we'd patch in the right
value later.
Also, make sure to set both size bits in the REX prefix for xoring a
register with itself.
When we know the value is a positive Int32 less than 0x7fffffff,
it's safe to just add 1 to it and use that as the final result.
This avoids the work of re-adding the INT32_TAG.
Compiler now has a BasicBlockData struct for each BasicBlock. The struct
contains all the stuff that we previously stored with the
Bytecode::BasicBlock.