diff options
author | Alan Wu <[email protected]> | 2021-12-01 14:15:23 -0500 |
---|---|---|
committer | Alan Wu <[email protected]> | 2021-12-03 20:02:25 -0500 |
commit | f41b4d44f95978dfa97af04af00055dc3fbf7978 (patch) | |
tree | 744a3d5e2d8f1ef0b3a4ab00a7cd99df0353f6b8 /yjit_asm.h | |
parent | 3be067234f156d75e6143cca5037df7eef1bd112 (diff) |
YJIT: Bounds check every byte in the assembler
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 <[email protected]>
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/5209
Diffstat (limited to 'yjit_asm.h')
-rw-r--r-- | yjit_asm.h | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/yjit_asm.h b/yjit_asm.h index ad032d0139..202f21e796 100644 --- a/yjit_asm.h +++ b/yjit_asm.h @@ -26,12 +26,13 @@ typedef struct LabelRef typedef struct CodeBlock { // Memory block - uint8_t *mem_block; + // Users are advised to not use this directly. + uint8_t *mem_block_; // Memory block size uint32_t mem_size; - /// Current writing position + // Current writing position uint32_t write_pos; // Table of registered label addresses @@ -50,14 +51,20 @@ typedef struct CodeBlock // Number of references to labels uint32_t num_refs; - // TODO: system for disassembly/comment strings, indexed by position - - // Flag to enable or disable comments - bool has_asm; // Keep track of the current aligned write position. // Used for changing protection when writing to the JIT buffer uint32_t current_aligned_write_pos; + + // Set if the assembler is unable to output some instructions, + // for example, when there is not enough space or when a jump + // target is too far away. + bool dropped_bytes; + + // Flag to enable or disable comments + bool has_asm; + + } codeblock_t; // 1 is not aligned so this won't match any pages @@ -258,8 +265,8 @@ static inline void cb_init(codeblock_t *cb, uint8_t *mem_block, uint32_t mem_siz static inline void cb_align_pos(codeblock_t *cb, uint32_t multiple); static inline void cb_set_pos(codeblock_t *cb, uint32_t pos); static inline void cb_set_write_ptr(codeblock_t *cb, uint8_t *code_ptr); -static inline uint8_t *cb_get_ptr(codeblock_t *cb, uint32_t index); -static inline uint8_t *cb_get_write_ptr(codeblock_t *cb); +static inline uint8_t *cb_get_ptr(const codeblock_t *cb, uint32_t index); +static inline uint8_t *cb_get_write_ptr(const codeblock_t *cb); static inline void cb_write_byte(codeblock_t *cb, uint8_t byte); static inline void cb_write_bytes(codeblock_t *cb, uint32_t num_bytes, ...); static inline void cb_write_int(codeblock_t *cb, uint64_t val, uint32_t num_bits); |