summaryrefslogtreecommitdiff
path: root/vm_backtrace.c
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2024-11-04 08:14:28 -0800
committerGitHub <[email protected]>2024-11-04 11:14:28 -0500
commit478e0fc710b8fefaa3bdb7cb41dda8716e29927a (patch)
tree7e4dfe65ad53e2ae5483adb0276d00ebe58bb802 /vm_backtrace.c
parent51ac93011a8b279c1e2b93bbe6c8709392e82f57 (diff)
YJIT: Replace Array#each only when YJIT is enabled (#11955)
* YJIT: Replace Array#each only when YJIT is enabled * Add comments about BUILTIN_ATTR_C_TRACE * Make Ruby Array#each available with --yjit as well * Fix all paths that expect a C location * Use method_basic_definition_p to detect patches * Copy a comment about C_TRACE flag to compilers * Rephrase a comment about add_yjit_hook * Give METHOD_ENTRY_BASIC flag to Array#each * Add --yjit-c-builtin option * Allow inconsistent source_location in test-spec * Refactor a check of BUILTIN_ATTR_C_TRACE * Set METHOD_ENTRY_BASIC without touching vm->running
Notes
Notes: Merged-By: maximecb <[email protected]>
Diffstat (limited to 'vm_backtrace.c')
-rw-r--r--vm_backtrace.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/vm_backtrace.c b/vm_backtrace.c
index 22b28368d7..56a0d861d6 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -265,10 +265,26 @@ retry:
}
}
+// Return true if a given location is a C method or supposed to behave like one.
+static inline bool
+location_cfunc_p(rb_backtrace_location_t *loc)
+{
+ if (!loc->cme) return false;
+
+ switch (loc->cme->def->type) {
+ case VM_METHOD_TYPE_CFUNC:
+ return true;
+ case VM_METHOD_TYPE_ISEQ:
+ return rb_iseq_attr_p(loc->cme->def->body.iseq.iseqptr, BUILTIN_ATTR_C_TRACE);
+ default:
+ return false;
+ }
+}
+
static VALUE
location_label(rb_backtrace_location_t *loc)
{
- if (loc->cme && loc->cme->def->type == VM_METHOD_TYPE_CFUNC) {
+ if (location_cfunc_p(loc)) {
return rb_gen_method_name(loc->cme->owner, rb_id2str(loc->cme->def->original_id));
}
else {
@@ -314,7 +330,7 @@ location_label_m(VALUE self)
static VALUE
location_base_label(rb_backtrace_location_t *loc)
{
- if (loc->cme && loc->cme->def->type == VM_METHOD_TYPE_CFUNC) {
+ if (location_cfunc_p(loc)) {
return rb_id2str(loc->cme->def->original_id);
}
@@ -448,7 +464,7 @@ location_to_str(rb_backtrace_location_t *loc)
VALUE file, owner = Qnil, name;
int lineno;
- if (loc->cme && loc->cme->def->type == VM_METHOD_TYPE_CFUNC) {
+ if (location_cfunc_p(loc)) {
if (loc->iseq && loc->pc) {
file = rb_iseq_path(loc->iseq);
lineno = calc_lineno(loc->iseq, loc->pc);
@@ -684,13 +700,21 @@ rb_ec_partial_backtrace_object(const rb_execution_context_t *ec, long start_fram
const VALUE *pc = cfp->pc;
loc = &bt->backtrace[bt->backtrace_size++];
RB_OBJ_WRITE(btobj, &loc->cme, rb_vm_frame_method_entry(cfp));
- RB_OBJ_WRITE(btobj, &loc->iseq, iseq);
- loc->pc = pc;
- bt_update_cfunc_loc(cfunc_counter, loc-1, iseq, pc);
- if (do_yield) {
- bt_yield_loc(loc - cfunc_counter, cfunc_counter+1, btobj);
+ // Ruby methods with `Primitive.attr! :c_trace` should behave like C methods
+ if (rb_iseq_attr_p(cfp->iseq, BUILTIN_ATTR_C_TRACE)) {
+ loc->iseq = NULL;
+ loc->pc = NULL;
+ cfunc_counter++;
+ }
+ else {
+ RB_OBJ_WRITE(btobj, &loc->iseq, iseq);
+ loc->pc = pc;
+ bt_update_cfunc_loc(cfunc_counter, loc-1, iseq, pc);
+ if (do_yield) {
+ bt_yield_loc(loc - cfunc_counter, cfunc_counter+1, btobj);
+ }
+ cfunc_counter = 0;
}
- cfunc_counter = 0;
}
skip_next_frame = is_rescue_or_ensure_frame(cfp);
}