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:
parent
799db969e9
commit
be3439026a
1 changed files with 67 additions and 6 deletions
73
iseq.c
73
iseq.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue