aboutsummaryrefslogtreecommitdiffstats
path: root/yjit_asm.c
Commit message (Collapse)AuthorAgeFilesLines
* YJIT: Fix unexpected truncation when outputing VALUEAlan Wu2021-12-141-1/+4
| | | | | | | | | | | | | Previously, YJIT incorrectly discarded the upper 32 bits of the object pointer when writing out VALUEs to setup default keyword arguments. In addition to incorrectly truncating, the output pointers were not properly tracked for handling GC compaction moving the referenced objects. YJIT previously attempted to encode a mov instruction with a memory destination and a 64 bit immediate when there is no such encoding possible in the ISA. Add an assert to mitigate not being able to catch this at build time.
* YJIT: Initialize code buffer with PUSH DSAlan Wu2021-12-051-3/+4
| | | | | | | PUSH DS triggers the #UD processor exception in 64-bit mode, which the OS translates to a SIGILL. Unlike INT3, this triggers the usual crash reporter, which makes failures easier to notice. When there is a debugger attached, the PUSH DS pauses execution just like INT3.
* YJIT: Bounds check every byte in the assemblerAlan Wu2021-12-031-38/+54
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, YJIT assumed that basic blocks never consume more than 1 KiB of memory. This assumption does not hold for long Ruby methods such as the one in the following: ```ruby eval(<<RUBY) def set_local_a_lot #{'_=0;'*0x40000} end RUBY set_local_a_lot ``` For low `--yjit-exec-mem-size` values, one basic block could exhaust the entire buffer. Introduce a new field `codeblock_t::dropped_bytes` that the assembler sets whenever it runs out of space. Check this field in gen_single_block() to respond to out of memory situations and other error conditions. This design avoids making the control flow graph of existing code generation functions more complex. Use POSIX shell in misc/test_yjit_asm.sh since bash is expanding `0%/*/*` differently. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
* Mark JIT code as writeable / executable depending on the situationAaron Patterson2021-12-011-3/+45
| | | | | | | | | | | | | | | | Some platforms don't want memory to be marked as writeable and executable at the same time. When we write to the code block, we calculate the OS page that the buffer position maps to. Then we call `mprotect` to allow writes on that particular page. As an optimization, we cache the "last written" aligned page which allows us to amortize the cost of the `mprotect` call. In other words, sequential writes to the same page will only call `mprotect` on the page once. When we're done writing, we call `mprotect` on the entire JIT buffer. This means we don't need to keep track of which pages were marked as writeable, we let the OS take care of that. Co-authored-by: John Hawthorn <john@hawthorn.email>
* YJIT: use shorter encoding for mov(r64,imm) when unambiguous (#5081)Alan Wu2021-11-051-6/+28
| | | | | | | | | | | | | | | | | | | | | | | | | * YJIT: use shorter encoding for mov(r64,imm) when unambiguous Previously, for small constants such as `mov(RAX, imm_opnd(Qundef))`, we emit an instruction with an 8-byte immediate. This form commonly gets the `movabs` mnemonic. In 64-bit mode, 32-bit operands get zero extended to 64-bit to fill the register, so when the immediate is small enough, we can save 4 bytes by using the `mov` variant that takes a 32-bit immediate and does a zero extension. Not implement with this change, there is an imm32 variant of `mov` that does sign extension we could use. When the constant is negative, we fallback to the `movabs` form. In railsbench, this change yields roughly a 12% code size reduction for the outlined block. Co-authored-by: Jemma Issroff <jemmaissroff@gmail.com> * [ci skip] comment edit. Please squash. Co-authored-by: Jemma Issroff <jemmaissroff@gmail.com>
* YJIT code pages refactoring for code GC (#5073)Maxime Chevalier-Boisvert2021-11-041-36/+1
| | | | | | | | | | | | | | | * New code page allocation logic * Fix leaked globals * Fix leaked symbols, yjit asm tests * Make COUNTED_EXIT take a jit argument, so we can eliminate global ocb * Remove extra whitespace * Change block start_pos/end_pos to be pointers instead of uint32_t * Change branch end_pos and start_pos to end_addr, start_addr
* YJIT: Show GCC that the mmap probing loop runs at least onceAlan Wu2021-10-201-3/+2
| | | | | Fixes: ./src/yjit_asm.c:196:8: warning: 'mem_block' may be used uninitialized [-Wmaybe-uninitialized]
* Fix non RUBY_DEBUG build warningsAlan Wu2021-10-201-5/+5
| | | | | | | | | | | On non RUBY_DEBUG builds, assert() compiles to nothing and the compiler warns about uninitialized variables in those code paths. Replace those asserts with rb_bug() to fix the warnings and do the assert in all builds. Since yjit_asm_tests.c compiles outside of Ruby, it needed a distinct version of rb_bug(). Also put YJIT_STATS check for function delcaration that is only defined in YJIT_STATS builds.
* Put YJIT into a single compilation unitAlan Wu2021-10-201-17/+20
| | | | | | | | | | | | | | | | | | | | | For upstreaming, we want functions we export either prefixed with "rb_" or made static. Historically we haven't been following this rule, so we were "leaking" a lot of symbols as `make leak-globals` would tell us. This change unifies everything YJIT into a single compilation unit, yjit.o, and makes everything unprefixed static to pass `make leak-globals`. This manual "unified build" setup is similar to that of vm.o. Having everything in one compilation unit allows static functions to be visible across YJIT files and removes the need for declarations in headers in some cases. Unnecessary declarations were removed. Other changes of note: - switched to MJIT_SYMBOL_EXPORT_BEGIN which indicates stuff as being off limits for native extensions - the first include of each YJIT file is change to be "internal.h" - undefined MAP_STACK before explicitly redefining it since it collide's with a definition in system headers. Consider renaming?
* style: line break before "else"Alan Wu2021-10-201-4/+8
|
* style: switch statements indentAlan Wu2021-10-201-24/+22
| | | | | Case labels get half an indent and the opening brace is on the same line as "switch".
* style: align pointer "*" to the rightAlan Wu2021-10-201-165/+165
|
* Try to break the code page refactoring into smaller stepsMaxime Chevalier-Boisvert2021-10-201-8/+16
|
* Include errno message in mmap failure outputJean Boussier2021-10-201-1/+2
| | | | It might help figure out why it is failing.
* First pass at code page GC object.Maxime Chevalier-Boisvert2021-10-201-25/+14
|
* Code page allocation codeMaxime Chevalier-Boisvert2021-10-201-0/+53
|
* Implement basic encodings for xchgMaxime Chevalier-Boisvert2021-10-201-0/+23
|
* Fix encoding of test x86 instructionMaxime Chevalier-Boisvert2021-10-201-1/+9
|
* Try to alloc executable memory within rel32 range on Linux machines (#12)Maxime Chevalier-Boisvert2021-10-201-26/+75
| | | | | | | | | | | | | | | | | | | * Use INT32_MIN, INT32_MAX, etc. constants in yjit_asm.c * Print warning on stderr when code past rel32 jump range * Fix preprocessor snafu * Move rel32 warning into --yjit-stats * Try to allocate within rel32 offset on Linux machines * Update yjit_asm.c Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> * On Linux, use sysconf to get the page size Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
* Update yjit_asm.cMaxime Chevalier-Boisvert2021-10-201-1/+1
|
* Fill uninitialized memory with int3Maxime Chevalier-Boisvert2021-10-201-0/+5
|
* Fix GCC warningsAlan Wu2021-10-201-1/+1
| | | | Mostly unused and uninitialized warnings here and there
* Fix condition in cb_align_pos which should return early when alignedDylan Thacker-Smith2021-10-201-1/+1
|
* Yet Another Ruby JIT!Jose Narvaez2021-10-201-0/+1646
Renaming uJIT to YJIT. AKA s/ujit/yjit/g.