1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

iseq.c (get_insn_info): use binary search instead of linear search

This change introduces get_insn_info_binary_search, which is (should be)
equivalent to the old get_insn_info.
The old get_insn_info is renamed to get_insn_info_linear_search.  When
VM_CHECK_MODE > 0, the equivalence is validated at finish_iseq_build.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61353 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
mame 2017-12-20 07:38:24 +00:00
parent 799db969e9
commit be3439026a

73
iseq.c
View file

@ -345,6 +345,10 @@ prepare_iseq_build(rb_iseq_t *iseq,
return Qtrue;
}
#if VM_CHECK_MODE > 0
static void validate_get_insn_info(rb_iseq_t *iseq);
#endif
static VALUE
finish_iseq_build(rb_iseq_t *iseq)
{
@ -353,6 +357,10 @@ finish_iseq_build(rb_iseq_t *iseq)
ISEQ_COMPILE_DATA_CLEAR(iseq);
compile_data_free(data);
#if VM_CHECK_MODE > 0
validate_get_insn_info(iseq);
#endif
if (RTEST(err)) {
VALUE path = pathobj_path(iseq->body->location.pathobj);
if (err == Qtrue) err = rb_exc_new_cstr(rb_eSyntaxError, "compile error");
@ -1237,11 +1245,52 @@ iseqw_to_a(VALUE self)
return iseq_data_to_ary(iseq);
}
/* TODO: search algorithm is brute force.
this should be binary search or so. */
static const struct iseq_insn_info_entry *
get_insn_info(const rb_iseq_t *iseq, size_t pos)
get_insn_info_binary_search(const rb_iseq_t *iseq, size_t pos)
{
size_t size = iseq->body->insns_info_size;
const struct iseq_insn_info_entry *insns_info = iseq->body->insns_info;
const int debug = 0;
if (debug) {
printf("size: %"PRIuSIZE"\n", size);
printf("insns_info[%"PRIuSIZE"]: position: %d, line: %d, pos: %"PRIuSIZE"\n",
(size_t)0, insns_info[0].position, insns_info[0].line_no, pos);
}
if (size == 0) {
return NULL;
}
else if (size == 1) {
return &insns_info[0];
}
else {
size_t l = 1, r = size - 1;
while (l <= r) {
size_t m = l + (r - l) / 2;
if (insns_info[m].position == pos) {
return &insns_info[m];
}
if (insns_info[m].position < pos) {
l = m + 1;
}
else {
r = m - 1;
}
}
if (l >= size) {
return &insns_info[size-1];
}
if (insns_info[l].position > pos) {
return &insns_info[l-1];
}
return &insns_info[l];
}
}
#if VM_CHECK_MODE > 0
static const struct iseq_insn_info_entry *
get_insn_info_linear_search(const rb_iseq_t *iseq, size_t pos)
{
size_t i = 0, size = iseq->body->insns_info_size;
const struct iseq_insn_info_entry *insns_info = iseq->body->insns_info;
@ -1275,10 +1324,22 @@ get_insn_info(const rb_iseq_t *iseq, size_t pos)
return &insns_info[i-1];
}
static void
validate_get_insn_info(rb_iseq_t *iseq)
{
size_t i;
for (i = 0; i < iseq->body->iseq_size; i++) {
if (get_insn_info_linear_search(iseq, i) != get_insn_info_binary_search(iseq, i)) {
rb_bug("validate_get_insn_info: get_insn_info_linear_search(iseq, %"PRIuSIZE") != get_insn_info_binary_search(iseq, %"PRIuSIZE")", i, i);
}
}
}
#endif
unsigned int
rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
{
const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
const struct iseq_insn_info_entry *entry = get_insn_info_binary_search(iseq, pos);
if (entry) {
return entry->line_no;
@ -1291,7 +1352,7 @@ rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos)
rb_event_flag_t
rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos)
{
const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pos);
const struct iseq_insn_info_entry *entry = get_insn_info_binary_search(iseq, pos);
if (entry) {
return entry->events;
}