~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to vm_method.c

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * This file is included by vm.h
 
2
 * This file is included by vm.c
3
3
 */
4
4
 
5
5
#define CACHE_SIZE 0x800
13
13
static ID added, singleton_added, attached;
14
14
 
15
15
struct cache_entry {            /* method hash table. */
 
16
    VALUE filled_version;        /* filled state version */
16
17
    ID mid;                     /* method's id */
17
18
    VALUE klass;                /* receiver's class */
18
19
    rb_method_entry_t *me;
22
23
#define ruby_running (GET_VM()->running)
23
24
/* int ruby_running = 0; */
24
25
 
 
26
static void
 
27
vm_clear_global_method_cache(void)
 
28
{
 
29
    struct cache_entry *ent, *end;
 
30
 
 
31
    ent = cache;
 
32
    end = ent + CACHE_SIZE;
 
33
    while (ent < end) {
 
34
        ent->filled_version = 0;
 
35
        ent++;
 
36
    }
 
37
}
 
38
 
25
39
void
26
40
rb_clear_cache(void)
27
41
{
28
 
    struct cache_entry *ent, *end;
29
 
 
30
42
    rb_vm_change_state();
31
 
 
32
 
    if (!ruby_running)
33
 
        return;
34
 
    ent = cache;
35
 
    end = ent + CACHE_SIZE;
36
 
    while (ent < end) {
37
 
        ent->me = 0;
38
 
        ent->mid = 0;
39
 
        ent++;
40
 
    }
41
43
}
42
44
 
43
45
static void
44
46
rb_clear_cache_for_undef(VALUE klass, ID id)
45
47
{
46
 
    struct cache_entry *ent, *end;
47
 
 
48
48
    rb_vm_change_state();
49
 
 
50
 
    if (!ruby_running)
51
 
        return;
52
 
    ent = cache;
53
 
    end = ent + CACHE_SIZE;
54
 
    while (ent < end) {
55
 
        if ((ent->me && ent->me->klass == klass) && ent->mid == id) {
56
 
            ent->me = 0;
57
 
            ent->mid = 0;
58
 
        }
59
 
        ent++;
60
 
    }
61
49
}
62
50
 
63
51
static void
64
52
rb_clear_cache_by_id(ID id)
65
53
{
66
 
    struct cache_entry *ent, *end;
67
 
 
68
54
    rb_vm_change_state();
69
 
 
70
 
    if (!ruby_running)
71
 
        return;
72
 
    ent = cache;
73
 
    end = ent + CACHE_SIZE;
74
 
    while (ent < end) {
75
 
        if (ent->mid == id) {
76
 
            ent->me = 0;
77
 
            ent->mid = 0;
78
 
        }
79
 
        ent++;
80
 
    }
81
55
}
82
56
 
83
57
void
84
58
rb_clear_cache_by_class(VALUE klass)
85
59
{
86
 
    struct cache_entry *ent, *end;
87
 
 
88
60
    rb_vm_change_state();
89
 
 
90
 
    if (!ruby_running)
91
 
        return;
92
 
    ent = cache;
93
 
    end = ent + CACHE_SIZE;
94
 
    while (ent < end) {
95
 
        if (ent->klass == klass || (ent->me && ent->me->klass == klass)) {
96
 
            ent->me = 0;
97
 
            ent->mid = 0;
98
 
        }
99
 
        ent++;
100
 
    }
101
61
}
102
62
 
103
63
VALUE
126
86
    }
127
87
}
128
88
 
129
 
static void
 
89
void
130
90
rb_unlink_method_entry(rb_method_entry_t *me)
131
91
{
132
92
    struct unlinked_method_entry_list_entry *ume = ALLOC(struct unlinked_method_entry_list_entry);
136
96
}
137
97
 
138
98
void
 
99
rb_gc_mark_unlinked_live_method_entries(void *pvm)
 
100
{
 
101
    rb_vm_t *vm = pvm;
 
102
    struct unlinked_method_entry_list_entry *ume = vm->unlinked_method_entry_list, *prev_ume = 0, *curr_ume;
 
103
 
 
104
    while (ume) {
 
105
        if (ume->me->mark) {
 
106
            rb_mark_method_entry(ume->me);
 
107
        }
 
108
        ume = ume->next;
 
109
    }
 
110
}
 
111
 
 
112
void
139
113
rb_sweep_method_entry(void *pvm)
140
114
{
141
115
    rb_vm_t *vm = pvm;
211
185
                rb_class2name(rb_ivar_get(klass, attached)));
212
186
        mid = ID_ALLOCATOR;
213
187
    }
214
 
    if (OBJ_FROZEN(klass)) {
215
 
        rb_error_frozen("class/module");
216
 
    }
217
188
 
 
189
    rb_check_frozen(klass);
218
190
    mtbl = RCLASS_M_TBL(klass);
219
191
 
220
192
    /* check re-definition */
230
202
            old_def->alias_count == 0 &&
231
203
            old_def->type != VM_METHOD_TYPE_UNDEF &&
232
204
            old_def->type != VM_METHOD_TYPE_ZSUPER) {
233
 
            extern rb_iseq_t *rb_proc_get_iseq(VALUE proc, int *is_proc);
234
205
            rb_iseq_t *iseq = 0;
235
206
 
236
207
            rb_warning("method redefined; discarding old %s", rb_id2name(mid));
284
255
 
285
256
#define CALL_METHOD_HOOK(klass, hook, mid) do {         \
286
257
        const VALUE arg = ID2SYM(mid);                  \
287
 
        VALUE recv_class = klass;                       \
288
 
        ID hook_id = hook;                              \
289
 
        if (FL_TEST(klass, FL_SINGLETON)) {             \
290
 
            recv_class = rb_ivar_get(klass, attached);  \
 
258
        VALUE recv_class = (klass);                     \
 
259
        ID hook_id = (hook);                            \
 
260
        if (FL_TEST((klass), FL_SINGLETON)) {           \
 
261
            recv_class = rb_ivar_get((klass), attached);        \
291
262
            hook_id = singleton_##hook;                 \
292
263
        }                                               \
293
264
        rb_funcall2(recv_class, hook_id, 1, &arg);      \
422
393
    if (ruby_running) {
423
394
        struct cache_entry *ent;
424
395
        ent = cache + EXPR1(klass, id);
 
396
        ent->filled_version = GET_VM_STATE_VERSION();
425
397
        ent->klass = klass;
426
398
 
427
399
        if (UNDEFINED_METHOD_ENTRY_P(me)) {
444
416
    struct cache_entry *ent;
445
417
 
446
418
    ent = cache + EXPR1(klass, id);
447
 
    if (ent->mid == id && ent->klass == klass) {
 
419
    if (ent->filled_version == GET_VM_STATE_VERSION() &&
 
420
        ent->mid == id && ent->klass == klass) {
448
421
        return ent->me;
449
422
    }
450
423
 
454
427
static void
455
428
remove_method(VALUE klass, ID mid)
456
429
{
457
 
    st_data_t data;
 
430
    st_data_t key, data;
458
431
    rb_method_entry_t *me = 0;
459
432
 
460
433
    if (klass == rb_cObject) {
463
436
    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
464
437
        rb_raise(rb_eSecurityError, "Insecure: can't remove method");
465
438
    }
466
 
    if (OBJ_FROZEN(klass))
467
 
        rb_error_frozen("class/module");
 
439
    rb_check_frozen(klass);
468
440
    if (mid == object_id || mid == id__send__ || mid == idInitialize) {
469
441
        rb_warn("removing `%s' may cause serious problems", rb_id2name(mid));
470
442
    }
475
447
        rb_name_error(mid, "method `%s' not defined in %s",
476
448
                      rb_id2name(mid), rb_class2name(klass));
477
449
    }
478
 
    st_delete(RCLASS_M_TBL(klass), &mid, &data);
 
450
    key = (st_data_t)mid;
 
451
    st_delete(RCLASS_M_TBL(klass), &key, &data);
479
452
 
480
453
    rb_vm_check_redefinition_opt_method(me);
481
454
    rb_clear_cache_for_undef(klass, mid);
1151
1124
 *     end
1152
1125
 *     class Cls
1153
1126
 *       include Mod
1154
 
 *       def callOne
 
1127
 *       def call_one
1155
1128
 *         one
1156
1129
 *       end
1157
1130
 *     end
1158
1131
 *     Mod.one     #=> "This is one"
1159
1132
 *     c = Cls.new
1160
 
 *     c.callOne   #=> "This is one"
 
1133
 *     c.call_one  #=> "This is one"
1161
1134
 *     module Mod
1162
1135
 *       def one
1163
1136
 *         "This is the new one"
1164
1137
 *       end
1165
1138
 *     end
1166
1139
 *     Mod.one     #=> "This is one"
1167
 
 *     c.callOne   #=> "This is the new one"
 
1140
 *     c.call_one  #=> "This is the new one"
1168
1141
 */
1169
1142
 
1170
1143
static VALUE
1293
1266
 *  See #respond_to?.
1294
1267
 */
1295
1268
static VALUE
1296
 
obj_respond_to_missing(VALUE obj, VALUE priv)
 
1269
obj_respond_to_missing(VALUE obj, VALUE mid, VALUE priv)
1297
1270
{
1298
1271
    return Qfalse;
1299
1272
}