summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c95
1 files changed, 67 insertions, 28 deletions
diff --git a/compile.c b/compile.c
index 077770a7e4..24b90826cd 100644
--- a/compile.c
+++ b/compile.c
@@ -48,9 +48,6 @@
#include "insns.inc"
#include "insns_info.inc"
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
-
#define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
#define FIXNUM_OR(n, i) ((n)|INT2FIX(i))
@@ -1479,11 +1476,11 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node,
VALUE name, const rb_iseq_t *parent, enum rb_iseq_type type, int line_no)
{
rb_iseq_t *ret_iseq;
- VALUE vast = rb_ruby_ast_new(node, NULL);
+ VALUE ast_value = rb_ruby_ast_new(node);
debugs("[new_child_iseq]> ---------------------------------------\n");
int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
- ret_iseq = rb_iseq_new_with_opt(vast, name,
+ ret_iseq = rb_iseq_new_with_opt(ast_value, name,
rb_iseq_path(iseq), rb_iseq_realpath(iseq),
line_no, parent,
isolated_depth ? isolated_depth + 1 : 0,
@@ -3080,7 +3077,7 @@ iseq_pop_newarray(rb_iseq_t *iseq, INSN *iobj)
static int
is_frozen_putstring(INSN *insn, VALUE *op)
{
- if (IS_INSN_ID(insn, putstring)) {
+ if (IS_INSN_ID(insn, putstring) || IS_INSN_ID(insn, putchilledstring)) {
*op = OPERAND_AT(insn, 0);
return 1;
}
@@ -3122,6 +3119,7 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
switch (INSN_OF(iobj)) {
case BIN(putstring):
+ case BIN(putchilledstring):
type = INT2FIX(T_STRING);
break;
case BIN(putnil):
@@ -3549,6 +3547,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
enum ruby_vminsn_type previ = ((INSN *)prev)->insn_id;
if (previ == BIN(putobject) || previ == BIN(putnil) ||
previ == BIN(putself) || previ == BIN(putstring) ||
+ previ == BIN(putchilledstring) ||
previ == BIN(dup) ||
previ == BIN(getlocal) ||
previ == BIN(getblockparam) ||
@@ -3690,7 +3689,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
- if (IS_INSN_ID(iobj, putstring) ||
+ if (IS_INSN_ID(iobj, putstring) || IS_INSN_ID(iobj, putchilledstring) ||
(IS_INSN_ID(iobj, putobject) && RB_TYPE_P(OPERAND_AT(iobj, 0), T_STRING))) {
/*
* putstring ""
@@ -4048,6 +4047,8 @@ insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id)
return COMPILE_OK;
}
+#define vm_ci_simple(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)
+
static int
iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
{
@@ -4059,24 +4060,43 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
INSN *niobj = (INSN *)iobj->link.next;
if (IS_INSN_ID(niobj, send)) {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(niobj, 0);
- if ((vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) && vm_ci_argc(ci) == 0) {
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0) {
switch (vm_ci_mid(ci)) {
case idMax:
case idMin:
case idHash:
{
VALUE num = iobj->operands[0];
+ int operand_len = insn_len(BIN(opt_newarray_send)) - 1;
iobj->insn_id = BIN(opt_newarray_send);
- iobj->operands = compile_data_calloc2(iseq, insn_len(iobj->insn_id) - 1, sizeof(VALUE));
+ iobj->operands = compile_data_calloc2(iseq, operand_len, sizeof(VALUE));
iobj->operands[0] = num;
iobj->operands[1] = rb_id2sym(vm_ci_mid(ci));
- iobj->operand_size = insn_len(iobj->insn_id) - 1;
+ iobj->operand_size = operand_len;
ELEM_REMOVE(&niobj->link);
return COMPILE_OK;
}
}
}
}
+ else if ((IS_INSN_ID(niobj, putstring) || IS_INSN_ID(niobj, putchilledstring) ||
+ (IS_INSN_ID(niobj, putobject) && RB_TYPE_P(OPERAND_AT(niobj, 0), T_STRING))) &&
+ IS_NEXT_INSN_ID(&niobj->link, send)) {
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT((INSN *)niobj->link.next, 0);
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idPack) {
+ VALUE num = iobj->operands[0];
+ int operand_len = insn_len(BIN(opt_newarray_send)) - 1;
+ iobj->insn_id = BIN(opt_newarray_send);
+ iobj->operands = compile_data_calloc2(iseq, operand_len, sizeof(VALUE));
+ iobj->operands[0] = FIXNUM_INC(num, 1);
+ iobj->operands[1] = rb_id2sym(vm_ci_mid(ci));
+ iobj->operand_size = operand_len;
+ ELEM_REMOVE(&iobj->link);
+ ELEM_REMOVE(niobj->link.next);
+ ELEM_INSERT_NEXT(&niobj->link, &iobj->link);
+ return COMPILE_OK;
+ }
+ }
}
if (IS_INSN_ID(iobj, send)) {
@@ -4084,7 +4104,7 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(iobj, 1);
#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
- if (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) {
+ if (vm_ci_simple(ci)) {
switch (vm_ci_argc(ci)) {
case 0:
switch (vm_ci_mid(ci)) {
@@ -4406,11 +4426,12 @@ static int
compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
int cnt;
+ int cflag = (int)RNODE_DREGX(node)->as.nd_cflag;
if (!RNODE_DREGX(node)->nd_next) {
if (!popped) {
VALUE src = rb_node_dregx_string_val(node);
- VALUE match = rb_reg_compile(src, (int)RNODE_DREGX(node)->nd_cflag, NULL, 0);
+ VALUE match = rb_reg_compile(src, cflag, NULL, 0);
ADD_INSN1(ret, node, putobject, match);
RB_OBJ_WRITTEN(iseq, Qundef, match);
}
@@ -4418,7 +4439,7 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
}
CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
- ADD_INSN2(ret, node, toregexp, INT2FIX(RNODE_DREGX(node)->nd_cflag), INT2FIX(cnt));
+ ADD_INSN2(ret, node, toregexp, INT2FIX(cflag), INT2FIX(cnt));
if (popped) {
ADD_INSN(ret, node, pop);
@@ -5380,12 +5401,17 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_ATTRASGN)", node));
+ bool safenav_call = false;
LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
iobj = (INSN *)get_prev_insn((INSN *)insn_element); /* send insn */
ASSUME(iobj);
- ELEM_REMOVE(LAST_ELEMENT(pre));
- ELEM_REMOVE((LINK_ELEMENT *)iobj);
- pre->last = iobj->link.prev;
+ ELEM_REMOVE(insn_element);
+ if (!IS_INSN_ID(iobj, send)) {
+ safenav_call = true;
+ iobj = (INSN *)get_prev_insn(iobj);
+ ELEM_INSERT_NEXT(&iobj->link, insn_element);
+ }
+ (pre->last = iobj->link.prev)->next = 0;
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0);
int argc = vm_ci_argc(ci) + 1;
@@ -5404,7 +5430,9 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
return COMPILE_NG;
}
- ADD_ELEM(lhs, (LINK_ELEMENT *)iobj);
+ iobj->link.prev = lhs->last;
+ lhs->last->next = &iobj->link;
+ for (lhs->last = &iobj->link; lhs->last->next; lhs->last = lhs->last->next);
if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
int argc = vm_ci_argc(ci);
bool dupsplat = false;
@@ -5437,9 +5465,11 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
}
INSERT_BEFORE_INSN1(iobj, line_no, node_id, pushtoarray, INT2FIX(1));
}
- ADD_INSN(lhs, line_node, pop);
- if (argc != 1) {
+ if (!safenav_call) {
ADD_INSN(lhs, line_node, pop);
+ if (argc != 1) {
+ ADD_INSN(lhs, line_node, pop);
+ }
}
for (int i=0; i < argc; i++) {
ADD_INSN(post, line_node, pop);
@@ -8311,7 +8341,7 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
static int
compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
- const int line = nd_line(node);
+ const int line = nd_line(RNODE_ENSURE(node)->nd_ensr);
const NODE *line_node = node;
DECL_ANCHOR(ensr);
const rb_iseq_t *ensure = NEW_CHILD_ISEQ(RNODE_ENSURE(node)->nd_ensr,
@@ -8771,10 +8801,10 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N
scope_node.nd_body = mandatory_node(iseq, node);
scope_node.nd_args = &args_node;
- VALUE vast = rb_ruby_ast_new(RNODE(&scope_node), NULL);
+ VALUE ast_value = rb_ruby_ast_new(RNODE(&scope_node));
ISEQ_BODY(iseq)->mandatory_only_iseq =
- rb_iseq_new_with_opt(vast, rb_iseq_base_label(iseq),
+ rb_iseq_new_with_opt(ast_value, rb_iseq_base_label(iseq),
rb_iseq_path(iseq), rb_iseq_realpath(iseq),
nd_line(line_node), NULL, 0,
ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option,
@@ -9852,7 +9882,7 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
static int
compile_make_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, LINK_ANCHOR *sub, const NODE *value, bool copy)
{
- ADD_INSN1(ret, value, putobject, rb_mRubyVMFrozenCore);
+ ADD_INSN1(ret, value, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_SEQ(ret, sub);
if (copy) {
@@ -9941,7 +9971,7 @@ compile_ensure_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *dest, con
*. RubyVM::FrozenCore.ensure_shareable(value, const_decl_path(dest))
*/
VALUE path = const_decl_path(dest);
- ADD_INSN1(ret, value, putobject, rb_mRubyVMFrozenCore);
+ ADD_INSN1(ret, value, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
CHECK(COMPILE(ret, "compile_ensure_shareable_node", value));
ADD_INSN1(ret, value, putobject, path);
RB_OBJ_WRITTEN(iseq, Qundef, path);
@@ -11388,7 +11418,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
{
/* TODO: body should be frozen */
long i, len = RARRAY_LEN(body);
- struct st_table *labels_table = DATA_PTR(labels_wrapper);
+ struct st_table *labels_table = RTYPEDDATA_DATA(labels_wrapper);
int j;
int line_no = 0, node_id = -1, insn_idx = 0;
int ret = COMPILE_OK;
@@ -11566,7 +11596,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
rb_raise(rb_eTypeError, "unexpected object for instruction");
}
}
- DATA_PTR(labels_wrapper) = 0;
+ RTYPEDDATA_DATA(labels_wrapper) = 0;
RB_GC_GUARD(labels_wrapper);
validate_labels(iseq, labels_table);
if (!ret) return ret;
@@ -11699,6 +11729,15 @@ rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *storage)
}
}
+static const rb_data_type_t labels_wrapper_type = {
+ .wrap_struct_name = "compiler/labels_wrapper",
+ .function = {
+ .dmark = (RUBY_DATA_FUNC)rb_mark_set,
+ .dfree = (RUBY_DATA_FUNC)st_free_table,
+ },
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
void
rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
VALUE exception, VALUE body)
@@ -11708,7 +11747,7 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
unsigned int arg_size, local_size, stack_max;
ID *tbl;
struct st_table *labels_table = st_init_numtable();
- VALUE labels_wrapper = Data_Wrap_Struct(0, rb_mark_set, st_free_table, labels_table);
+ VALUE labels_wrapper = TypedData_Wrap_Struct(0, &labels_wrapper_type, labels_table);
VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt));
VALUE keywords = rb_hash_aref(params, SYM(keyword));
VALUE sym_arg_rest = ID2SYM(rb_intern_const("#arg_rest"));
@@ -13514,7 +13553,7 @@ ibf_load_object_string(const struct ibf_load *load, const struct ibf_object_head
VALUE str;
if (header->frozen && !header->internal) {
- str = rb_enc_interned_str(ptr, len, rb_enc_from_index(encindex));
+ str = rb_enc_literal_str(ptr, len, rb_enc_from_index(encindex));
}
else {
str = rb_enc_str_new(ptr, len, rb_enc_from_index(encindex));