mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-02 12:27:21 +02:00
Merge pull request #21048 from Snuffleupagus/buildPostScriptJsFunction-forceInterpreter
Shorten the `src/core/postscript/` code a tiny bit
This commit is contained in:
commit
dd8f0a327f
@ -544,7 +544,7 @@ class PSStackToTree {
|
|||||||
|
|
||||||
static #init() {
|
static #init() {
|
||||||
// Binary operator ids — used by _evalOp.
|
// Binary operator ids — used by _evalOp.
|
||||||
PSStackToTree.#binaryOps = new Set([
|
this.#binaryOps = new Set([
|
||||||
TOKEN.add,
|
TOKEN.add,
|
||||||
TOKEN.sub,
|
TOKEN.sub,
|
||||||
TOKEN.mul,
|
TOKEN.mul,
|
||||||
@ -565,7 +565,7 @@ class PSStackToTree {
|
|||||||
TOKEN.bitshift,
|
TOKEN.bitshift,
|
||||||
]);
|
]);
|
||||||
// Unary operator ids.
|
// Unary operator ids.
|
||||||
PSStackToTree.#unaryOps = new Set([
|
this.#unaryOps = new Set([
|
||||||
TOKEN.abs,
|
TOKEN.abs,
|
||||||
TOKEN.neg,
|
TOKEN.neg,
|
||||||
TOKEN.ceiling,
|
TOKEN.ceiling,
|
||||||
@ -583,7 +583,7 @@ class PSStackToTree {
|
|||||||
]);
|
]);
|
||||||
// Unary operators where f(f(x)) = f(x) — applying them twice is the same
|
// Unary operators where f(f(x)) = f(x) — applying them twice is the same
|
||||||
// as applying them once.
|
// as applying them once.
|
||||||
PSStackToTree.#idempotentUnary = new Set([
|
this.#idempotentUnary = new Set([
|
||||||
TOKEN.abs,
|
TOKEN.abs,
|
||||||
TOKEN.ceiling,
|
TOKEN.ceiling,
|
||||||
TOKEN.cvi,
|
TOKEN.cvi,
|
||||||
@ -594,7 +594,7 @@ class PSStackToTree {
|
|||||||
]);
|
]);
|
||||||
// Maps each comparison operator to its logical negation.
|
// Maps each comparison operator to its logical negation.
|
||||||
// Used to simplify not(comparison) → negated-comparison.
|
// Used to simplify not(comparison) → negated-comparison.
|
||||||
PSStackToTree.#negatedComparison = new Map([
|
this.#negatedComparison = new Map([
|
||||||
[TOKEN.eq, TOKEN.ne],
|
[TOKEN.eq, TOKEN.ne],
|
||||||
[TOKEN.ne, TOKEN.eq],
|
[TOKEN.ne, TOKEN.eq],
|
||||||
[TOKEN.lt, TOKEN.ge],
|
[TOKEN.lt, TOKEN.ge],
|
||||||
|
|||||||
@ -327,8 +327,8 @@ class PsJsCompiler {
|
|||||||
let ip = 0,
|
let ip = 0,
|
||||||
sp = 0;
|
sp = 0;
|
||||||
const n = ir.length;
|
const n = ir.length;
|
||||||
const stack = PsJsCompiler.#stack;
|
const stack = this.#stack;
|
||||||
const tmp = PsJsCompiler.#tmp;
|
const tmp = this.#tmp;
|
||||||
|
|
||||||
while (ip < n) {
|
while (ip < n) {
|
||||||
switch (ir[ip++] | 0) {
|
switch (ir[ip++] | 0) {
|
||||||
@ -795,9 +795,15 @@ class PSStackBasedInterpreter {
|
|||||||
* @param {number[]} range – flat [min0,max0, …]
|
* @param {number[]} range – flat [min0,max0, …]
|
||||||
* @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
|
* @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
|
||||||
*/
|
*/
|
||||||
function buildPostScriptJsFunction(source, domain, range) {
|
function buildPostScriptJsFunction(
|
||||||
|
source,
|
||||||
|
domain,
|
||||||
|
range,
|
||||||
|
forceInterpreter = false
|
||||||
|
) {
|
||||||
const program = parsePostScriptFunction(source);
|
const program = parsePostScriptFunction(source);
|
||||||
const ir = new PsJsCompiler(domain, range).compile(program);
|
const ir =
|
||||||
|
!forceInterpreter && new PsJsCompiler(domain, range).compile(program);
|
||||||
if (ir) {
|
if (ir) {
|
||||||
return (src, srcOffset, dest, destOffset) => {
|
return (src, srcOffset, dest, destOffset) => {
|
||||||
PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
|
PsJsCompiler.execute(ir, src, srcOffset, dest, destOffset);
|
||||||
@ -807,14 +813,4 @@ function buildPostScriptJsFunction(source, domain, range) {
|
|||||||
return PSStackBasedInterpreter.build(program, domain, range);
|
return PSStackBasedInterpreter.build(program, domain, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export { buildPostScriptJsFunction };
|
||||||
* @param {import("./ast.js").PsProgram} program
|
|
||||||
* @param {number[]} domain – flat [min0,max0, …]
|
|
||||||
* @param {number[]} range – flat [min0,max0, …]
|
|
||||||
* @returns {Function} – `(src, srcOffset, dest, destOffset) => void`
|
|
||||||
*/
|
|
||||||
function buildPostScriptProgramFunction(program, domain, range) {
|
|
||||||
return PSStackBasedInterpreter.build(program, domain, range);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { buildPostScriptJsFunction, buildPostScriptProgramFunction };
|
|
||||||
|
|||||||
@ -120,8 +120,8 @@ class Lexer {
|
|||||||
operatorSingletons[name] = token;
|
operatorSingletons[name] = token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Lexer.#singletons = singletons;
|
this.#singletons = singletons;
|
||||||
Lexer.#operatorSingletons = operatorSingletons;
|
this.#operatorSingletons = operatorSingletons;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(data) {
|
constructor(data) {
|
||||||
|
|||||||
@ -170,7 +170,7 @@ class PsWasmCompiler {
|
|||||||
|
|
||||||
static #init() {
|
static #init() {
|
||||||
// TOKEN comparison ids → Wasm f64 comparison opcodes (leave i32 on stack).
|
// TOKEN comparison ids → Wasm f64 comparison opcodes (leave i32 on stack).
|
||||||
PsWasmCompiler.#comparisonToOp = new Map([
|
this.#comparisonToOp = new Map([
|
||||||
[TOKEN.eq, OP.f64_eq],
|
[TOKEN.eq, OP.f64_eq],
|
||||||
[TOKEN.ne, OP.f64_ne],
|
[TOKEN.ne, OP.f64_ne],
|
||||||
[TOKEN.lt, OP.f64_lt],
|
[TOKEN.lt, OP.f64_lt],
|
||||||
@ -179,18 +179,20 @@ class PsWasmCompiler {
|
|||||||
[TOKEN.ge, OP.f64_ge],
|
[TOKEN.ge, OP.f64_ge],
|
||||||
]);
|
]);
|
||||||
// Index of each import function by name.
|
// Index of each import function by name.
|
||||||
PsWasmCompiler.#importIdx = Object.create(null);
|
this.#importIdx = Object.create(null);
|
||||||
for (let i = 0; i < MATH_IMPORTS.length; i++) {
|
for (let i = 0; i < MATH_IMPORTS.length; i++) {
|
||||||
PsWasmCompiler.#importIdx[MATH_IMPORTS[i][0]] = i;
|
this.#importIdx[MATH_IMPORTS[i][0]] = i;
|
||||||
}
|
}
|
||||||
PsWasmCompiler.#degToRad = Math.PI / 180;
|
this.#degToRad = Math.PI / 180;
|
||||||
PsWasmCompiler.#radToDeg = 180 / Math.PI;
|
this.#radToDeg = 180 / Math.PI;
|
||||||
// Import type entries are identical on every compilation — compute once.
|
// Import type entries are identical on every compilation — compute once.
|
||||||
PsWasmCompiler.#importTypeEntries = MATH_IMPORTS.map(
|
this.#importTypeEntries = MATH_IMPORTS.map(([, , , params, results]) => [
|
||||||
([, , , params, results]) => [FUNC_TYPE, ...vec(params), ...vec(results)]
|
FUNC_TYPE,
|
||||||
);
|
...vec(params),
|
||||||
|
...vec(results),
|
||||||
|
]);
|
||||||
// Static Wasm sections that never change between compilations.
|
// Static Wasm sections that never change between compilations.
|
||||||
PsWasmCompiler.#importSection = new Uint8Array(
|
this.#importSection = new Uint8Array(
|
||||||
section(
|
section(
|
||||||
SECTION.import,
|
SECTION.import,
|
||||||
vec(
|
vec(
|
||||||
@ -204,16 +206,16 @@ class PsWasmCompiler {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
// One function, type index 0.
|
// One function, type index 0.
|
||||||
PsWasmCompiler.#functionSection = new Uint8Array(
|
this.#functionSection = new Uint8Array(
|
||||||
section(SECTION.function, vec([[0]]))
|
section(SECTION.function, vec([[0]]))
|
||||||
);
|
);
|
||||||
// Min 1 page (64 KiB), no max.
|
// Min 1 page (64 KiB), no max.
|
||||||
// https://webassembly.github.io/spec/core/binary/types.html#binary-limits
|
// https://webassembly.github.io/spec/core/binary/types.html#binary-limits
|
||||||
PsWasmCompiler.#memorySection = new Uint8Array(
|
this.#memorySection = new Uint8Array(
|
||||||
section(SECTION.memory, vec([[0x00, 0x01]]))
|
section(SECTION.memory, vec([[0x00, 0x01]]))
|
||||||
);
|
);
|
||||||
// Export "fn" (func index = nImports) and "mem" (memory) for the wrapper.
|
// Export "fn" (func index = nImports) and "mem" (memory) for the wrapper.
|
||||||
PsWasmCompiler.#exportSection = new Uint8Array(
|
this.#exportSection = new Uint8Array(
|
||||||
section(
|
section(
|
||||||
SECTION.export,
|
SECTION.export,
|
||||||
vec([
|
vec([
|
||||||
@ -228,7 +230,7 @@ class PsWasmCompiler {
|
|||||||
);
|
);
|
||||||
// Wasm binary magic + version (constant).
|
// Wasm binary magic + version (constant).
|
||||||
// https://webassembly.github.io/spec/core/binary/modules.html#binary-magic
|
// https://webassembly.github.io/spec/core/binary/modules.html#binary-magic
|
||||||
PsWasmCompiler.#wasmMagicVersion = new Uint8Array([
|
this.#wasmMagicVersion = new Uint8Array([
|
||||||
0x00,
|
0x00,
|
||||||
0x61,
|
0x61,
|
||||||
0x73,
|
0x73,
|
||||||
@ -239,9 +241,9 @@ class PsWasmCompiler {
|
|||||||
0x00, // version 1
|
0x00, // version 1
|
||||||
]);
|
]);
|
||||||
const f64Buf = new ArrayBuffer(8);
|
const f64Buf = new ArrayBuffer(8);
|
||||||
PsWasmCompiler.#f64View = new DataView(f64Buf);
|
this.#f64View = new DataView(f64Buf);
|
||||||
PsWasmCompiler.#f64Arr = new Uint8Array(f64Buf);
|
this.#f64Arr = new Uint8Array(f64Buf);
|
||||||
PsWasmCompiler.#initialized = true;
|
this.#initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(domain, range) {
|
constructor(domain, range) {
|
||||||
|
|||||||
@ -13,10 +13,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
|
||||||
buildPostScriptJsFunction,
|
|
||||||
buildPostScriptProgramFunction,
|
|
||||||
} from "../../src/core/postscript/js_evaluator.js";
|
|
||||||
import {
|
import {
|
||||||
buildPostScriptWasmFunction,
|
buildPostScriptWasmFunction,
|
||||||
compilePostScriptToWasm,
|
compilePostScriptToWasm,
|
||||||
@ -39,6 +35,7 @@ import {
|
|||||||
PsTernaryNode,
|
PsTernaryNode,
|
||||||
PsUnaryNode,
|
PsUnaryNode,
|
||||||
} from "../../src/core/postscript/ast.js";
|
} from "../../src/core/postscript/ast.js";
|
||||||
|
import { buildPostScriptJsFunction } from "../../src/core/postscript/js_evaluator.js";
|
||||||
|
|
||||||
// Precision argument for toBeCloseTo() in trigonometric tests.
|
// Precision argument for toBeCloseTo() in trigonometric tests.
|
||||||
const TRIGONOMETRY_EPS = 1e-10;
|
const TRIGONOMETRY_EPS = 1e-10;
|
||||||
@ -209,10 +206,11 @@ describe("PostScript Type 4 lexer, parser, and Wasm compiler", function () {
|
|||||||
// direct program interpreter otherwise.
|
// direct program interpreter otherwise.
|
||||||
const jsFn = buildPostScriptJsFunction(src, domain, range);
|
const jsFn = buildPostScriptJsFunction(src, domain, range);
|
||||||
// Direct interpreter: always available, never uses PSStackToTree.
|
// Direct interpreter: always available, never uses PSStackToTree.
|
||||||
const interpFn = buildPostScriptProgramFunction(
|
const interpFn = buildPostScriptJsFunction(
|
||||||
parsePostScriptFunction(src),
|
src,
|
||||||
domain,
|
domain,
|
||||||
range
|
range,
|
||||||
|
/* forceInterpreter = */ true
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!wasmFn) {
|
if (!wasmFn) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user