diff --git a/ChangeLog b/ChangeLog index 53b777f3b7..4cb65763cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +Mon Jul 14 16:04:41 2014 Eric Wong + + * iseq.h (struct iseq_catch_table): new flexible array struct + (iseq_catch_table_bytes): allocated size function + * vm_core.h (struct rb_iseq_struct): update catch_table member + * compile.c (iseq_set_exception_table): update for struct changes + * iseq.c (iseq_free): ditto + * iseq.c (iseq_memsize): ditto + * iseq.c (rb_iseq_disasm): ditto + * iseq.c (iseq_data_to_ary): ditto + * iseq.c (rb_iseq_build_for_ruby2cext): ditto (untested) + * vm.c (vm_exec): ditto + * vm_core.h (struct rb_iseq_struct): ditto + * vm_insnhelper.c (vm_throw): ditto + Sun Jul 13 17:49:52 2014 SHIBATA Hiroshi * ext/openssl/ossl_cipher.c: Fix call to ciphers class method and diff --git a/compile.c b/compile.c index 6c71a8586f..637e112b05 100644 --- a/compile.c +++ b/compile.c @@ -1681,12 +1681,15 @@ iseq_set_exception_table(rb_iseq_t *iseq) tlen = (int)RARRAY_LEN(iseq->compile_data->catch_table_ary); tptr = RARRAY_CONST_PTR(iseq->compile_data->catch_table_ary); - iseq->catch_table = tlen ? ALLOC_N(struct iseq_catch_table_entry, tlen) : 0; - iseq->catch_table_size = tlen; + iseq->catch_table = 0; + if (tlen > 0) { + iseq->catch_table = xmalloc(iseq_catch_table_bytes(tlen)); + iseq->catch_table->size = tlen; + } - for (i = 0; i < tlen; i++) { + if (iseq->catch_table) for (i = 0; i < iseq->catch_table->size; i++) { ptr = RARRAY_CONST_PTR(tptr[i]); - entry = &iseq->catch_table[i]; + entry = &iseq->catch_table->entries[i]; entry->type = (enum catch_type)(ptr[0] & 0xffff); entry->start = label_get_position((LABEL *)(ptr[1] & ~1)); entry->end = label_get_position((LABEL *)(ptr[2] & ~1)); diff --git a/iseq.c b/iseq.c index 77507d83cf..a7e40ea86c 100644 --- a/iseq.c +++ b/iseq.c @@ -141,7 +141,9 @@ iseq_memsize(const void *ptr) size += iseq->iseq_size * sizeof(VALUE); size += iseq->line_info_size * sizeof(struct iseq_line_info_entry); size += iseq->local_table_size * sizeof(ID); - size += iseq->catch_table_size * sizeof(struct iseq_catch_table_entry); + if (iseq->catch_table) { + size += iseq_catch_table_bytes(iseq->catch_table->size); + } size += iseq->arg_opts * sizeof(VALUE); size += iseq->is_size * sizeof(union iseq_inline_storage_entry); size += iseq->callinfo_size * sizeof(rb_call_info_t); @@ -1400,11 +1402,11 @@ rb_iseq_disasm(VALUE self) rb_str_cat2(str, "\n"); /* show catch table information */ - if (iseqdat->catch_table_size != 0) { + if (iseqdat->catch_table) { rb_str_cat2(str, "== catch table\n"); } - for (i = 0; i < iseqdat->catch_table_size; i++) { - struct iseq_catch_table_entry *entry = &iseqdat->catch_table[i]; + if (iseqdat->catch_table) for (i = 0; i < iseqdat->catch_table->size; i++) { + struct iseq_catch_table_entry *entry = &iseqdat->catch_table->entries[i]; rb_str_catf(str, "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n", catch_type((int)entry->type), (int)entry->start, @@ -1413,7 +1415,7 @@ rb_iseq_disasm(VALUE self) rb_str_concat(str, rb_iseq_disasm(entry->iseq)); } } - if (iseqdat->catch_table_size != 0) { + if (iseqdat->catch_table) { rb_str_cat2(str, "|-------------------------------------" "-----------------------------------\n"); } @@ -1845,9 +1847,9 @@ iseq_data_to_ary(rb_iseq_t *iseq) nbody = body; /* exception */ - for (i=0; icatch_table_size; i++) { + if (iseq->catch_table) for (i=0; icatch_table->size; i++) { VALUE ary = rb_ary_new(); - struct iseq_catch_table_entry *entry = &iseq->catch_table[i]; + struct iseq_catch_table_entry *entry = &iseq->catch_table->entries[i]; rb_ary_push(ary, exception_type2symbol(entry->type)); if (entry->iseq) { rb_iseq_t *eiseq; @@ -2117,8 +2119,14 @@ rb_iseq_build_for_ruby2cext( ALLOC_AND_COPY(iseq->line_info_table, line_info_table, struct iseq_line_info_entry, iseq->line_info_size); - ALLOC_AND_COPY(iseq->catch_table, catch_table, - struct iseq_catch_table_entry, iseq->catch_table_size); + /* + * FIXME: probably broken, but this function is probably unused + * and should be removed + */ + if (iseq->catch_table) { + MEMCPY(&iseq->catch_table->entries, catch_table, + struct iseq_catch_table_entry, iseq->catch_table->size); + } ALLOC_AND_COPY(iseq->arg_opt_table, arg_opt_table, VALUE, iseq->arg_opts); diff --git a/iseq.h b/iseq.h index 5487d86f7b..be7d8efd9d 100644 --- a/iseq.h +++ b/iseq.h @@ -68,6 +68,18 @@ struct iseq_catch_table_entry { unsigned long sp; }; +PACKED_STRUCT_UNALIGNED(struct iseq_catch_table { + int size; + struct iseq_catch_table_entry entries[1]; /* flexible array */ +}); + +static inline int +iseq_catch_table_bytes(int n) +{ + return sizeof(struct iseq_catch_table) + + (n - 1) * sizeof(struct iseq_catch_table_entry); +} + #define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE (512) struct iseq_compile_data_storage { diff --git a/vm.c b/vm.c index 0fd5e3fd9c..c33f16a0bd 100644 --- a/vm.c +++ b/vm.c @@ -1383,6 +1383,7 @@ vm_exec(rb_thread_t *th) else { int i; struct iseq_catch_table_entry *entry; + struct iseq_catch_table *ct; unsigned long epc, cont_pc, cont_sp; VALUE catch_iseqval; rb_control_frame_t *cfp; @@ -1417,8 +1418,9 @@ vm_exec(rb_thread_t *th) SET_THROWOBJ_STATE(err, state = TAG_BREAK); } else { - for (i = 0; i < cfp->iseq->catch_table_size; i++) { - entry = &cfp->iseq->catch_table[i]; + ct = cfp->iseq->catch_table; + if (ct) for (i = 0; i < ct->size; i++) { + entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_ENSURE) { catch_iseqval = entry->iseq; @@ -1458,8 +1460,9 @@ vm_exec(rb_thread_t *th) } if (state == TAG_RAISE) { - for (i = 0; i < cfp->iseq->catch_table_size; i++) { - entry = &cfp->iseq->catch_table[i]; + ct = cfp->iseq->catch_table; + if (ct) for (i = 0; i < ct->size; i++) { + entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_RESCUE || @@ -1473,8 +1476,9 @@ vm_exec(rb_thread_t *th) } } else if (state == TAG_RETRY) { - for (i = 0; i < cfp->iseq->catch_table_size; i++) { - entry = &cfp->iseq->catch_table[i]; + ct = cfp->iseq->catch_table; + if (ct) for (i = 0; i < ct->size; i++) { + entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_ENSURE) { @@ -1499,8 +1503,9 @@ vm_exec(rb_thread_t *th) type = CATCH_TYPE_BREAK; search_restart_point: - for (i = 0; i < cfp->iseq->catch_table_size; i++) { - entry = &cfp->iseq->catch_table[i]; + ct = cfp->iseq->catch_table; + if (ct) for (i = 0; i < ct->size; i++) { + entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_ENSURE) { @@ -1536,8 +1541,9 @@ vm_exec(rb_thread_t *th) goto search_restart_point; } else { - for (i = 0; i < cfp->iseq->catch_table_size; i++) { - entry = &cfp->iseq->catch_table[i]; + ct = cfp->iseq->catch_table; + if (ct) for (i = 0; i < ct->size; i++) { + entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_ENSURE) { diff --git a/vm_core.h b/vm_core.h index 8a8ceeb981..510a4ad4cd 100644 --- a/vm_core.h +++ b/vm_core.h @@ -274,8 +274,7 @@ struct rb_iseq_struct { ID *arg_keyword_table; /* catch table */ - struct iseq_catch_table_entry *catch_table; - int catch_table_size; + struct iseq_catch_table *catch_table; /* for child iseq */ struct rb_iseq_struct *parent_iseq; diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 9d77b01a0f..0f9eab1610 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -646,10 +646,12 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, if (cfp->ep == ep) { VALUE epc = cfp->pc - cfp->iseq->iseq_encoded; rb_iseq_t *iseq = cfp->iseq; + struct iseq_catch_table *ct = iseq->catch_table; + struct iseq_catch_table_entry *entry; int i; - for (i=0; icatch_table_size; i++) { - struct iseq_catch_table_entry *entry = &iseq->catch_table[i]; + for (i=0; isize; i++) { + entry = &ct->entries[i]; if (entry->type == CATCH_TYPE_BREAK && entry->start < epc && entry->end >= epc) {