mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
compile: translate iseq in-place
running "ruby -rpp -e 'pp GC.stat'", a reduction in malloc usage is shown: before: :malloc_increase=>118784, :oldmalloc_increase=>1178736, after: :malloc_increase=>99832, :oldmalloc_increase=>1031976, For "ruby -e exit", valgrind reports over 300K reduction in overall allocations (and unnecessary memory copies). before: total heap usage: 49,622 allocs, 20,492 frees, 8,697,493 bytes allocated after: total heap usage: 48,935 allocs, 19,805 frees, 8,373,773 bytes allocated (numbers from x86-64) v2 changes based on ko1 recommendations [ruby-core:64883]: - squashed in-place direct thread translation to avoid alloc+copy - renamed rb_iseq_untranslate_threaded_code to rb_iseq_original_iseq, cache new iseq->iseq_original field. * compile.c (rb_iseq_translate_threaded_code): modify in-place w/o copy (rb_vm_addr2insn): new function for debug (rb_iseq_original_iseq): ditto (iseq_set_sequence): assign iseq_encoded directly [Feature #10185] * vm_core (rb_iseq_t): move original ->iseq to bottom * iseq.c (iseq_free, iseq_free): adjust for new layout (rb_iseq_disasm): use original iseq for dump (iseq_data_to_ary): ditto (rb_iseq_line_trace_each): ditto (rb_iseq_build_for_ruby2cext): use iseq_encoded directly * vm_dump.c (rb_vmdebug_debug_print_pre): use original iseq git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47508 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
fd31eb3f5c
commit
ea4c97904e
6 changed files with 90 additions and 30 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
||||||
|
Wed Sep 10 15:07:35 2014 Eric Wong <e@80x24.org>
|
||||||
|
|
||||||
|
* compile.c (rb_iseq_translate_threaded_code):
|
||||||
|
modify in-place w/o copy
|
||||||
|
(rb_vm_addr2insn): new function for debug
|
||||||
|
(rb_iseq_original_iseq): ditto
|
||||||
|
(iseq_set_sequence): assign iseq_encoded directly
|
||||||
|
[Feature #10185]
|
||||||
|
|
||||||
|
* vm_core (rb_iseq_t): move original ->iseq to bottom
|
||||||
|
|
||||||
|
* iseq.c (iseq_free, iseq_free): adjust for new layout
|
||||||
|
(rb_iseq_disasm): use original iseq for dump
|
||||||
|
(iseq_data_to_ary): ditto
|
||||||
|
(rb_iseq_line_trace_each): ditto
|
||||||
|
(rb_iseq_build_for_ruby2cext): use iseq_encoded directly
|
||||||
|
|
||||||
|
* vm_dump.c (rb_vmdebug_debug_print_pre): use original iseq
|
||||||
|
|
||||||
Wed Sep 10 15:00:11 2014 Eric Wong <e@80x24.org>
|
Wed Sep 10 15:00:11 2014 Eric Wong <e@80x24.org>
|
||||||
|
|
||||||
* time.c (time_mark): remove NULL check
|
* time.c (time_mark): remove NULL check
|
||||||
|
|
47
compile.c
47
compile.c
|
@ -569,21 +569,56 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
|
||||||
const void * const *table = rb_vm_get_insns_address_table();
|
const void * const *table = rb_vm_get_insns_address_table();
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
iseq->iseq_encoded = ALLOC_N(VALUE, iseq->iseq_size);
|
|
||||||
MEMCPY(iseq->iseq_encoded, iseq->iseq, VALUE, iseq->iseq_size);
|
|
||||||
|
|
||||||
for (i = 0; i < iseq->iseq_size; /* */ ) {
|
for (i = 0; i < iseq->iseq_size; /* */ ) {
|
||||||
int insn = (int)iseq->iseq_encoded[i];
|
int insn = (int)iseq->iseq_encoded[i];
|
||||||
int len = insn_len(insn);
|
int len = insn_len(insn);
|
||||||
iseq->iseq_encoded[i] = (VALUE)table[insn];
|
iseq->iseq_encoded[i] = (VALUE)table[insn];
|
||||||
i += len;
|
i += len;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
iseq->iseq_encoded = iseq->iseq;
|
|
||||||
#endif
|
#endif
|
||||||
return COMPILE_OK;
|
return COMPILE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
|
||||||
|
static int
|
||||||
|
rb_vm_addr2insn(const void *addr) /* cold path */
|
||||||
|
{
|
||||||
|
int insn;
|
||||||
|
const void * const *table = rb_vm_get_insns_address_table();
|
||||||
|
|
||||||
|
for (insn = 0; insn < VM_INSTRUCTION_SIZE; insn++) {
|
||||||
|
if (table[insn] == addr)
|
||||||
|
return insn;
|
||||||
|
}
|
||||||
|
rb_bug("rb_vm_addr2insn: invalid insn address: %p", addr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VALUE *
|
||||||
|
rb_iseq_original_iseq(rb_iseq_t *iseq) /* cold path */
|
||||||
|
{
|
||||||
|
if (iseq->iseq) return iseq->iseq;
|
||||||
|
|
||||||
|
iseq->iseq = ALLOC_N(VALUE, iseq->iseq_size);
|
||||||
|
|
||||||
|
MEMCPY(iseq->iseq, iseq->iseq_encoded, VALUE, iseq->iseq_size);
|
||||||
|
|
||||||
|
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < iseq->iseq_size; /* */ ) {
|
||||||
|
const void *addr = (const void *)iseq->iseq[i];
|
||||||
|
int insn = (VALUE)rb_vm_addr2insn(addr);
|
||||||
|
|
||||||
|
iseq->iseq[i] = insn;
|
||||||
|
i += insn_len(insn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return iseq->iseq;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************/
|
/*********************************************/
|
||||||
/* definition of data structure for compiler */
|
/* definition of data structure for compiler */
|
||||||
/*********************************************/
|
/*********************************************/
|
||||||
|
@ -1645,7 +1680,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
iseq->iseq = (void *)generated_iseq;
|
iseq->iseq_encoded = (void *)generated_iseq;
|
||||||
iseq->iseq_size = pos;
|
iseq->iseq_size = pos;
|
||||||
iseq->stack_max = stack_max;
|
iseq->stack_max = stack_max;
|
||||||
|
|
||||||
|
|
38
iseq.c
38
iseq.c
|
@ -75,11 +75,7 @@ iseq_free(void *ptr)
|
||||||
RSTRING_PTR(iseq->location.path));
|
RSTRING_PTR(iseq->location.path));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iseq->iseq != iseq->iseq_encoded) {
|
|
||||||
RUBY_FREE_UNLESS_NULL(iseq->iseq_encoded);
|
RUBY_FREE_UNLESS_NULL(iseq->iseq_encoded);
|
||||||
}
|
|
||||||
|
|
||||||
RUBY_FREE_UNLESS_NULL(iseq->iseq);
|
|
||||||
RUBY_FREE_UNLESS_NULL(iseq->line_info_table);
|
RUBY_FREE_UNLESS_NULL(iseq->line_info_table);
|
||||||
RUBY_FREE_UNLESS_NULL(iseq->local_table);
|
RUBY_FREE_UNLESS_NULL(iseq->local_table);
|
||||||
RUBY_FREE_UNLESS_NULL(iseq->is_entries);
|
RUBY_FREE_UNLESS_NULL(iseq->is_entries);
|
||||||
|
@ -88,6 +84,7 @@ iseq_free(void *ptr)
|
||||||
RUBY_FREE_UNLESS_NULL(iseq->arg_opt_table);
|
RUBY_FREE_UNLESS_NULL(iseq->arg_opt_table);
|
||||||
RUBY_FREE_UNLESS_NULL(iseq->arg_keyword_table);
|
RUBY_FREE_UNLESS_NULL(iseq->arg_keyword_table);
|
||||||
compile_data_free(iseq->compile_data);
|
compile_data_free(iseq->compile_data);
|
||||||
|
RUBY_FREE_UNLESS_NULL(iseq->iseq);
|
||||||
}
|
}
|
||||||
ruby_xfree(ptr);
|
ruby_xfree(ptr);
|
||||||
}
|
}
|
||||||
|
@ -134,10 +131,6 @@ iseq_memsize(const void *ptr)
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
iseq = ptr;
|
iseq = ptr;
|
||||||
if (!iseq->orig) {
|
if (!iseq->orig) {
|
||||||
if (iseq->iseq != iseq->iseq_encoded) {
|
|
||||||
size += iseq->iseq_size * sizeof(VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
size += iseq->iseq_size * sizeof(VALUE);
|
size += iseq->iseq_size * sizeof(VALUE);
|
||||||
size += iseq->line_info_size * sizeof(struct iseq_line_info_entry);
|
size += iseq->line_info_size * sizeof(struct iseq_line_info_entry);
|
||||||
size += iseq->local_table_size * sizeof(ID);
|
size += iseq->local_table_size * sizeof(ID);
|
||||||
|
@ -158,6 +151,9 @@ iseq_memsize(const void *ptr)
|
||||||
}
|
}
|
||||||
size += sizeof(struct iseq_compile_data);
|
size += sizeof(struct iseq_compile_data);
|
||||||
}
|
}
|
||||||
|
if (iseq->iseq) {
|
||||||
|
size += iseq->iseq_size * sizeof(VALUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1392,7 +1388,6 @@ rb_iseq_disasm(VALUE self)
|
||||||
|
|
||||||
rb_secure(1);
|
rb_secure(1);
|
||||||
|
|
||||||
iseq = iseqdat->iseq;
|
|
||||||
size = iseqdat->iseq_size;
|
size = iseqdat->iseq_size;
|
||||||
|
|
||||||
rb_str_cat2(str, "== disasm: ");
|
rb_str_cat2(str, "== disasm: ");
|
||||||
|
@ -1472,6 +1467,7 @@ rb_iseq_disasm(VALUE self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* show each line */
|
/* show each line */
|
||||||
|
iseq = rb_iseq_original_iseq(iseqdat);
|
||||||
for (n = 0; n < size;) {
|
for (n = 0; n < size;) {
|
||||||
n += rb_iseq_disasm_insn(str, iseq, n, iseqdat, child);
|
n += rb_iseq_disasm_insn(str, iseq, n, iseqdat, child);
|
||||||
}
|
}
|
||||||
|
@ -1658,7 +1654,7 @@ iseq_data_to_ary(rb_iseq_t *iseq)
|
||||||
size_t ti;
|
size_t ti;
|
||||||
unsigned int pos;
|
unsigned int pos;
|
||||||
unsigned int line = 0;
|
unsigned int line = 0;
|
||||||
VALUE *seq;
|
VALUE *seq, *iseq_original;
|
||||||
|
|
||||||
VALUE val = rb_ary_new();
|
VALUE val = rb_ary_new();
|
||||||
VALUE type; /* Symbol */
|
VALUE type; /* Symbol */
|
||||||
|
@ -1759,7 +1755,9 @@ iseq_data_to_ary(rb_iseq_t *iseq)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* body */
|
/* body */
|
||||||
for (seq = iseq->iseq; seq < iseq->iseq + iseq->iseq_size; ) {
|
iseq_original = rb_iseq_original_iseq(iseq);
|
||||||
|
|
||||||
|
for (seq = iseq_original; seq < iseq_original + iseq->iseq_size; ) {
|
||||||
VALUE insn = *seq++;
|
VALUE insn = *seq++;
|
||||||
int j, len = insn_len(insn);
|
int j, len = insn_len(insn);
|
||||||
VALUE *nseq = seq + len - 1;
|
VALUE *nseq = seq + len - 1;
|
||||||
|
@ -1769,7 +1767,7 @@ iseq_data_to_ary(rb_iseq_t *iseq)
|
||||||
for (j=0; j<len-1; j++, seq++) {
|
for (j=0; j<len-1; j++, seq++) {
|
||||||
switch (insn_op_type(insn, j)) {
|
switch (insn_op_type(insn, j)) {
|
||||||
case TS_OFFSET: {
|
case TS_OFFSET: {
|
||||||
unsigned long idx = nseq - iseq->iseq + *seq;
|
unsigned long idx = nseq - iseq_original + *seq;
|
||||||
rb_ary_push(ary, register_label(labels_table, idx));
|
rb_ary_push(ary, register_label(labels_table, idx));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1828,7 +1826,7 @@ iseq_data_to_ary(rb_iseq_t *iseq)
|
||||||
|
|
||||||
for (i=0; i<RARRAY_LEN(val); i+=2) {
|
for (i=0; i<RARRAY_LEN(val); i+=2) {
|
||||||
VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
|
VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
|
||||||
unsigned long idx = nseq - iseq->iseq + pos;
|
unsigned long idx = nseq - iseq_original + pos;
|
||||||
|
|
||||||
rb_ary_store(val, i+1,
|
rb_ary_store(val, i+1,
|
||||||
register_label(labels_table, idx));
|
register_label(labels_table, idx));
|
||||||
|
@ -2100,11 +2098,11 @@ rb_iseq_build_for_ruby2cext(
|
||||||
RB_OBJ_WRITE(iseq->self, &iseq->mark_ary, 0);
|
RB_OBJ_WRITE(iseq->self, &iseq->mark_ary, 0);
|
||||||
iseq->self = iseqval;
|
iseq->self = iseqval;
|
||||||
|
|
||||||
iseq->iseq = ALLOC_N(VALUE, iseq->iseq_size);
|
iseq->iseq_encoded = ALLOC_N(VALUE, iseq->iseq_size);
|
||||||
|
|
||||||
for (i=0; i<iseq->iseq_size; i+=2) {
|
for (i=0; i<iseq->iseq_size; i+=2) {
|
||||||
iseq->iseq[i] = BIN(opt_call_c_function);
|
iseq->iseq_encoded[i] = BIN(opt_call_c_function);
|
||||||
iseq->iseq[i+1] = (VALUE)func;
|
iseq->iseq_encoded[i+1] = (VALUE)func;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_iseq_translate_threaded_code(iseq);
|
rb_iseq_translate_threaded_code(iseq);
|
||||||
|
@ -2148,13 +2146,15 @@ rb_iseq_line_trace_each(VALUE iseqval, int (*func)(int line, rb_event_flag_t *ev
|
||||||
size_t insn;
|
size_t insn;
|
||||||
rb_iseq_t *iseq;
|
rb_iseq_t *iseq;
|
||||||
int cont = 1;
|
int cont = 1;
|
||||||
|
VALUE *iseq_original;
|
||||||
GetISeqPtr(iseqval, iseq);
|
GetISeqPtr(iseqval, iseq);
|
||||||
|
|
||||||
|
iseq_original = rb_iseq_original_iseq(iseq);
|
||||||
for (pos = 0; cont && pos < iseq->iseq_size; pos += insn_len(insn)) {
|
for (pos = 0; cont && pos < iseq->iseq_size; pos += insn_len(insn)) {
|
||||||
insn = iseq->iseq[pos];
|
insn = iseq_original[pos];
|
||||||
|
|
||||||
if (insn == BIN(trace)) {
|
if (insn == BIN(trace)) {
|
||||||
rb_event_flag_t current_events = (VALUE)iseq->iseq[pos+1];
|
rb_event_flag_t current_events = (VALUE)iseq_original[pos+1];
|
||||||
|
|
||||||
if (current_events & RUBY_EVENT_LINE) {
|
if (current_events & RUBY_EVENT_LINE) {
|
||||||
rb_event_flag_t events = current_events & RUBY_EVENT_SPECIFIED_LINE;
|
rb_event_flag_t events = current_events & RUBY_EVENT_SPECIFIED_LINE;
|
||||||
|
@ -2165,7 +2165,7 @@ rb_iseq_line_trace_each(VALUE iseqval, int (*func)(int line, rb_event_flag_t *ev
|
||||||
/* printf("line: %d\n", line); */
|
/* printf("line: %d\n", line); */
|
||||||
cont = (*func)(line, &events, data);
|
cont = (*func)(line, &events, data);
|
||||||
if (current_events != events) {
|
if (current_events != events) {
|
||||||
iseq->iseq[pos+1] = iseq->iseq_encoded[pos+1] =
|
iseq_original[pos+1] = iseq->iseq_encoded[pos+1] =
|
||||||
(VALUE)(current_events | (events & RUBY_EVENT_SPECIFIED_LINE));
|
(VALUE)(current_events | (events & RUBY_EVENT_SPECIFIED_LINE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
iseq.h
1
iseq.h
|
@ -17,6 +17,7 @@ RUBY_SYMBOL_EXPORT_BEGIN
|
||||||
/* compile.c */
|
/* compile.c */
|
||||||
VALUE rb_iseq_compile_node(VALUE self, NODE *node);
|
VALUE rb_iseq_compile_node(VALUE self, NODE *node);
|
||||||
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq);
|
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq);
|
||||||
|
VALUE *rb_iseq_original_iseq(rb_iseq_t *iseq);
|
||||||
VALUE rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args,
|
VALUE rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args,
|
||||||
VALUE exception, VALUE body);
|
VALUE exception, VALUE body);
|
||||||
|
|
||||||
|
|
|
@ -212,8 +212,7 @@ struct rb_iseq_struct {
|
||||||
|
|
||||||
rb_iseq_location_t location;
|
rb_iseq_location_t location;
|
||||||
|
|
||||||
VALUE *iseq; /* iseq (insn number and operands) */
|
VALUE *iseq_encoded; /* encoded iseq (insn addr and operands) */
|
||||||
VALUE *iseq_encoded; /* encoded iseq */
|
|
||||||
unsigned int iseq_size;
|
unsigned int iseq_size;
|
||||||
unsigned int line_info_size;
|
unsigned int line_info_size;
|
||||||
|
|
||||||
|
@ -309,6 +308,10 @@ struct rb_iseq_struct {
|
||||||
|
|
||||||
/* used at compile time */
|
/* used at compile time */
|
||||||
struct iseq_compile_data *compile_data;
|
struct iseq_compile_data *compile_data;
|
||||||
|
|
||||||
|
/* original iseq, before encoding
|
||||||
|
* used for debug/dump (TODO: union with compile_data) */
|
||||||
|
VALUE *iseq;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ruby_special_exceptions {
|
enum ruby_special_exceptions {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "addr2line.h"
|
#include "addr2line.h"
|
||||||
#include "vm_core.h"
|
#include "vm_core.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "iseq.h"
|
||||||
|
|
||||||
/* see vm_insnhelper.h for the values */
|
/* see vm_insnhelper.h for the values */
|
||||||
#ifndef VMDEBUG
|
#ifndef VMDEBUG
|
||||||
|
@ -359,7 +360,6 @@ rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp,VALUE *_pc)
|
||||||
rb_iseq_t *iseq = cfp->iseq;
|
rb_iseq_t *iseq = cfp->iseq;
|
||||||
|
|
||||||
if (iseq != 0) {
|
if (iseq != 0) {
|
||||||
VALUE *seq = iseq->iseq;
|
|
||||||
ptrdiff_t pc = _pc - iseq->iseq_encoded;
|
ptrdiff_t pc = _pc - iseq->iseq_encoded;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -371,7 +371,9 @@ rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp,VALUE *_pc)
|
||||||
|
|
||||||
/* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(th, cfp)); */
|
/* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(th, cfp)); */
|
||||||
if (pc >= 0) {
|
if (pc >= 0) {
|
||||||
rb_iseq_disasm_insn(0, seq, (size_t)pc, iseq, 0);
|
const VALUE *iseq_original = rb_iseq_original_iseq(iseq);
|
||||||
|
|
||||||
|
rb_iseq_disasm_insn(0, iseq_original, (size_t)pc, iseq, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue