зеркало из https://github.com/github/ruby.git
WIP refactor block lists to use darray
This commit is contained in:
Родитель
5c497dfd7f
Коммит
abc016ad2c
|
@ -576,13 +576,27 @@ gen_getinstancevariable(jitstate_t* jit, ctx_t* ctx)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
num_versions = count_block_versions(this_instruction);
|
||||||
|
|
||||||
|
if (num_versions > N)
|
||||||
|
return JIT_CANT_COMPILE;
|
||||||
|
|
||||||
|
|
||||||
if (defer_compilation(this_instruction, ctx))
|
if (defer_compilation(this_instruction, ctx))
|
||||||
return JIT_END_BLOCK;
|
return JIT_END_BLOCK;
|
||||||
|
|
||||||
|
|
||||||
VALUE top_val = jit_peek_at_stack();
|
VALUE top_val = jit_peek_at_stack();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class = get_ruby_class(top_val);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
guard_object_class(class, current_instr);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -593,6 +607,9 @@ gen_getinstancevariable(jitstate_t* jit, ctx_t* ctx)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// If the class uses the default allocator, instances should all be T_OBJECT
|
// If the class uses the default allocator, instances should all be T_OBJECT
|
||||||
// NOTE: This assumes nobody changes the allocator of the class after allocation.
|
// NOTE: This assumes nobody changes the allocator of the class after allocation.
|
||||||
// Eventually, we can encode whether an object is T_OBJECT or not
|
// Eventually, we can encode whether an object is T_OBJECT or not
|
||||||
|
|
98
ujit_core.c
98
ujit_core.c
|
@ -144,17 +144,25 @@ int ctx_diff(const ctx_t* src, const ctx_t* dst)
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static block_t *
|
static rb_ujit_block_array_t
|
||||||
get_first_version(const rb_iseq_t *iseq, unsigned idx)
|
get_version_array(const rb_iseq_t *iseq, unsigned idx)
|
||||||
{
|
{
|
||||||
struct rb_iseq_constant_body *body = iseq->body;
|
struct rb_iseq_constant_body *body = iseq->body;
|
||||||
|
|
||||||
if (rb_darray_size(body->ujit_blocks) == 0) {
|
if (rb_darray_size(body->ujit_blocks) == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RUBY_ASSERT((unsigned)rb_darray_size(body->ujit_blocks) == body->iseq_size);
|
RUBY_ASSERT((unsigned)rb_darray_size(body->ujit_blocks) == body->iseq_size);
|
||||||
return rb_darray_get(body->ujit_blocks, idx);
|
return rb_darray_get(body->ujit_blocks, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count the number of block versions matching a given blockid
|
||||||
|
static size_t get_num_versions(blockid_t blockid)
|
||||||
|
{
|
||||||
|
return rb_darray_size(get_version_array(blockid.iseq, blockid.idx));
|
||||||
|
}
|
||||||
|
|
||||||
// Keep track of a block version. Block should be fully constructed.
|
// Keep track of a block version. Block should be fully constructed.
|
||||||
static void
|
static void
|
||||||
add_block_version(blockid_t blockid, block_t* block)
|
add_block_version(blockid_t blockid, block_t* block)
|
||||||
|
@ -214,50 +222,29 @@ add_block_version(blockid_t blockid, block_t* block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count the number of block versions matching a given blockid
|
|
||||||
static size_t count_block_versions(blockid_t blockid)
|
|
||||||
{
|
|
||||||
size_t count = 0;
|
|
||||||
block_t *first_version = get_first_version(blockid.iseq, blockid.idx);
|
|
||||||
|
|
||||||
// For each version matching the blockid
|
|
||||||
for (block_t *version = first_version; version != NULL; version = version->next)
|
|
||||||
{
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve a basic block version for an (iseq, idx) tuple
|
// Retrieve a basic block version for an (iseq, idx) tuple
|
||||||
block_t* find_block_version(blockid_t blockid, const ctx_t* ctx)
|
block_t* find_block_version(blockid_t blockid, const ctx_t* ctx)
|
||||||
{
|
{
|
||||||
block_t *first_version = get_first_version(blockid.iseq, blockid.idx);
|
rb_ujit_block_array_t versions = get_version_array(iseq, block->blockid.idx);
|
||||||
|
|
||||||
// If there exists a version for this block id
|
|
||||||
if (!first_version) return NULL;
|
|
||||||
|
|
||||||
// Best match found
|
// Best match found
|
||||||
block_t* best_version = NULL;
|
block_t* best_version = NULL;
|
||||||
int best_diff = INT_MAX;
|
int best_diff = INT_MAX;
|
||||||
|
|
||||||
// For each version matching the blockid
|
// For each version matching the blockid
|
||||||
for (block_t* version = first_version; version != NULL; version = version->next)
|
block_t **element;
|
||||||
{
|
rb_darray_foreach(versions, idx, element) {
|
||||||
int diff = ctx_diff(ctx, &version->ctx);
|
block_t *version = *element;
|
||||||
|
int diff = ctx_diff(ctx, version->ctx);
|
||||||
|
|
||||||
if (diff < best_diff)
|
// Note that we always prefer the first matching
|
||||||
{
|
// version because of inline-cache chains
|
||||||
|
if (diff < best_diff) {
|
||||||
best_version = version;
|
best_version = version;
|
||||||
best_diff = diff;
|
best_diff = diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best_version == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return best_version;
|
return best_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +380,7 @@ uint8_t* branch_stub_hit(uint32_t branch_idx, uint32_t target_idx, rb_execution_
|
||||||
ctx_t generic_ctx = DEFAULT_CTX;
|
ctx_t generic_ctx = DEFAULT_CTX;
|
||||||
generic_ctx.stack_size = target_ctx->stack_size;
|
generic_ctx.stack_size = target_ctx->stack_size;
|
||||||
generic_ctx.sp_offset = target_ctx->sp_offset;
|
generic_ctx.sp_offset = target_ctx->sp_offset;
|
||||||
if (count_block_versions(target) >= MAX_VERSIONS - 1)
|
if (get_num_versions(target) >= MAX_VERSIONS - 1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "version limit hit in branch_stub_hit\n");
|
fprintf(stderr, "version limit hit in branch_stub_hit\n");
|
||||||
target_ctx = &generic_ctx;
|
target_ctx = &generic_ctx;
|
||||||
|
@ -559,7 +546,7 @@ void gen_direct_jump(
|
||||||
ctx_t generic_ctx = DEFAULT_CTX;
|
ctx_t generic_ctx = DEFAULT_CTX;
|
||||||
generic_ctx.stack_size = ctx->stack_size;
|
generic_ctx.stack_size = ctx->stack_size;
|
||||||
generic_ctx.sp_offset = ctx->sp_offset;
|
generic_ctx.sp_offset = ctx->sp_offset;
|
||||||
if (count_block_versions(target0) >= MAX_VERSIONS - 1)
|
if (get_num_versions(target0) >= MAX_VERSIONS - 1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "version limit hit in gen_direct_jump\n");
|
fprintf(stderr, "version limit hit in gen_direct_jump\n");
|
||||||
ctx = &generic_ctx;
|
ctx = &generic_ctx;
|
||||||
|
@ -658,6 +645,27 @@ ujit_free_block(block_t *block)
|
||||||
free(block);
|
free(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove a block version without reordering the version array
|
||||||
|
static bool
|
||||||
|
block_array_remove(rb_ujit_block_array_t block_array, block_t *block)
|
||||||
|
{
|
||||||
|
block_t **element;
|
||||||
|
bool shifting = false;
|
||||||
|
rb_darray_foreach(block_array, idx, element) {
|
||||||
|
if (*element == block) {
|
||||||
|
shifting = true;
|
||||||
|
}
|
||||||
|
else if (shifting) {
|
||||||
|
rb_darray_set(block_array, idx - 1, *element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shifting) {
|
||||||
|
rb_darray_pop(block_array);
|
||||||
|
}
|
||||||
|
return shifting;
|
||||||
|
}
|
||||||
|
|
||||||
// Invalidate one specific block version
|
// Invalidate one specific block version
|
||||||
void
|
void
|
||||||
invalidate_block_version(block_t* block)
|
invalidate_block_version(block_t* block)
|
||||||
|
@ -667,24 +675,12 @@ invalidate_block_version(block_t* block)
|
||||||
// fprintf(stderr, "invalidating block (%p, %d)\n", block->blockid.iseq, block->blockid.idx);
|
// fprintf(stderr, "invalidating block (%p, %d)\n", block->blockid.iseq, block->blockid.idx);
|
||||||
// fprintf(stderr, "block=%p\n", block);
|
// fprintf(stderr, "block=%p\n", block);
|
||||||
|
|
||||||
block_t *first_block = get_first_version(iseq, block->blockid.idx);
|
// Remove this block from the version array
|
||||||
RUBY_ASSERT(first_block != NULL);
|
rb_ujit_block_array_t versions = get_version_array(iseq, block->blockid.idx);
|
||||||
|
RUBY_ASSERT(rb_darray_size(versions) > 0);
|
||||||
// Remove references to this block
|
RB_UNUSED_VAR(bool removed);
|
||||||
if (first_block == block) {
|
removed = block_array_remove(versions, block);
|
||||||
// Make the next block the new first version
|
RUBY_ASSERT(removed);
|
||||||
rb_darray_set(iseq->body->ujit_blocks, block->blockid.idx, block->next);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bool deleted = false;
|
|
||||||
for (block_t* cur = first_block; cur != NULL; cur = cur->next) {
|
|
||||||
if (cur->next == block) {
|
|
||||||
cur->next = cur->next->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RUBY_ASSERT(deleted);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a pointer to the generated code for this block
|
// Get a pointer to the generated code for this block
|
||||||
uint8_t* code_ptr = cb_get_ptr(cb, block->start_pos);
|
uint8_t* code_ptr = cb_get_ptr(cb, block->start_pos);
|
||||||
|
|
|
@ -121,12 +121,6 @@ typedef struct ujit_block_version
|
||||||
// Offsets for GC managed objects in the mainline code block
|
// Offsets for GC managed objects in the mainline code block
|
||||||
int32_array_t gc_object_offsets;
|
int32_array_t gc_object_offsets;
|
||||||
|
|
||||||
// Next block version for this blockid (singly-linked list)
|
|
||||||
struct ujit_block_version *next;
|
|
||||||
|
|
||||||
// Offsets for GC managed objects in the mainline code block
|
|
||||||
offset_array_t gc_object_offsets;
|
|
||||||
|
|
||||||
// GC managed objects that this block depend on
|
// GC managed objects that this block depend on
|
||||||
struct {
|
struct {
|
||||||
VALUE cc;
|
VALUE cc;
|
||||||
|
|
15
ujit_iface.c
15
ujit_iface.c
|
@ -379,12 +379,13 @@ ujit_blocks_for(VALUE mod, VALUE rb_iseq)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rb_iseq_t *iseq = rb_iseqw_to_iseq(rb_iseq);
|
const rb_iseq_t *iseq = rb_iseqw_to_iseq(rb_iseq);
|
||||||
block_t **element;
|
|
||||||
VALUE all_versions = rb_ary_new();
|
|
||||||
|
|
||||||
rb_darray_foreach(iseq->body->ujit_blocks, idx, element) {
|
VALUE all_versions = rb_ary_new();
|
||||||
for (block_t *version = *element; version; version = version->next) {
|
rb_ujit_block_array_t *versions;
|
||||||
VALUE rb_block = TypedData_Wrap_Struct(cUjitBlock, &ujit_block_type, version);
|
rb_darray_foreach(iseq->body->ujit_blocks, idx, versions) {
|
||||||
|
block_t **block;
|
||||||
|
rb_darray_foreach(*versions, idx, block) {
|
||||||
|
VALUE rb_block = TypedData_Wrap_Struct(cUjitBlock, &ujit_block_type, *block);
|
||||||
rb_ary_push(all_versions, rb_block);
|
rb_ary_push(all_versions, rb_block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -679,9 +680,11 @@ rb_ujit_iseq_mark(const struct rb_iseq_constant_body *body)
|
||||||
{
|
{
|
||||||
block_t **element;
|
block_t **element;
|
||||||
rb_darray_foreach(body->ujit_blocks, idx, element) {
|
rb_darray_foreach(body->ujit_blocks, idx, element) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (block_t *block = *element; block; block = block->next) {
|
for (block_t *block = *element; block; block = block->next) {
|
||||||
rb_gc_mark_movable((VALUE)block->blockid.iseq);
|
rb_gc_mark_movable((VALUE)block->blockid.iseq);
|
||||||
|
|
||||||
rb_gc_mark_movable(block->dependencies.cc);
|
rb_gc_mark_movable(block->dependencies.cc);
|
||||||
rb_gc_mark_movable(block->dependencies.cme);
|
rb_gc_mark_movable(block->dependencies.cme);
|
||||||
rb_gc_mark_movable(block->dependencies.iseq);
|
rb_gc_mark_movable(block->dependencies.iseq);
|
||||||
|
|
|
@ -312,7 +312,9 @@ pathobj_realpath(VALUE pathobj)
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
struct rb_mjit_unit;
|
struct rb_mjit_unit;
|
||||||
|
|
||||||
|
// List of YJIT block versions
|
||||||
typedef rb_darray(struct ujit_block_version *) rb_ujit_block_array_t;
|
typedef rb_darray(struct ujit_block_version *) rb_ujit_block_array_t;
|
||||||
|
typedef rb_darray(rb_ujit_block_array_t) rb_ujit_block_array_array_t;
|
||||||
|
|
||||||
struct rb_iseq_constant_body {
|
struct rb_iseq_constant_body {
|
||||||
enum iseq_type {
|
enum iseq_type {
|
||||||
|
@ -453,7 +455,7 @@ struct rb_iseq_constant_body {
|
||||||
struct rb_mjit_unit *jit_unit;
|
struct rb_mjit_unit *jit_unit;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rb_ujit_block_array_t ujit_blocks; // empty, or has a size equal to iseq_size
|
rb_ujit_block_array_array_t ujit_blocks; // empty, or has a size equal to iseq_size
|
||||||
};
|
};
|
||||||
|
|
||||||
/* T_IMEMO/iseq */
|
/* T_IMEMO/iseq */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче