### Build SLJIT Examples with GNU Make (Bash) Source: https://github.com/zherczeg/sljit/blob/master/docs/general/getting-started/setup.md Command to build the SLJIT example executables using GNU Make. Run 'make examples' from the repository root. The executables will be placed in the 'bin' directory. ```bash make examples ``` -------------------------------- ### Start Docusaurus Development Server Source: https://github.com/zherczeg/sljit/blob/master/docs/website/README.md Starts the local development server for the Docusaurus website. This command typically launches a browser window to preview changes in real-time. ```bash npm run start ``` -------------------------------- ### Install Website Dependencies Source: https://github.com/zherczeg/sljit/blob/master/docs/website/README.md Installs the necessary Node.js dependencies for the Docusaurus website using npm. This command should be executed within the `docs/website` directory. ```bash cd docs/website npm install ``` -------------------------------- ### Implement Loop with SLJIT C Source: https://github.com/zherczeg/sljit/blob/master/docs/tutorial/03-branching.md Illustrates how to construct a loop in C using SLJIT. This example shows the generation of code for a for loop by using labels for loop start and end points, conditional jumps for loop termination, and arithmetic operations for iteration. ```c #include "sljitLir.h" #include #include typedef sljit_sw (SLJIT_FUNC *func2_t)(sljit_sw a, sljit_sw b); static int loop(sljit_sw a, sljit_sw b) { void *code; sljit_uw len; func2_t func; struct sljit_label *loopstart; struct sljit_jump *out; /* Create a SLJIT compiler */ struct sljit_compiler *C = sljit_create_compiler(NULL); /* 2 arg, 2 temp reg, 2 saved reg */ sljit_emit_enter(C, 0, SLJIT_ARGS2(W, W, W), 2, 2, 0); /* R0 = 0 */ sljit_emit_op2(C, SLJIT_XOR, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_R1, 0); /* RET = 0 */ sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); /* loopstart: */ loopstart = sljit_emit_label(C); /* R1 >= a --> jump out */ out = sljit_emit_cmp(C, SLJIT_GREATER_EQUAL, SLJIT_R1, 0, SLJIT_S0, 0); /* RET += b */ sljit_emit_op2(C, SLJIT_ADD, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0, SLJIT_S1, 0); R1 += 1 */ sljit_emit_op2(C, SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); /* jump loopstart */ sljit_set_label(sljit_emit_jump(C, SLJIT_JUMP), loopstart); /* out: */ sljit_set_label(out, sljit_emit_label(C)); /* return RET */ sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0); /* Generate machine code */ code = sljit_generate_code(C, 0, NULL); len = sljit_get_generated_code_size(C); /* Execute code */ func = (func2_t)code; printf("func return %ld\n", (long)func(a, b)); /* dump_code(code, len); */ /* Clean up */ sljit_free_compiler(C); /* sljit_free_code(code, NULL); */ /* Commented out to avoid double free if code is not generated */ return 0; } ``` -------------------------------- ### SLJIT Example Main Function Source: https://github.com/zherczeg/sljit/blob/master/docs/tutorial/03-branching.md This snippet shows a basic C main function that calls another function named 'loop' with arguments 4 and 5. It represents a simple execution flow within the SLJIT project context. The surrounding text implies this is part of a larger example demonstrating control structures. ```c int main() { return loop(4, 5); } ``` -------------------------------- ### Build SLJIT Tests with GNU Make (Bash) Source: https://github.com/zherczeg/sljit/blob/master/docs/general/getting-started/setup.md Command to build the SLJIT test executable using GNU Make. Navigate to the repository root and run 'make'. The output 'sljit_test' will be in the 'bin' directory. ```bash make ``` -------------------------------- ### Include SLJIT as Library (C) Source: https://github.com/zherczeg/sljit/blob/master/docs/general/getting-started/setup.md Demonstrates how to compile SLJIT's main C file as a separate translation unit and include its header. This method requires adding the SLJIT source directory to include paths and linking the compiled object file. ```c #include "sljitLir.h" // Link against sljitLir.o ``` -------------------------------- ### Embed SLJIT as All-in-one (C) Source: https://github.com/zherczeg/sljit/blob/master/docs/general/getting-started/setup.md Shows how to embed SLJIT directly into a project by defining SLJIT_CONFIG_STATIC before including the sljitLir.c file. This hides SLJIT's interface and prevents symbol clashes, useful for static linking. ```c #define SLJIT_CONFIG_STATIC 1 #include "sljitLir.c" // SLJIT can be used in hidden.c, but not in other translation units ``` -------------------------------- ### Build SLJIT Tests with CMake (Bash) Source: https://github.com/zherczeg/sljit/blob/master/docs/general/getting-started/setup.md Instructions for building SLJIT tests on Windows using MSVC and NMake via CMake. This involves creating a build directory and executing the build command. ```bash cmake -B bin -G "NMake Makefiles" cmake --build bin ``` -------------------------------- ### SLJIT Function Signature and Parameter Passing Source: https://github.com/zherczeg/sljit/blob/master/docs/tutorial/02-your-first-program.md Explains how function signatures are defined in SLJIT using `SLJIT_ARGS...` macros. It details parameter passing conventions for integer and floating-point types, and how return values are handled. ```C /* Example of function signature definition */ /* SLJIT_ARGS(return_type, arg1_type, arg2_type, ...) For example, to declare a function returning an integer and taking three integer parameters: SLJIT_ARGS(SLJIT_W, SLJIT_W, SLJIT_W, SLJIT_W) */ /* Parameter passing: Integers: SLJIT_S0 - SLJIT_S3 Floating point: SLJIT_FR0 - SLJIT_FR3 Return value: SLJIT_R0 (integer) or SLJIT_FR0 (float) */ ``` -------------------------------- ### Create and Execute Addition Function with SLJIT Source: https://github.com/zherczeg/sljit/blob/master/docs/tutorial/02-your-first-program.md This C code snippet demonstrates the fundamental usage of the SLJIT library to generate machine code for a function that adds three integer arguments. It covers creating a SLJIT compiler, defining the function's ABI using `sljit_emit_enter`, emitting arithmetic operations (`sljit_emit_op1`, `sljit_emit_op2`), returning the result (`sljit_emit_return`), generating executable code, and executing the compiled function. It also includes necessary cleanup steps. ```c #include "sljitLir.h" #include #include typedef sljit_sw (SLJIT_FUNC *func3_t)(sljit_sw a, sljit_sw b, sljit_sw c); static int add3(sljit_sw a, sljit_sw b, sljit_sw c) { void *code; sljit_uw len; func3_t func; /* Create a SLJIT compiler */ struct sljit_compiler *C = sljit_create_compiler(NULL); /* Start a context (function prologue) */ sljit_emit_enter(C, 0, /* Options */ SLJIT_ARGS3(W, W, W, W), /* 1 return value and 3 parameters of type sljit_sw */ 1, /* 1 scratch register used */ 3, /* 3 saved registers used */ 0); /* 0 bytes allocated for function local variables */ /* The first argument of a function is stored in register SLJIT_S0, the 2nd in SLJIT_S1, etc. */ /* R0 = first */ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0); /* R0 = R0 + second */ sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0); /* R0 = R0 + third */ sljit_emit_op2(C, SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0); /* This statement moves R0 to RETURN REG and returns */ /* (in fact, R0 is the RETURN REG itself) */ sljit_emit_return(C, SLJIT_MOV, SLJIT_R0, 0); /* Generate machine code */ code = sljit_generate_code(C, 0, NULL); len = sljit_get_generated_code_size(C); /* Execute code */ func = (func3_t)code; printf("func return %ld\n", (long)func(a, b, c)); /* dump_code(code, len); */ /* Clean up */ sljit_free_compiler(C); sljit_free_code(code, NULL); return 0; } int main() { return add3(4, 5, 6); } ``` -------------------------------- ### Generate Code for x86-64 (C) Source: https://github.com/zherczeg/sljit/blob/master/docs/general/getting-started/setup.md Demonstrates how to configure SLJIT to generate code for the x86 64-bit architecture. This involves defining SLJIT_CONFIG_STATIC and SLJIT_CONFIG_X86_64 before including the sljitLir.c file. ```c #define SLJIT_CONFIG_STATIC 1 #define SLJIT_CONFIG_X86_64 1 #include "sljitLir.c" // Generate code for x86 64-bit ``` -------------------------------- ### Generate Code for x86-32 (C) Source: https://github.com/zherczeg/sljit/blob/master/docs/general/getting-started/setup.md Illustrates how to configure SLJIT to generate code specifically for the x86 32-bit architecture. This is achieved by defining both SLJIT_CONFIG_STATIC and SLJIT_CONFIG_X86_32 before including sljitLir.c. ```c #define SLJIT_CONFIG_STATIC 1 #define SLJIT_CONFIG_X86_32 1 #include "sljitLir.c" // Generate code for x86 32-bit ``` -------------------------------- ### SLJIT Emit Operation Operands Source: https://github.com/zherczeg/sljit/blob/master/docs/tutorial/02-your-first-program.md Documents the operand types and their representations for the `sljit_emit_opN` functions. This includes immediate values, registers, and various memory addressing modes. ```APIDOC SLJIT_EMIT_OP_OPERANDS: Operand Types: - Register: - Format: `r` (e.g., `SLJIT_R0`) - Description: The value contained in register `r`. - Example: `SLJIT_R0, 0` - Immediate Value: - Format: `SLJIT_IMM, value` - Description: The literal value `value`. - Example: `SLJIT_IMM, 17` - Memory Address (Absolute): - Format: `SLJIT_MEM / SLJIT_MEM0, address` - Description: The value at the absolute memory address `a`. - Example: `SLJIT_MEM0, &my_c_func` - Memory Address (Register + Offset): - Format: `SLJIT_MEM1(r), offset` - Description: The value at the memory address `*r + o`. - Example: `SLJIT_MEM1(SLJIT_R0), 16` (Access memory at address in SLJIT_R0 offset by 16) - Memory Address (Register + Register * Scale): - Format: `SLJIT_MEM2(r1, r2), shift` - Description: The value at memory address `*r1 + (*r2 * (1 << s))`. `s` must be in `[0, 1, 2, 3]`. - Example: `SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 2` (Access index SLJIT_R1 in an array of items of length 2 bytes starting at address SLJIT_R0) Related Functions: - `sljit_emit_opN`: Emits generic operations with specified operands. - `sljit_emit_return`: Returns control to the caller. ``` -------------------------------- ### Dump SLJIT Generated Code Source: https://github.com/zherczeg/sljit/blob/master/docs/tutorial/08-where-to-go-from-here.md A C function to dump the generated assembly code from SLJIT to a file and display it using objdump. It requires file I/O and system calls, and uses SLJIT configuration defines to select the correct objdump command for x86-32 or x86-64 architectures. ```c static void dump_code(void *code, sljit_uw len) { FILE *fp = fopen("/tmp/sljit_dump", "wb"); if (!fp) return; fwrite(code, len, 1, fp); fclose(fp); #if defined(SLJIT_CONFIG_X86_64) system("objdump -b binary -m l1om -D /tmp/sljit_dump"); #elif defined(SLJIT_CONFIG_X86_32) system("objdump -b binary -m i386 -D /tmp/sljit_dump"); #endif } ``` -------------------------------- ### Implement Conditional Branching with SLJIT C Source: https://github.com/zherczeg/sljit/blob/master/docs/tutorial/03-branching.md Demonstrates how to implement a conditional branch in C using SLJIT. It shows the process of emitting comparison instructions, conditional jumps, labels, and connecting them to achieve the desired control flow, similar to an if-else statement. ```c #include "sljitLir.h" #include #include typedef sljit_sw (SLJIT_FUNC *func3_t)(sljit_sw a, sljit_sw b, sljit_sw c); static int branch(sljit_sw a, sljit_sw b, sljit_sw c) { void *code; sljit_uw len; func3_t func; struct sljit_jump *ret_c; struct sljit_jump *out; /* Create a SLJIT compiler */ struct sljit_compiler *C = sljit_create_compiler(NULL); /* 3 arg, 1 temp reg, 3 save reg */ sljit_emit_enter(C, 0, SLJIT_ARGS3(W, W, W, W), 1, 3, 0); /* R0 = a & 1, S0 is argument a */ sljit_emit_op2(C, SLJIT_AND, SLJIT_R0, 0, SLJIT_S0, 0, SLJIT_IMM, 1); /* if R0 == 0 then jump to ret_c, where is ret_c? we assign it later */ ret_c = sljit_emit_cmp(C, SLJIT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0); /* R0 = b, S1 is argument b */ sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S1, 0); /* jump to out */ out = sljit_emit_jump(C, SLJIT_JUMP); /* here is the 'ret_c' should jump, we emit a label and set it to ret_c */ sljit_set_label(ret_c, sljit_emit_label(C)); /* R0 = c, S2 is argument c */ sljit_emit_op1(C, SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_S2, 0); /* here is the 'out' should jump */ sljit_set_label(out, sljit_emit_label(C)); /* end of function */ sljit_emit_return(C, SLJIT_MOV, SLJIT_RETURN_REG, 0); /* Generate machine code */ code = sljit_generate_code(C, 0, NULL); len = sljit_get_generated_code_size(C); /* Execute code */ func = (func3_t)code; printf("func return %ld\n", (long)func(a, b, c)); /* dump_code(code, len); */ /* Clean up */ sljit_free_compiler(C); sljit_free_code(code, NULL); return 0; } int main() { return branch(4, 5, 6); } ``` -------------------------------- ### CMake Build Script for sljit Source: https://github.com/zherczeg/sljit/blob/master/CMakeLists.txt This CMake script configures the build process for sljit. It specifies the minimum required CMake version, defines the project, includes a custom function to read variables from a GNUmakefile, finds required packages like Threads, sets up include directories, defines the main executable target 'sljit_test' with its source files, and configures platform-specific compile definitions and linker flags. ```cmake cmake_minimum_required(VERSION 3.12) project(sljit C) # https://gist.github.com/tusharpm/d71dd6cab8a00320ddb48cc82bf7f64c if(POLICY CMP0007) cmake_policy(SET CMP0007 NEW) endif() function(ReadVariables MKFile) file(READ "${MKFile}" FileContents) string(REPLACE "\\n" "" FileContents ${FileContents}) string(REPLACE "\n" ";" FileLines ${FileContents}) list(REMOVE_ITEM FileLines "") foreach(line ${FileLines}) if(line MATCHES "^[ A-Z]*=") string(REPLACE "=" ";" line_split ${line}) list(GET line_split -1 value) string(STRIP "${value}" value) separate_arguments(value) list(REMOVE_AT line_split -1) foreach(var_name ${line_split}) string(STRIP ${var_name} var_name) set(${var_name} ${value} PARENT_SCOPE) endforeach() endif() endforeach() endfunction() ReadVariables(GNUmakefile) find_package(Threads REQUIRED) include_directories(${SRCDIR} ${TESTDIR}) add_executable(sljit_test ${TESTDIR}/sljitMain.c ${TESTDIR}/sljitTest.c ${SRCDIR}/sljitLir.c) target_compile_definitions(sljit_test PRIVATE SLJIT_HAVE_CONFIG_PRE) target_link_libraries(sljit_test Threads::Threads) if(MSVC) set_target_properties(sljit_test PROPERTIES LINK_FLAGS "/STACK:0x400000") else() set_target_properties(sljit_test PROPERTIES LINK_FLAGS "-Wl,--stack,4194304") endif() ``` -------------------------------- ### Calling an External C Function Source: https://github.com/zherczeg/sljit/blob/master/docs/tutorial/04-calling-external-functions.md Demonstrates how to call an external C function, `print_num`, from JIT-compiled code using SLJIT. It shows how to set up arguments in registers and use `sljit_emit_icall` with the correct calling convention and function address. ```c /* R0 = S2 */ sljit_emit_op1(C, SLJIT_MOV, SLJIT_R0, 0, SLJIT_S2, 0); /* print_num(R0) */ sljit_emit_icall(C, SLJIT_CALL, SLJIT_ARGS1(W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(print_num)); ``` -------------------------------- ### PCRE2 JIT Pattern Structure in Python Source: https://github.com/zherczeg/sljit/blob/master/docs/general/use-cases/pattern-matching/speeding-up-pcre2-with-sljit.md This Python code illustrates the structure of machine code generated by the PCRE2 JIT compiler for regular expression patterns. It details the matching and backtracking paths, control flow, and the use of variables like STRING_POINTER, crucial for understanding regex engine execution. ```python # Start of matching paths ENTER # Matching path of matching the "a" letter MATCH "a", IF FAILS GOTO L6 # Matching path of (?:)+ STACK_PUSH NULL L1: # Matching path of matching the \w special character MATCH WORD_CHARACTER, IF FAILS GOTO L5 # Matching path of matching the \d special character MATCH DIGIT_CHARACTER, IF FAILS GOTO L4 # Continue the matching path of (?:)+ STACK_PUSH STRING_POINTER GOTO L1 L2: # Matching path of matching the "d" letter MATCH "d", IF FAILS GOTO L3 RETURN SUCCESS # Start of backtracking paths # Backtracking path of matching the "d" letter (empty) L3: # Backtracking path of (?:)+ (empty) # Backtracking path of matching the dot special character (empty) L4: # Backtracking path of matching the "b" letter (empty) L5: # Continue backtracking path of (?:)+ STRING_POINTER = STACK_POP IF STRING_POINTER != NULL GOTO L2 # Backtracking path of matching the "a" letter (empty) L6: RETURN FAIL ``` -------------------------------- ### Demonstrate SLJIT Register Type Matching in C Source: https://github.com/zherczeg/sljit/blob/master/docs/general/architecture.md This snippet illustrates valid register type usage in SLJIT. It shows loading an int32_t value into SLJIT_R0 and then performing a byte swap operation, maintaining the int32_t type. This adheres to SLJIT's rule that source operand register types must match instruction expectations. ```c sljit_emit_op1(compiler, SLJIT_MOV32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0); // An int32_t value is loaded into SLJIT_R0 sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R0, 0, SLJIT_R0, 0); // the int32_t value in SLJIT_R0 is byte swapped // and the type of the result is still int32_t ``` -------------------------------- ### SLJIT Memory Access and Offset Macros Source: https://github.com/zherczeg/sljit/blob/master/docs/tutorial/05-accessing-structures.md Details on SLJIT's approach to accessing structure members via memory operands and offset calculations. Covers the `sljit_emit_op1` function, `SLJIT_MEM1` addressing mode, and the `SLJIT_OFFSETOF` macro for determining member offsets. ```APIDOC SLJIT API Documentation: SLJIT_MEM1(reg) - Addressing mode for memory access relative to a base register. - Parameters: - reg: The base register (e.g., SLJIT_S0). - Usage: Used with SLJIT_OP1 or SLJIT_OP2 to specify a memory operand. SLJIT_OFFSETOF(struct_type, member) - Macro to calculate the byte offset of a member within a structure. - Parameters: - struct_type: The name of the structure (e.g., `struct point_st`). - member: The name of the member within the structure (e.g., `y`). - Returns: The calculated offset as an integer. - Usage: Typically used as the second operand in `sljit_emit_op1` or `sljit_emit_op2` when accessing memory via `SLJIT_MEM1`. sljit_emit_op1(compiler, op, dst, dstw, src, srcw) - Emits a binary operation. - Parameters: - compiler: Pointer to the SLJIT compiler context. - op: The operation code (e.g., SLJIT_MOV_S32 for signed 32-bit move). - dst: Destination operand. - dstw: Width of the destination operand. - src: Source operand. - srcw: Width of the source operand. - Example Usage: sljit_emit_op1(C, SLJIT_MOV_S32, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(struct point_st, y)); - This moves a signed 32-bit value from the memory location pointed to by SLJIT_S0 plus the offset of `y` in `struct point_st` into register SLJIT_R0. Important Note: - Always use the correctly typed variant of `SLJIT_MOV` (e.g., `SLJIT_MOV_S32`, `SLJIT_MOV_U16`) to match the data type of the member being accessed. ``` -------------------------------- ### SLJIT Function Generation API Source: https://github.com/zherczeg/sljit/blob/master/docs/general/architecture.md SLJIT provides specific complex instructions for generating function entry and return points. These instructions, along with context management, are crucial for creating callable functions from C. The compilation context, set by `sljit_emit_enter` or `sljit_set_context`, influences compiler optimizations. ```APIDOC SLJIT Function Generation and Context Management: `sljit_emit_enter(uint32_t options, uint32_t locals, uint32_t args)` - Emits instructions to generate a function entry point. - Initializes the compilation context, specifying register mapping, local space size, and other configurations. - Parameters: - `options`: Flags for function entry (e.g., calling convention). - `locals`: Size of the local stack frame in bytes. - `args`: Number of arguments passed to the function. - Returns: SLJIT status code. `sljit_set_context(uint32_t options, uint32_t locals, uint32_t args)` - Sets the compilation context without emitting machine instructions. - Can be used to change the context after the initial setup. - Parameters: - `options`: Flags for function entry. - `locals`: Size of the local stack frame in bytes. - `args`: Number of arguments passed to the function. - Returns: SLJIT status code. `sljit_emit_return(uint32_t options)` - Emits instructions to generate a function return point. - Parameters: - `options`: Flags for function return. - Returns: SLJIT status code. Note: The first instruction after compiler creation must be either `sljit_emit_enter` or `sljit_set_context`. ``` -------------------------------- ### Regex Atomic Block and Repetition Optimizations Source: https://github.com/zherczeg/sljit/blob/master/docs/general/use-cases/pattern-matching/speeding-up-pcre2-with-sljit.md Illustrates optimizations for atomic blocks and repetitions in regular expressions. The JIT compiler can convert greedy repetitions to possessive ones (`a+` to `a++`) when side effects are not an issue, and optimizes repetitions followed by a single character by limiting backtracking ranges. It also explains the use of `(*SKIP)` to improve performance by resuming search from the end of failed matches. ```regex x\R{2}y // Matches 'x' followed by exactly two newline characters, then 'y'. \R represents a newline character. a+b // Greedy repetition of 'a' followed by 'b'. The JIT may convert this to a++b if no side effects occur. a++b // Possessive repetition of 'a' followed by 'b'. Prevents backtracking into the 'a' sequence. \w+x // Matches one or more word characters followed by 'x'. The JIT optimizes this by recording the range of the last 'x' found. \w++ // Possessive repetition of word characters. (*SKIP) // Control verb that skips the current match and continues searching from the end of the skipped portion. \w+(*SKIP)! // Pattern that matches word characters, skips them, and then fails. Used to exclude certain patterns. \w+! // Similar to \w+(*SKIP)!, but relies on the JIT's ability to resume search from the end of the failed match. ``` -------------------------------- ### Caseless Character Class Optimizations Source: https://github.com/zherczeg/sljit/blob/master/docs/general/use-cases/pattern-matching/speeding-up-pcre2-with-sljit.md Details optimizations for caseless character comparisons and character class checks. When caseless mode is active, simple character comparisons can be optimized using bitwise operations if the case difference is a single bit. This extends to character ranges, allowing for faster checks. ```c-like int chr = 'x'; // Basic caseless compare using bitwise OR if ((chr | 0x20) == 'x') { // Character is 'x' or 'X' } // Optimized caseless range check // For a range like [f-xF-X] char c = 'g'; if (((c | 0x20) - 'f') < ('x' - 'f')) { // Character is within the caseless range 'f'-'x' } ``` -------------------------------- ### UTF-8 Character Reader Optimizations Source: https://github.com/zherczeg/sljit/blob/master/docs/general/use-cases/pattern-matching/speeding-up-pcre2-with-sljit.md Explains JIT optimizations for UTF-8 character decoding. When character classes are limited to ASCII (less than 128), only the next byte needs to be read. For invalid UTF-8 parsing, the compiler can optimize boundary checks by assuming at least four bytes are available, which is common. ```conceptual // Optimization for UTF-8 when class is limited to < 128 // Instead of full UTF-8 decoding, only the next byte is read. // Optimization for invalid UTF-8 parsing // Assumes at least 4 bytes remaining in buffer for decoding, // avoiding boundary checks for the longest UTF-8 character. ``` -------------------------------- ### Demonstrate Invalid SLJIT Register Type Usage in C Source: https://github.com/zherczeg/sljit/blob/master/docs/general/architecture.md This snippet highlights an invalid register type sequence in SLJIT. It attempts to load an intptr_t value into SLJIT_R0 and then apply a 32-bit byte swap. This mismatch between the register's intptr_t type and the SLJIT_REV32 instruction's int32_t expectation leads to undefined results or potential crashes. ```c sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R1), 0); // An intptr_t value is loaded into SLJIT_R0 sljit_emit_op1(compiler, SLJIT_REV32, SLJIT_R0, 0, SLJIT_R0, 0); // The result of the instruction is undefined. // Even crash is possible for some instructions // (e.g. on MIPS-64). ``` -------------------------------- ### Single Choice Engine with State Tracking Source: https://github.com/zherczeg/sljit/blob/master/docs/general/use-cases/pattern-matching/regular-expression-engine-types.md Explains balanced engines that use state tracking, characterized by the absence of pathological cases and good partial matching support. Their main drawback is generally lower matching speed due to complex state updates. They also have a limited feature set, similar to pre-generated state machine engines. Execution involves linear search time, often through interpreted DFA or parallel NFA matching. ```APIDOC Single Choice Engine with State Tracking: Type: Usually balanced engines Advantages: - No pathological cases - Partial matching support is not difficult Disadvantages: - Matching speed is generally low due to the complex state update mechanism - Limited feature set (due to synchronization issues, they have a similar feature set as the engines with pre-generated state machine) Execution modes: - Interpreted execution of Deterministic Finite Automaton (DFA); example: PCRE-DFA interpreter - Parallel matching of NFA; example: TRE engine ```