summaryrefslogtreecommitdiff
path: root/yjit_asm.h
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2021-12-01 14:15:23 -0500
committerAlan Wu <XrXr@users.noreply.github.com>2021-12-03 20:02:25 -0500
commitf41b4d44f95978dfa97af04af00055dc3fbf7978 (patch)
tree744a3d5e2d8f1ef0b3a4ab00a7cd99df0353f6b8 /yjit_asm.h
parent3be067234f156d75e6143cca5037df7eef1bd112 (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 <tenderlove@ruby-lang.org>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5209
Diffstat (limited to 'yjit_asm.h')
-rw-r--r--yjit_asm.h23
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);