зеркало из https://github.com/github/ruby.git
Support multiple attributes with Primitive.attr!
This commit is contained in:
Родитель
3a02c7818c
Коммит
0c0c88d383
51
compile.c
51
compile.c
|
@ -8214,6 +8214,47 @@ delegate_call_p(const rb_iseq_t *iseq, unsigned int argc, const LINK_ANCHOR *arg
|
|||
}
|
||||
}
|
||||
|
||||
// Compile Primitive.attr! :inline, ...
|
||||
static int
|
||||
compile_builtin_attr(rb_iseq_t *iseq, const NODE *node)
|
||||
{
|
||||
VALUE symbol;
|
||||
VALUE string;
|
||||
if (!node) goto no_arg;
|
||||
while (node) {
|
||||
if (!nd_type_p(node, NODE_LIST)) goto bad_arg;
|
||||
const NODE *next = node->nd_next;
|
||||
|
||||
node = node->nd_head;
|
||||
if (!node) goto no_arg;
|
||||
if (!nd_type_p(node, NODE_LIT)) goto bad_arg;
|
||||
|
||||
symbol = node->nd_lit;
|
||||
if (!SYMBOL_P(symbol)) goto non_symbol_arg;
|
||||
|
||||
string = rb_sym_to_s(symbol);
|
||||
if (strcmp(RSTRING_PTR(string), "inline") == 0) {
|
||||
ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_INLINE;
|
||||
}
|
||||
else {
|
||||
goto unknown_arg;
|
||||
}
|
||||
node = next;
|
||||
}
|
||||
return COMPILE_OK;
|
||||
no_arg:
|
||||
COMPILE_ERROR(ERROR_ARGS "attr!: no argument");
|
||||
return COMPILE_NG;
|
||||
non_symbol_arg:
|
||||
COMPILE_ERROR(ERROR_ARGS "non symbol argument to attr!: %s", rb_builtin_class_name(symbol));
|
||||
return COMPILE_NG;
|
||||
unknown_arg:
|
||||
COMPILE_ERROR(ERROR_ARGS "unknown argument to attr!: %s", RSTRING_PTR(string));
|
||||
return COMPILE_NG;
|
||||
bad_arg:
|
||||
UNKNOWN_NODE("attr!", node, COMPILE_NG);
|
||||
}
|
||||
|
||||
static int
|
||||
compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, const NODE *line_node, int popped)
|
||||
{
|
||||
|
@ -8337,9 +8378,7 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD
|
|||
return COMPILE_OK;
|
||||
}
|
||||
else if (strcmp("attr!", builtin_func) == 0) {
|
||||
// There's only "inline" attribute for now
|
||||
ISEQ_BODY(iseq)->builtin_inline_p = true;
|
||||
return COMPILE_OK;
|
||||
return compile_builtin_attr(iseq, args_node);
|
||||
}
|
||||
else if (strcmp("arg!", builtin_func) == 0) {
|
||||
return compile_builtin_arg(iseq, ret, args_node, line_node, popped);
|
||||
|
@ -12122,7 +12161,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
|
|||
ibf_dump_write_small_value(dump, body->ci_size);
|
||||
ibf_dump_write_small_value(dump, body->stack_max);
|
||||
ibf_dump_write_small_value(dump, body->catch_except_p);
|
||||
ibf_dump_write_small_value(dump, body->builtin_inline_p);
|
||||
ibf_dump_write_small_value(dump, body->builtin_attrs);
|
||||
|
||||
#undef IBF_BODY_OFFSET
|
||||
|
||||
|
@ -12235,7 +12274,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
|
|||
const unsigned int ci_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
|
||||
const unsigned int stack_max = (unsigned int)ibf_load_small_value(load, &reading_pos);
|
||||
const char catch_except_p = (char)ibf_load_small_value(load, &reading_pos);
|
||||
const bool builtin_inline_p = (bool)ibf_load_small_value(load, &reading_pos);
|
||||
const unsigned int builtin_attrs = (unsigned int)ibf_load_small_value(load, &reading_pos);
|
||||
|
||||
// setup fname and dummy frame
|
||||
VALUE path = ibf_load_object(load, location_pathobj_index);
|
||||
|
@ -12308,7 +12347,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
|
|||
load_body->location.code_location.end_pos.lineno = location_code_location_end_pos_lineno;
|
||||
load_body->location.code_location.end_pos.column = location_code_location_end_pos_column;
|
||||
load_body->catch_except_p = catch_except_p;
|
||||
load_body->builtin_inline_p = builtin_inline_p;
|
||||
load_body->builtin_attrs = builtin_attrs;
|
||||
|
||||
load_body->ivc_size = ivc_size;
|
||||
load_body->icvarc_size = icvarc_size;
|
||||
|
|
|
@ -1256,7 +1256,7 @@ module RubyVM::RJIT # :nodoc: all
|
|||
ci_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), ci_size)")],
|
||||
stack_max: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), stack_max)")],
|
||||
catch_except_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), catch_except_p)")],
|
||||
builtin_inline_p: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), builtin_inline_p)")],
|
||||
builtin_attrs: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), builtin_attrs)")],
|
||||
mark_bits: [CType::Union.new(
|
||||
"", Primitive.cexpr!("SIZEOF(((struct rb_iseq_constant_body *)NULL)->mark_bits)"),
|
||||
list: CType::Pointer.new { self.iseq_bits_t },
|
||||
|
|
|
@ -44,13 +44,17 @@ def inline_text argc, arg1
|
|||
arg1.join("").rstrip
|
||||
end
|
||||
|
||||
def inline_attr(argc, arg1)
|
||||
raise "argc (#{argc}) of attr! should be 1" unless argc == 1
|
||||
attr = symbol_literal(arg1)
|
||||
unless BUILTIN_ATTRS.include?(attr)
|
||||
raise "attr (#{attr}) was not in: #{BUILTIN_ATTRS.join(', ')}"
|
||||
def inline_attrs(args)
|
||||
raise "args was empty" if args.empty?
|
||||
attrs = []
|
||||
args.each do |arg|
|
||||
attr = symbol_literal(arg)
|
||||
unless BUILTIN_ATTRS.include?(attr)
|
||||
raise "attr (#{attr}) was not in: #{BUILTIN_ATTRS.join(', ')}"
|
||||
end
|
||||
attrs << attr
|
||||
end
|
||||
attr
|
||||
attrs
|
||||
end
|
||||
|
||||
def make_cfunc_name inlines, name, lineno
|
||||
|
@ -159,7 +163,8 @@ def collect_builtin base, tree, name, bs, inlines, locals = nil
|
|||
if /(.+)[\!\?]\z/ =~ func_name
|
||||
case $1
|
||||
when 'attr'
|
||||
text = inline_attr(argc, args.first)
|
||||
# Compile-time validation only. compile.c will parse them.
|
||||
inline_attrs(args)
|
||||
break
|
||||
when 'cstmt'
|
||||
text = inline_text argc, args.first
|
||||
|
|
13
vm_core.h
13
vm_core.h
|
@ -365,6 +365,12 @@ enum rb_iseq_type {
|
|||
ISEQ_TYPE_PLAIN
|
||||
};
|
||||
|
||||
// Attributes specified by Primitive.attr!
|
||||
enum rb_builtin_attr {
|
||||
// If true, this ISeq does not call methods.
|
||||
BUILTIN_ATTR_INLINE = 0x01,
|
||||
};
|
||||
|
||||
struct rb_iseq_constant_body {
|
||||
enum rb_iseq_type type;
|
||||
|
||||
|
@ -484,12 +490,7 @@ struct rb_iseq_constant_body {
|
|||
unsigned int stack_max; /* for stack overflow check */
|
||||
|
||||
bool catch_except_p; // If a frame of this ISeq may catch exception, set true.
|
||||
// If true, this ISeq is leaf *and* backtraces are not used, for example,
|
||||
// by rb_profile_frames. We verify only leafness on VM_CHECK_MODE though.
|
||||
// Note that GC allocations might use backtraces due to
|
||||
// ObjectSpace#trace_object_allocations.
|
||||
// For more details, see: https://bugs.ruby-lang.org/issues/16956
|
||||
bool builtin_inline_p;
|
||||
unsigned int builtin_attrs; // Union of rb_builtin_attr
|
||||
|
||||
union {
|
||||
iseq_bits_t * list; /* Find references for GC */
|
||||
|
|
|
@ -6395,7 +6395,7 @@ lookup_builtin_invoker(int argc)
|
|||
static inline VALUE
|
||||
invoke_bf(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const struct rb_builtin_function* bf, const VALUE *argv)
|
||||
{
|
||||
const bool canary_p = ISEQ_BODY(reg_cfp->iseq)->builtin_inline_p; // Verify an assumption of `Primitive.attr! 'inline'`
|
||||
const bool canary_p = ISEQ_BODY(reg_cfp->iseq)->builtin_attrs & BUILTIN_ATTR_INLINE; // Verify an assumption of `Primitive.attr! :inline`
|
||||
SETUP_CANARY(canary_p);
|
||||
VALUE ret = (*lookup_builtin_invoker(bf->argc))(ec, reg_cfp->self, argv, (rb_insn_func_t)bf->func_ptr);
|
||||
CHECK_CANARY(canary_p, BIN(invokebuiltin));
|
||||
|
|
8
yjit.c
8
yjit.c
|
@ -620,12 +620,6 @@ rb_get_iseq_body_iseq_encoded(const rb_iseq_t *iseq)
|
|||
return iseq->body->iseq_encoded;
|
||||
}
|
||||
|
||||
bool
|
||||
rb_get_iseq_body_builtin_inline_p(const rb_iseq_t *iseq)
|
||||
{
|
||||
return iseq->body->builtin_inline_p;
|
||||
}
|
||||
|
||||
unsigned
|
||||
rb_get_iseq_body_stack_max(const rb_iseq_t *iseq)
|
||||
{
|
||||
|
@ -741,7 +735,7 @@ rb_leaf_invokebuiltin_iseq_p(const rb_iseq_t *iseq)
|
|||
return (iseq->body->iseq_size == (invokebuiltin_len + leave_len) &&
|
||||
rb_vm_insn_addr2opcode((void *)iseq->body->iseq_encoded[0]) == BIN(opt_invokebuiltin_delegate_leave) &&
|
||||
rb_vm_insn_addr2opcode((void *)iseq->body->iseq_encoded[invokebuiltin_len]) == BIN(leave) &&
|
||||
iseq->body->builtin_inline_p
|
||||
(iseq->body->builtin_attrs & BUILTIN_ATTR_INLINE) != 0
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче