Skip to content

Commit 7d1dd60

Browse files
authored
Merge pull request ruby#125 from Shopify/code_pages
Code page GC object
2 parents e8a5c7b + 34a0954 commit 7d1dd60

File tree

4 files changed

+69
-27
lines changed

4 files changed

+69
-27
lines changed

yjit_asm.c

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -224,18 +224,11 @@ uint8_t* alloc_exec_mem(uint32_t mem_size)
224224
// How many code pages to allocate at once
225225
#define PAGES_PER_ALLOC 512
226226

227-
typedef struct free_list_node
228-
{
229-
uint8_t* page_ptr;
230-
231-
struct free_list_node *next;
232-
233-
} freelist_t;
234-
235-
freelist_t *freelist = NULL;
227+
// Head of the list of free code pages
228+
code_page_t *freelist = NULL;
236229

237230
// Allocate a single code page from a pool of free pages
238-
uint8_t* alloc_code_page()
231+
code_page_t* alloc_code_page()
239232
{
240233
fprintf(stderr, "allocating code page\n");
241234

@@ -246,29 +239,25 @@ uint8_t* alloc_code_page()
246239

247240
// Do this in reverse order so we allocate our pages in order
248241
for (int i = PAGES_PER_ALLOC - 1; i >= 0; --i) {
249-
freelist_t* node = malloc(sizeof(freelist_t));
250-
node->page_ptr = code_chunk + i * CODE_PAGE_SIZE;
251-
node->next = freelist;
252-
freelist = node;
242+
code_page_t* code_page = malloc(sizeof(code_page_t));
243+
code_page->mem_block = code_chunk + i * CODE_PAGE_SIZE;
244+
code_page->page_size = CODE_PAGE_SIZE;
245+
code_page->_next = freelist;
246+
freelist = code_page;
253247
}
254248
}
255249

256-
freelist_t* free_node = freelist;
257-
uint8_t* page_ptr = freelist->page_ptr;
258-
259-
freelist = freelist->next;
260-
free(free_node);
250+
code_page_t* free_page = freelist;
251+
freelist = freelist->_next;
261252

262-
return page_ptr;
253+
return free_page;
263254
}
264255

265256
// Put a code page back into the allocation pool
266-
void free_code_page(uint8_t* page_ptr)
257+
void free_code_page(code_page_t* code_page)
267258
{
268-
freelist_t* node = malloc(sizeof(freelist_t));
269-
node->page_ptr = page_ptr;
270-
node->next = freelist;
271-
freelist = node;
259+
code_page->_next = freelist;
260+
freelist = code_page;
272261
}
273262

274263
// Initialize a code block object

yjit_asm.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,20 @@ typedef struct X86Opnd
131131

132132
} x86opnd_t;
133133

134+
// Struct representing a code page
135+
typedef struct code_page_struct
136+
{
137+
// Chunk of executable memory
138+
uint8_t* mem_block;
139+
140+
// Size of the executable memory chunk
141+
uint32_t page_size;
142+
143+
// Next node in the free list (private)
144+
struct code_page_struct* _next;
145+
146+
} code_page_t;
147+
134148
// Dummy none/null operand
135149
static const x86opnd_t NO_OPND = { OPND_NONE, 0, .as.imm = 0 };
136150

@@ -242,8 +256,8 @@ x86opnd_t const_ptr_opnd(const void *ptr);
242256

243257
// Machine code allocation
244258
uint8_t* alloc_exec_mem(uint32_t mem_size);
245-
uint8_t* alloc_code_page();
246-
void free_code_page(uint8_t* page_ptr);
259+
code_page_t* alloc_code_page(void);
260+
void free_code_page(code_page_t* code_page);
247261

248262
// Code block methods
249263
void cb_init(codeblock_t* cb, uint8_t* mem_block, uint32_t mem_size);

yjit_core.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,12 @@ typedef struct yjit_block_version
242242
VALUE receiver_klass;
243243
VALUE callee_cme;
244244

245+
// Code page this block lives on
246+
VALUE code_page;
247+
245248
// Index one past the last instruction in the iseq
246249
uint32_t end_idx;
250+
247251
} block_t;
248252

249253
// Context object methods

yjit_iface.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,9 @@ rb_yjit_iseq_mark(const struct rb_iseq_constant_body *body)
855855
memcpy(&object, value_address, SIZEOF_VALUE);
856856
rb_gc_mark_movable(object);
857857
}
858+
859+
// Mark the machine code page this block lives on
860+
rb_gc_mark_movable(block->code_page);
858861
}
859862
}
860863
}
@@ -895,6 +898,9 @@ rb_yjit_iseq_update_references(const struct rb_iseq_constant_body *body)
895898
memcpy(value_address, &possibly_moved, SIZEOF_VALUE);
896899
}
897900
}
901+
902+
// Update the machine code page this block lives on
903+
block->code_page = rb_gc_location(block->code_page);
898904
}
899905
}
900906
}
@@ -917,6 +923,35 @@ rb_yjit_iseq_free(const struct rb_iseq_constant_body *body)
917923
rb_darray_free(body->yjit_blocks);
918924
}
919925

926+
static void
927+
yjit_code_page_free(void *code_page)
928+
{
929+
free_code_page((code_page_t*)code_page);
930+
}
931+
932+
// Custom type for interacting with the GC
933+
static const rb_data_type_t yjit_code_page_type = {
934+
"yjit_code_page",
935+
{NULL, yjit_code_page_free, NULL, NULL},
936+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
937+
};
938+
939+
// Allocate a code page and wrap it into a Ruby object owned by the GC
940+
VALUE rb_yjit_code_page_alloc(void)
941+
{
942+
code_page_t* code_page = alloc_code_page();
943+
VALUE cp_obj = TypedData_Wrap_Struct(0, &yjit_code_page_type, code_page);
944+
return cp_obj;
945+
}
946+
947+
// Unwrap the Ruby object representing a code page
948+
code_page_t *rb_yjit_code_page_unwrap(VALUE cp_obj)
949+
{
950+
code_page_t * code_page;
951+
TypedData_Get_Struct(cp_obj, code_page_t, &yjit_code_page_type, code_page);
952+
return code_page;
953+
}
954+
920955
bool
921956
rb_yjit_enabled_p(void)
922957
{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy