summaryrefslogtreecommitdiff
path: root/tool/ruby_vm/views/_leaf_helpers.erb
blob: 00c2e3882a2179151d0ac05452b80c08c2371f9b (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
%# -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*-
%# 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.
%;

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 whitelist[] = {
            rb_gvar_val_getter,
            rb_gvar_var_getter,
            rb_gvar_undef_getter,
        };
        rb_gvar_getter_t *f = rb_gvar_getter_function_of(e);
        int i;

        for (i = 0; i < numberof(whitelist); i++) {
            if (f == whitelist[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 whitelist[] = {
            rb_gvar_val_setter,
            rb_gvar_readonly_setter,
            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(whitelist); i++) {
            if (f == whitelist[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:
        /* 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;
    }
}