ruby-changes:68823
From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:14:05 +0900 (JST)
Subject: [ruby-changes:68823] 824fea684f (master): Thread EC through jit state. Add codegen status enum.
https://git.ruby-lang.org/ruby.git/commit/?id=824fea684f From 824fea684f8346386db0391fb8575ced07ae01d6 Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...> Date: Mon, 1 Mar 2021 20:43:58 -0500 Subject: Thread EC through jit state. Add codegen status enum. --- mjit.h | 2 +- ujit.h | 2 +- ujit_codegen.c | 301 ++++++++++++++++++++++++++------------------------------- ujit_codegen.h | 28 +++--- ujit_core.c | 20 ++-- ujit_core.h | 4 +- ujit_iface.c | 15 +-- 7 files changed, 169 insertions(+), 203 deletions(-) diff --git a/mjit.h b/mjit.h index 83f5cb919a..48596980b4 100644 --- a/mjit.h +++ b/mjit.h @@ -151,7 +151,7 @@ mjit_exec(rb_execution_context_t *ec) https://github.com/ruby/ruby/blob/trunk/mjit.h#L151 #ifndef MJIT_HEADER if (rb_ujit_enabled_p() && !mjit_call_p && body->total_calls == rb_ujit_call_threshold()) { - rb_ujit_compile_iseq(iseq); + rb_ujit_compile_iseq(iseq, ec); return Qundef; } #endif diff --git a/ujit.h b/ujit.h index f3c2bffae6..e7ff96e64d 100644 --- a/ujit.h +++ b/ujit.h @@ -49,7 +49,7 @@ RUBY_SYMBOL_EXPORT_END https://github.com/ruby/ruby/blob/trunk/ujit.h#L49 void rb_ujit_collect_vm_usage_insn(int insn); void rb_ujit_method_lookup_change(VALUE cme_or_cc); -void rb_ujit_compile_iseq(const rb_iseq_t *iseq); +void rb_ujit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec); void rb_ujit_init(struct rb_ujit_options *options); void rb_ujit_bop_redefined(VALUE klass, const rb_method_entry_t *me, enum ruby_basic_operators bop); void rb_ujit_constant_state_changed(void); diff --git a/ujit_codegen.c b/ujit_codegen.c index 78806e0f5a..e67d15c96b 100644 --- a/ujit_codegen.c +++ b/ujit_codegen.c @@ -205,7 +205,7 @@ ujit_check_ints(codeblock_t* cb, uint8_t* side_exit) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L205 Compile a sequence of bytecode instructions for a given basic block version */ void -ujit_gen_block(ctx_t* ctx, block_t* block) +ujit_gen_block(ctx_t* ctx, block_t* block, rb_execution_context_t* ec) { RUBY_ASSERT(cb != NULL); RUBY_ASSERT(block != NULL); @@ -229,18 +229,17 @@ ujit_gen_block(ctx_t* ctx, block_t* block) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L229 block, block->blockid.iseq, 0, - 0 + 0, + ec }; - // Last operation that was successfully compiled - opdesc_t* p_last_op = NULL; - // Mark the start position of the block block->start_pos = cb->write_pos; // For each instruction to compile for (;;) { // Set the current instruction + RUBY_ASSERT(insn_idx < iseq->body->iseq_size); jit.insn_idx = insn_idx; jit.pc = &encoded[insn_idx]; @@ -248,8 +247,11 @@ ujit_gen_block(ctx_t* ctx, block_t* block) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L247 int opcode = jit_get_opcode(&jit); // Lookup the codegen function for this instruction - st_data_t st_op_desc; - if (!rb_st_lookup(gen_fns, opcode, &st_op_desc)) { + codegen_fn gen_fn; + if (!rb_st_lookup(gen_fns, opcode, (st_data_t*)&gen_fn)) { + // If we reach an unknown instruction, + // exit to the interpreter and stop compiling + ujit_gen_exit(&jit, ctx, cb, &encoded[insn_idx]); break; } @@ -266,30 +268,24 @@ ujit_gen_block(ctx_t* ctx, block_t* block) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L268 //print_str(cb, insn_name(opcode)); // Call the code generation function - opdesc_t* p_desc = (opdesc_t*)st_op_desc; - bool success = p_desc->gen_fn(&jit, ctx); + codegen_status_t status = gen_fn(&jit, ctx); - // If we can't compile this instruction, stop - if (!success) { + // If we can't compile this instruction + // exit to the interpreter and stop compiling + if (status == UJIT_CANT_COMPILE) { + ujit_gen_exit(&jit, ctx, cb, &encoded[insn_idx]); break; } - // Move to the next instruction - p_last_op = p_desc; + // Move to the next instruction to compile insn_idx += insn_len(opcode); - // If this instruction terminates this block - if (p_desc->is_branch) { + // If the instruction terminates this block + if (status == UJIT_END_BLOCK) { break; } } - // If the last instruction compiled did not terminate the block - // Generate code to exit to the interpreter - if (!p_last_op || !p_last_op->is_branch) { - ujit_gen_exit(&jit, ctx, cb, &encoded[insn_idx]); - } - // Mark the end position of the block block->end_pos = cb->write_pos; @@ -309,7 +305,7 @@ ujit_gen_block(ctx_t* ctx, block_t* block) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L305 } } -static bool +static codegen_status_t gen_dup(jitstate_t* jit, ctx_t* ctx) { // Get the top value and its type @@ -321,34 +317,34 @@ gen_dup(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L317 mov(cb, REG0, dup_val); mov(cb, loc0, REG0); - return true; + return UJIT_KEEP_COMPILING; } -static bool +static codegen_status_t gen_nop(jitstate_t* jit, ctx_t* ctx) { // Do nothing - return true; + return UJIT_KEEP_COMPILING; } -static bool +static codegen_status_t gen_pop(jitstate_t* jit, ctx_t* ctx) { // Decrement SP ctx_stack_pop(ctx, 1); - return true; + return UJIT_KEEP_COMPILING; } -static bool +static codegen_status_t gen_putnil(jitstate_t* jit, ctx_t* ctx) { // Write constant at SP x86opnd_t stack_top = ctx_stack_push(ctx, T_NIL); mov(cb, stack_top, imm_opnd(Qnil)); - return true; + return UJIT_KEEP_COMPILING; } -static bool +static codegen_status_t gen_putobject(jitstate_t* jit, ctx_t* ctx) { VALUE arg = jit_get_arg(jit, 0); @@ -389,10 +385,10 @@ gen_putobject(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L385 mov(cb, stack_top, RAX); } - return true; + return UJIT_KEEP_COMPILING; } -static bool +static codegen_status_t gen_putobject_int2fix(jitstate_t* jit, ctx_t* ctx) { int opcode = jit_get_opcode(jit); @@ -402,10 +398,10 @@ gen_putobject_int2fix(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L398 x86opnd_t stack_top = ctx_stack_push(ctx, T_FIXNUM); mov(cb, stack_top, imm_opnd(INT2FIX(cst_val))); - return true; + return UJIT_KEEP_COMPILING; } -static bool +static codegen_status_t gen_putself(jitstate_t* jit, ctx_t* ctx) { // Load self from CFP @@ -415,10 +411,10 @@ gen_putself(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L411 x86opnd_t stack_top = ctx_stack_push(ctx, T_NONE); mov(cb, stack_top, RAX); - return true; + return UJIT_KEEP_COMPILING; } -static bool +static codegen_status_t gen_getlocal_wc0(jitstate_t* jit, ctx_t* ctx) { // Load environment pointer EP from CFP @@ -435,10 +431,10 @@ gen_getlocal_wc0(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L431 x86opnd_t stack_top = ctx_stack_push(ctx, T_NONE); mov(cb, stack_top, REG0); - return true; + return UJIT_KEEP_COMPILING; } -static bool +static codegen_status_t gen_getlocal_wc1(jitstate_t* jit, ctx_t* ctx) { //fprintf(stderr, "gen_getlocal_wc1\n"); @@ -462,10 +458,10 @@ gen_getlocal_wc1(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L458 x86opnd_t stack_top = ctx_stack_push(ctx, T_NONE); mov(cb, stack_top, REG0); - return true; + return UJIT_KEEP_COMPILING; } -static bool +static codegen_status_t gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx) { /* @@ -503,7 +499,7 @@ gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L499 const int32_t offs = -8 * local_idx; mov(cb, mem_opnd(64, REG0, offs), REG1); - return true; + return UJIT_KEEP_COMPILING; } // Check that `self` is a pointer to an object on the GC heap @@ -522,24 +518,22 @@ guard_self_is_object(codeblock_t *cb, x86opnd_t self_opnd, uint8_t *side_exit, c https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L518 } } -static bool +static codegen_status_t gen_getinstancevariable(jitstate_t* jit, ctx_t* ctx) { IVC ic = (IVC)jit_get_arg(jit, 1); // Check that the inline cache has been set, slot index is known - if (!ic->entry) - { - return false; + if (!ic->entry) { + return UJIT_CANT_COMPILE; } // 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. // Eventually, we can encode whether an object is T_OBJECT or not // inside object shapes. - if (rb_get_alloc_func(ic->entry->class_value) != rb_class_allocate_instance) - { - return false; + if (rb_get_alloc_func(ic->entry->class_value) != rb_class_allocate_instance) { + return UJIT_CANT_COMPILE; } uint32_t ivar_index = ic->entry->index; @@ -566,8 +560,7 @@ gen_getinstancevariable(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L560 jnz_ptr(cb, side_exit); // check that the extended table is big enough - if (ivar_index >= ROBJECT_EMBED_LEN_MAX + 1) - { + if (ivar_index >= ROBJECT_EMBED_LEN_MAX + 1) { // Check that the slot is inside the extended table (num_slots > index) x86opnd_t num_slots = mem_opnd(32, REG0, offsetof(struct RObject, as.heap.numiv)); cmp(cb, num_slots, imm_opnd(ivar_index)); @@ -590,27 +583,25 @@ gen_getinstancevariable(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/