Skip to content

Commit

Permalink
* vm_core.h: revisit the structure of frame, block and env.
Browse files Browse the repository at this point in the history
  [Bug #12628]

  This patch introduce many changes.

  * Introduce concept of "Block Handler (BH)" to represent
    passed blocks.

  * move rb_control_frame_t::flag to ep[0] (as a special local
    variable). This flags represents not only frame type, but also
    env flags such as escaped.

  * rename `rb_block_t` to `struct rb_block`.

  * Make Proc, Binding and RubyVM::Env objects wb-protected.

  Check [Bug #12628] for more details.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55766 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information
ko1 committed Jul 28, 2016
1 parent 683eafd commit 9f60791
Show file tree
Hide file tree
Showing 25 changed files with 1,880 additions and 1,068 deletions.
20 changes: 20 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
Thu Jul 28 19:53:21 2016 Koichi Sasada <ko1@atdot.net>

* vm_core.h: revisit the structure of frame, block and env.
[Bug #12628]

This patch introduce many changes.

* Introduce concept of "Block Handler (BH)" to represent
passed blocks.

* move rb_control_frame_t::flag to ep[0] (as a special local
variable). This flags represents not only frame type, but also
env flags such as escaped.

* rename `rb_block_t` to `struct rb_block`.

* Make Proc, Binding and RubyVM::Env objects wb-protected.

Check [Bug #12628] for more details.

Thu Jul 28 15:05:12 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>

* include/ruby/ruby.h (ruby_fl_type): use __extension__ to get rid
Expand Down
111 changes: 56 additions & 55 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ r_value(VALUE value)
#define debug_compile(msg, v) (v)
#endif

#define LVAR_ERRINFO (1)

/* create new label */
#define NEW_LABEL(l) new_label_body(iseq, (l))
Expand Down Expand Up @@ -264,6 +265,16 @@ r_value(VALUE value)
} \
} while (0)

#define ADD_GETLOCAL(seq, line, idx, level) \
do { \
ADD_INSN2((seq), (line), getlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); \
} while (0)

#define ADD_SETLOCAL(seq, line, idx, level) \
do { \
ADD_INSN2((seq), (line), setlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); \
} while (0)

/* add label */
#define ADD_LABEL(seq, label) \
ADD_ELEM((seq), (LINK_ELEMENT *) (label))
Expand Down Expand Up @@ -646,7 +657,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, NODE *node)
}

if (iseq->body->type == ISEQ_TYPE_RESCUE || iseq->body->type == ISEQ_TYPE_ENSURE) {
ADD_INSN2(ret, 0, getlocal, INT2FIX(2), INT2FIX(0));
ADD_GETLOCAL(ret, 0, LVAR_ERRINFO, 0);
ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ );
}
else {
Expand Down Expand Up @@ -1176,7 +1187,6 @@ iseq_set_exception_local_table(rb_iseq_t *iseq)

CONST_ID(id_dollar_bang, "#$!");
iseq->body->local_table_size = 1;
iseq->body->local_size = iseq->body->local_table_size + 1;
ids[0] = id_dollar_bang;
iseq->body->local_table = ids;
return COMPILE_OK;
Expand Down Expand Up @@ -1237,7 +1247,7 @@ get_dyna_var_idx(const rb_iseq_t *iseq, ID id, int *level, int *ls)
}

*level = lv;
*ls = iseq->body->local_size;
*ls = iseq->body->local_table_size;
return idx;
}

Expand Down Expand Up @@ -1467,10 +1477,10 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args)
static int
iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl)
{
int size;
unsigned int size;

if (tbl) {
size = (int)*tbl;
size = (unsigned int)*tbl;
tbl++;
}
else {
Expand All @@ -1482,18 +1492,9 @@ iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl)
MEMCPY(ids, tbl, ID, size);
iseq->body->local_table = ids;
}
iseq->body->local_table_size = size;

iseq->body->local_size = iseq->body->local_table_size = size;
iseq->body->local_size += 1;
/*
if (lfp == dfp ) { // top, class, method
dfp[-1]: svar
else { // block
dfp[-1]: cref
}
*/

debugs("iseq_set_local_table: %d, %d\n", iseq->body->local_size, iseq->body->local_table_size);
debugs("iseq_set_local_table: %u\n", iseq->body->local_table_size);
return COMPILE_OK;
}

Expand Down Expand Up @@ -4470,7 +4471,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
switch (nd_type(narg)) {
case NODE_ARRAY:
while (narg) {
ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
COMPILE(ret, "rescue arg", narg->nd_head);
ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
ADD_INSNL(ret, line, branchif, label_hit);
Expand All @@ -4480,7 +4481,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
case NODE_SPLAT:
case NODE_ARGSCAT:
case NODE_ARGSPUSH:
ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
COMPILE(ret, "rescue/cond splat", narg);
ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE | VM_CHECKMATCH_ARRAY));
ADD_INSNL(ret, line, branchif, label_hit);
Expand All @@ -4490,7 +4491,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
}
else {
ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
ADD_INSN1(ret, line, putobject, rb_eStandardError);
ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
ADD_INSNL(ret, line, branchif, label_hit);
Expand Down Expand Up @@ -4577,16 +4578,15 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)

case NODE_LASGN:{
ID id = node->nd_vid;
int idx = iseq->body->local_iseq->body->local_size - get_local_var_idx(iseq, id);
int idx = iseq->body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id);

debugs("lvar: %"PRIsVALUE" idx: %d\n", rb_id2str(id), idx);
COMPILE(ret, "rvalue", node->nd_value);

if (!poped) {
ADD_INSN(ret, line, dup);
}
ADD_INSN2(ret, line, setlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq)));

ADD_SETLOCAL(ret, line, idx, get_lvar_level(iseq));
break;
}
case NODE_DASGN:
Expand All @@ -4605,8 +4605,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
compile_bug(ERROR_ARGS "NODE_DASGN(_CURR): unknown id (%"PRIsVALUE")",
rb_id2str(node->nd_vid));
}

ADD_INSN2(ret, line, setlocal, INT2FIX(ls - idx), INT2FIX(lv));
ADD_SETLOCAL(ret, line, ls - idx, lv);
break;
}
case NODE_GASGN:{
Expand Down Expand Up @@ -5192,24 +5191,25 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)

/* normal arguments */
for (i = 0; i < liseq->body->param.lead_num; i++) {
int idx = liseq->body->local_size - i;
ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
int idx = liseq->body->local_table_size - i;
ADD_GETLOCAL(args, line, idx, lvar_level);
}

if (liseq->body->param.flags.has_opt) {
/* optional arguments */
int j;
for (j = 0; j < liseq->body->param.opt_num; j++) {
int idx = liseq->body->local_size - (i + j);
ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
int idx = liseq->body->local_table_size - (i + j);
ADD_GETLOCAL(args, line, idx, lvar_level);
}
i += j;
argc = i;
}
if (liseq->body->param.flags.has_rest) {
/* rest argument */
int idx = liseq->body->local_size - liseq->body->param.rest_start;
ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
int idx = liseq->body->local_table_size - liseq->body->param.rest_start;
ADD_GETLOCAL(args, line, idx, lvar_level);

argc = liseq->body->param.rest_start + 1;
flag |= VM_CALL_ARGS_SPLAT;
}
Expand All @@ -5221,8 +5221,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
if (liseq->body->param.flags.has_rest) {
int j;
for (j=0; j<post_len; j++) {
int idx = liseq->body->local_size - (post_start + j);
ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
int idx = liseq->body->local_table_size - (post_start + j);
ADD_GETLOCAL(args, line, idx, lvar_level);
}
ADD_INSN1(args, line, newarray, INT2FIX(j));
ADD_INSN (args, line, concatarray);
Expand All @@ -5231,21 +5231,22 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
else {
int j;
for (j=0; j<post_len; j++) {
int idx = liseq->body->local_size - (post_start + j);
ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
int idx = liseq->body->local_table_size - (post_start + j);
ADD_GETLOCAL(args, line, idx, lvar_level);
}
argc = post_len + post_start;
}
}

if (liseq->body->param.flags.has_kw) { /* TODO: support keywords */
int local_size = liseq->body->local_size;
int local_size = liseq->body->local_table_size;
argc++;

ADD_INSN1(args, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));

if (liseq->body->param.flags.has_kwrest) {
ADD_INSN2(args, line, getlocal, INT2FIX(liseq->body->local_size - liseq->body->param.keyword->rest_start), INT2FIX(lvar_level));
int idx = liseq->body->local_table_size - liseq->body->param.keyword->rest_start;
ADD_GETLOCAL(args, line, idx, lvar_level);
ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0));
}
else {
Expand All @@ -5255,7 +5256,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
ID id = liseq->body->param.keyword->table[i];
int idx = local_size - get_local_var_idx(liseq, id);
ADD_INSN1(args, line, putobject, ID2SYM(id));
ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level));
ADD_GETLOCAL(args, line, idx, lvar_level);
}
ADD_SEND(args, line, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1));
if (liseq->body->param.flags.has_rest) {
Expand All @@ -5265,7 +5266,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
}
else if (liseq->body->param.flags.has_kwrest) {
ADD_INSN2(args, line, getlocal, INT2FIX(liseq->body->local_size - liseq->body->param.keyword->rest_start), INT2FIX(lvar_level));
int idx = liseq->body->local_table_size - liseq->body->param.keyword->rest_start;
ADD_GETLOCAL(args, line, idx, lvar_level);

ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0));
if (liseq->body->param.flags.has_rest) {
ADD_INSN1(args, line, newarray, INT2FIX(1));
Expand Down Expand Up @@ -5406,10 +5409,10 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
case NODE_LVAR:{
if (!poped) {
ID id = node->nd_vid;
int idx = iseq->body->local_iseq->body->local_size - get_local_var_idx(iseq, id);
int idx = iseq->body->local_iseq->body->local_table_size - get_local_var_idx(iseq, id);

debugs("id: %"PRIsVALUE" idx: %d\n", rb_id2str(id), idx);
ADD_INSN2(ret, line, getlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq)));
ADD_GETLOCAL(ret, line, idx, get_lvar_level(iseq));
}
break;
}
Expand All @@ -5422,7 +5425,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
compile_bug(ERROR_ARGS "unknown dvar (%"PRIsVALUE")",
rb_id2str(node->nd_vid));
}
ADD_INSN2(ret, line, getlocal, INT2FIX(ls - idx), INT2FIX(lv));
ADD_GETLOCAL(ret, line, ls - idx, lv);
}
break;
}
Expand Down Expand Up @@ -5954,7 +5957,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
case NODE_ERRINFO:{
if (!poped) {
if (iseq->body->type == ISEQ_TYPE_RESCUE) {
ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0));
ADD_GETLOCAL(ret, line, LVAR_ERRINFO, 0);
}
else {
const rb_iseq_t *ip = iseq;
Expand All @@ -5967,7 +5970,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
level++;
}
if (ip) {
ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(level));
ADD_GETLOCAL(ret, line, LVAR_ERRINFO, level);
}
else {
ADD_INSN(ret, line, putnil);
Expand Down Expand Up @@ -6032,10 +6035,10 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
* kw = default_value
* end
*/
int kw_bits_idx = iseq->body->local_size - iseq->body->param.keyword->bits_start;
int kw_bits_idx = iseq->body->local_table_size - iseq->body->param.keyword->bits_start;
int keyword_idx = iseq->body->param.keyword->num;

ADD_INSN2(ret, line, checkkeyword, INT2FIX(kw_bits_idx), INT2FIX(keyword_idx));
ADD_INSN2(ret, line, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx));
ADD_INSNL(ret, line, branchif, end_label);
COMPILE_POPED(ret, "keyword default argument", node->nd_body);
ADD_LABEL(ret, end_label);
Expand Down Expand Up @@ -6779,7 +6782,6 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
len = RARRAY_LENINT(locals);
iseq->body->local_table_size = len;
iseq->body->local_table = tbl = len > 0 ? (ID *)ALLOC_N(ID, iseq->body->local_table_size) : NULL;
iseq->body->local_size = iseq->body->local_table_size + 1;

for (i = 0; i < len; i++) {
VALUE lv = RARRAY_AREF(locals, i);
Expand Down Expand Up @@ -6866,11 +6868,11 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
/* for parser */

int
rb_dvar_defined(ID id, const rb_block_t *base_block)
rb_dvar_defined(ID id, const struct rb_block *base_block)
{
const rb_iseq_t *iseq;

if (base_block && (iseq = base_block->iseq)) {
if (base_block && (iseq = vm_block_iseq(base_block)) != NULL) {
while (iseq->body->type == ISEQ_TYPE_BLOCK ||
iseq->body->type == ISEQ_TYPE_RESCUE ||
iseq->body->type == ISEQ_TYPE_ENSURE ||
Expand All @@ -6891,13 +6893,13 @@ rb_dvar_defined(ID id, const rb_block_t *base_block)
}

int
rb_local_defined(ID id, const rb_block_t *base_block)
rb_local_defined(ID id, const struct rb_block *base_block)
{
const rb_iseq_t *iseq;

if (base_block && base_block->iseq) {
if (base_block && (iseq = vm_block_iseq(base_block)) != NULL) {
unsigned int i;
iseq = base_block->iseq->body->local_iseq;
iseq = iseq->body->local_iseq;

for (i=0; i<iseq->body->local_table_size; i++) {
if (iseq->body->local_table[i] == id) {
Expand Down Expand Up @@ -6975,7 +6977,7 @@ for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *ret, VALUE a)
iseq->body->param.lead_num = 1;
iseq->body->param.size = 1;

ADD_INSN2(ret, line, getlocal, INT2FIX(numberof(vars)-0), INT2FIX(0));
ADD_GETLOCAL(ret, line, numberof(vars)-1, 0);
ADD_INSN1(ret, line, putobject, args->arg);
ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func);
ADD_INSN(ret, line, pop);
Expand Down Expand Up @@ -7415,7 +7417,7 @@ ibf_load_line_info_table(const struct ibf_load *load, const struct rb_iseq_const
static ID *
ibf_dump_local_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
const int size = iseq->body->local_size - 1;
const int size = iseq->body->local_table_size;
ID *table = ALLOCA_N(ID, size);
int i;

Expand All @@ -7429,7 +7431,7 @@ ibf_dump_local_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
static ID *
ibf_load_local_table(const struct ibf_load *load, const struct rb_iseq_constant_body *body)
{
const int size = body->local_size - 1;
const int size = body->local_table_size;

if (size > 0) {
ID *table = IBF_R(body->local_table, ID, size);
Expand Down Expand Up @@ -7596,7 +7598,6 @@ ibf_load_iseq_each(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t of
/* memcpy(load_body, load->buff + offset, sizeof(*load_body)); */
load_body->type = body->type;
load_body->stack_max = body->stack_max;
load_body->local_size = body->local_size;
load_body->iseq_size = body->iseq_size;
load_body->param = body->param;
load_body->local_table_size = body->local_table_size;
Expand Down
Loading

0 comments on commit 9f60791

Please sign in to comment.