summaryrefslogtreecommitdiff
path: root/tool/ruby_vm/views/_leaf_helpers.erb
blob: ac60f2dcbc909c4daf6ea06c042180fbb7a3ce91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
%# -*- C -*-
%# Copyright (c) 2018 Urabe, Shyouhei.  All rights reserved.
%#
%# This file is a part of  the programming language Ruby.  Permission is hereby
%# granted, to either  redistribute and/or modify this file,  provided that the
%# conditions mentioned  in the  file COPYING  are met.   Consult the  file for
%# details.
%;
#line <%= __LINE__ + 1 %> <%=cstr __FILE__ %>

static bool
leafness_of_getglobal(VALUE gentry)
{
    const struct rb_global_entry *e = (void *)gentry;

    if (UNLIKELY(rb_gvar_is_traced(e))) {
        return false;
    }
    else {
        /* We cannot write this function using a switch() because a
         * case label cannot be a function pointer. */
        static rb_gvar_getter_t *const allowlist[] = {
            rb_gvar_val_getter,
            rb_gvar_var_getter,
            /* rb_gvar_undef_getter issues rb_warning() */
        };
        rb_gvar_getter_t *f = rb_gvar_getter_function_of(e);
        int i;

        for (i = 0; i < numberof(allowlist); i++) {
            if (f == allowlist[i]) {
                return true;
            }
        }
        return false;
    }
}

static bool
leafness_of_setglobal(VALUE gentry)
{
    const struct rb_global_entry *e = (void *)gentry;

    if (UNLIKELY(rb_gvar_is_traced(e))) {
        return false;
    }
    else {
        /* We cannot write this function using a switch() because a
         * case label cannot be a function pointer. */
        static rb_gvar_setter_t *const allowlist[] = {
            rb_gvar_val_setter,
            /* rb_gvar_readonly_setter issues rb_name_error() */
            rb_gvar_var_setter,
            rb_gvar_undef_setter,
        };
        rb_gvar_setter_t *f = rb_gvar_setter_function_of(e);
        int i;

        for (i = 0; i < numberof(allowlist); i++) {
            if (f == allowlist[i]) {
                return true;
            }
        }
        return false;
    }
}

#include "iseq.h"

static bool
leafness_of_defined(rb_num_t op_type)
{
    /* see also: vm_insnhelper.c:vm_defined() */
    switch (op_type) {
      case DEFINED_IVAR:
      case DEFINED_IVAR2:
      case DEFINED_GVAR:
      case DEFINED_CVAR:
      case DEFINED_YIELD:
      case DEFINED_REF:
      case DEFINED_ZSUPER:
        return false;
      case DEFINED_CONST:
      case DEFINED_CONST_FROM:
        /* has rb_autoload_load(); */
        return false;
      case DEFINED_FUNC:
      case DEFINED_METHOD:
        /* calls #respond_to_missing? */
        return false;
      default:
        rb_bug("unknown operand %ld: blame @shyouhei.", op_type);
    }
}

static bool
leafness_of_checkmatch(rb_num_t flag)
{
    /* see also: vm_insnhelper.c:check_match() */
    if (flag == VM_CHECKMATCH_TYPE_WHEN) {
        return true;
    }
    else {
        /* has rb_funcallv() */
        return false;
    }
}
#pragma RubyVM reset source