Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 36 additions & 8 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -889,19 +889,43 @@ rb_iseq_original_iseq(const rb_iseq_t *iseq) /* cold path */
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
{
unsigned int i;
unsigned int pc = 0;

for (i = 0; i < iseq->body->iseq_size; /* */ ) {
const void *addr = (const void *)original_code[i];
const int insn = rb_vm_insn_addr2insn(addr);
RUBY_ASSERT(iseq->body->original_insns.insns);

original_code[i] = insn;
i += insn_len(insn);
for (i = 0; i < iseq->body->original_insns.size; i++) {
const int insn = iseq->body->original_insns.insns[i];
original_code[pc] = insn;
pc += insn_len(insn);
}

RUBY_ASSERT(pc == iseq->body->iseq_size);
}
#endif
return original_code;
}

static void
record_original_instructions(rb_iseq_t *iseq)
{
unsigned int code_index = 0;
unsigned int insn_index = 0;
uint8_t *insns = ALLOC_N(uint8_t, iseq->body->iseq_size);
VALUE *encoded = iseq->body->iseq_encoded;

while (code_index < iseq->body->iseq_size) {
VALUE insn = encoded[code_index];
insns[insn_index++] = insn;
code_index += insn_len(insn);
}
RUBY_ASSERT(code_index == iseq->body->iseq_size);

REALLOC_N(insns, uint8_t, insn_index);

iseq->body->original_insns.insns = insns;
iseq->body->original_insns.size = insn_index;
}

/*********************************************/
/* definition of data structure for compiler */
/*********************************************/
Expand Down Expand Up @@ -1384,13 +1408,13 @@ update_catch_except_flags(struct rb_iseq_constant_body *body)
/* This assumes that a block has parent_iseq which may catch an exception from the block, and that
BREAK/NEXT/REDO catch table entries are used only when `throw` insn is used in the block. */
pos = 0;
while (pos < body->iseq_size) {
insn = rb_vm_insn_decode(body->iseq_encoded[pos]);
while (pos < body->original_insns.size) {
insn = body->original_insns.insns[pos];
if (insn == BIN(throw)) {
set_catch_except_p(body);
break;
}
pos += insn_len(insn);
pos++;
}

if (ct == NULL)
Expand Down Expand Up @@ -1495,6 +1519,9 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
debugs("[compile step 4.3 (set_optargs_table)] \n");
if (!iseq_set_optargs_table(iseq)) return COMPILE_NG;

debugs("[compile step 4.4 (record_original_instructions)] \n");
record_original_instructions(iseq);

debugs("[compile step 5 (iseq_translate_threaded_code)] \n");
if (!rb_iseq_translate_threaded_code(iseq)) return COMPILE_NG;

Expand Down Expand Up @@ -11914,6 +11941,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
rb_iseq_insns_info_encode_positions(iseq);
#endif

record_original_instructions(iseq);
rb_iseq_translate_threaded_code(iseq);

#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
Expand Down
48 changes: 14 additions & 34 deletions iseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,32 +143,16 @@ rb_iseq_free(const rb_iseq_t *iseq)
RUBY_FREE_LEAVE("iseq");
}

#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
static VALUE
rb_vm_insn_addr2insn2(const void *addr)
{
return (VALUE)rb_vm_insn_addr2insn(addr);
}
#endif

static VALUE
rb_vm_insn_null_translator(const void *addr)
{
return (VALUE)addr;
}

typedef VALUE iseq_value_itr_t(void *ctx, VALUE obj);
typedef VALUE rb_vm_insns_translator_t(const void *addr);

static int
iseq_extract_values(VALUE *code, size_t pos, iseq_value_itr_t * func, void *data, rb_vm_insns_translator_t * translator)
static void
iseq_extract_values(VALUE insn, VALUE *code, size_t pos, iseq_value_itr_t * func, void *data)
{
VALUE insn = translator((void *)code[pos]);
int len = insn_len(insn);
int op_no;
const char *types = insn_op_types(insn);

for (op_no = 0; types[op_no]; op_no++) {
for (op_no = 0; op_no + 1 < len; op_no++) {
char type = types[op_no];
switch (type) {
case TS_CDHASH:
Expand Down Expand Up @@ -225,28 +209,22 @@ iseq_extract_values(VALUE *code, size_t pos, iseq_value_itr_t * func, void *data
break;
}
}

return len;
}

static void
rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data)
{
unsigned int size;
VALUE *code;
size_t n;
rb_vm_insns_translator_t *const translator =
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
(FL_TEST((VALUE)iseq, ISEQ_TRANSLATED)) ? rb_vm_insn_addr2insn2 :
#endif
rb_vm_insn_null_translator;
const struct rb_iseq_constant_body *const body = iseq->body;

size = body->iseq_size;
code = body->iseq_encoded;
VALUE *code = body->iseq_encoded;
size_t pc = 0;

for (n = 0; n < size;) {
n += iseq_extract_values(code, n, func, data, translator);
size_t size = body->original_insns.size;
for (size_t n = 0; n < size; n++) {
VALUE insn = body->original_insns.insns[n];
iseq_extract_values(insn, code, pc, func, data);

pc += insn_len(insn);
}
}

Expand Down Expand Up @@ -293,7 +271,9 @@ rb_iseq_update_references(rb_iseq_t *iseq)
size_t n = 0;
const unsigned int size = body->iseq_size;
while (n < size) {
n += iseq_extract_values(original_iseq, n, update_each_insn_value, NULL, rb_vm_insn_null_translator);
VALUE insn = original_iseq[n];
iseq_extract_values(insn, original_iseq, n, update_each_insn_value, NULL);
n += insn_len(insn);
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions vm_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,11 @@ struct rb_iseq_constant_body {
#endif
} insns_info;

struct {
uint8_t *insns;
unsigned int size;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's different between original_insns.size and iseq_size?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

original_insns.size is the count of instructions in this iseq. iseq_size is the count of instructions + the total count of operands.

} original_insns;

const ID *local_table; /* must free */

/* catch table */
Expand Down