Bug #18062 » 4716.patch
| vm_eval.c | ||
|---|---|---|
|     { | ||
|         struct rb_class_cc_entries *ccs; | ||
|         struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); | ||
|         VALUE ccs_data; | ||
|         if (rb_id_table_lookup(cc_tbl, mid, (VALUE*)&ccs)) { | ||
|         if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { | ||
|             // ok | ||
|             ccs = (struct rb_class_cc_entries *)ccs_data; | ||
|         } | ||
|         else { | ||
|             ccs = vm_ccs_create(klass, cme); | ||
| vm_insnhelper.c | ||
|---|---|---|
|     const ID mid = vm_ci_mid(ci); | ||
|     struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); | ||
|     struct rb_class_cc_entries *ccs = NULL; | ||
|     VALUE ccs_data; | ||
|     if (cc_tbl) { | ||
|         if (rb_id_table_lookup(cc_tbl, mid, (VALUE *)&ccs)) { | ||
|         if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { | ||
|             ccs = (struct rb_class_cc_entries *)ccs_data; | ||
|             const int ccs_len = ccs->len; | ||
|             VM_ASSERT(vm_ccs_verify(ccs, mid, klass)); | ||
| ... | ... | |
|     if (ccs == NULL) { | ||
|         VM_ASSERT(cc_tbl != NULL); | ||
|         if (LIKELY(rb_id_table_lookup(cc_tbl, mid, (VALUE*)&ccs))) { | ||
|         if (LIKELY(rb_id_table_lookup(cc_tbl, mid, &ccs_data))) { | ||
|             // rb_callable_method_entry() prepares ccs. | ||
|             ccs = (struct rb_class_cc_entries *)ccs_data; | ||
|         } | ||
|         else { | ||
|             // TODO: required? | ||
| vm_method.c | ||
|---|---|---|
| { | ||
|     struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); | ||
|     if (cc_tbl) { | ||
|         const struct rb_class_cc_entries *ccs; | ||
|         VALUE ccs; | ||
|         if (target_mid) { | ||
|             if (rb_id_table_lookup(cc_tbl, target_mid, (VALUE *)&ccs)) { | ||
|             if (rb_id_table_lookup(cc_tbl, target_mid, &ccs)) { | ||
|                 fprintf(stderr, "  [CCTB] %p\n", (void *)cc_tbl); | ||
|                 vm_ccs_dump_i(target_mid, (VALUE)ccs, NULL); | ||
|                 vm_ccs_dump_i(target_mid, ccs, NULL); | ||
|             } | ||
|         } | ||
|         else { | ||
| ... | ... | |
|     fprintf(stderr, "# vm_mtbl\n"); | ||
|     while (klass) { | ||
|         rp_m("  -> ", klass); | ||
|         rb_method_entry_t *me; | ||
|         VALUE me; | ||
|         if (RCLASS_M_TBL(klass)) { | ||
|             if (target_mid != 0) { | ||
|                 if (rb_id_table_lookup(RCLASS_M_TBL(klass), target_mid, (VALUE *)&me)) { | ||
|                 if (rb_id_table_lookup(RCLASS_M_TBL(klass), target_mid, &me)) { | ||
|                     rp_m("  [MTBL] ", me); | ||
|                 } | ||
|             } | ||
| ... | ... | |
|         } | ||
|         if (RCLASS_CALLABLE_M_TBL(klass)) { | ||
|             if (target_mid != 0) { | ||
|                 if (rb_id_table_lookup(RCLASS_CALLABLE_M_TBL(klass), target_mid, (VALUE *)&me)) { | ||
|                 if (rb_id_table_lookup(RCLASS_CALLABLE_M_TBL(klass), target_mid, &me)) { | ||
|                     rp_m("  [CM**] ", me); | ||
|                 } | ||
|             } | ||
| ... | ... | |
|         // check only current class | ||
|         struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); | ||
|         struct rb_class_cc_entries *ccs; | ||
|         VALUE ccs_data; | ||
|         // invalidate CCs | ||
|         if (cc_tbl && rb_id_table_lookup(cc_tbl, mid, (VALUE *)&ccs)) { | ||
|         if (cc_tbl && rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { | ||
|             struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_data; | ||
|             rb_vm_ccs_free(ccs); | ||
|             rb_id_table_delete(cc_tbl, mid); | ||
|             RB_DEBUG_COUNTER_INC(cc_invalidate_leaf_ccs); | ||
| ... | ... | |
|         } | ||
|         else { | ||
|             rb_vm_t *vm = GET_VM(); | ||
|             if (rb_id_table_lookup(vm->negative_cme_table, mid, (VALUE *)&cme)) { | ||
|             VALUE cme_data = cme; | ||
|             if (rb_id_table_lookup(vm->negative_cme_table, mid, &cme_data)) { | ||
|                 rb_id_table_delete(vm->negative_cme_table, mid); | ||
|                 vm_me_invalidate_cache((rb_callable_method_entry_t *)cme); | ||
|                 vm_me_invalidate_cache((rb_callable_method_entry_t *)cme_data); | ||
|                 RB_DEBUG_COUNTER_INC(cc_invalidate_negative); | ||
|             } | ||
| ... | ... | |
| { | ||
|     struct rb_id_table *mtbl; | ||
|     const rb_callable_method_entry_t *cme; | ||
|     VALUE cme_data; | ||
|     if (me) { | ||
|         if (me->defined_class == 0) { | ||
| ... | ... | |
|             mtbl = RCLASS_CALLABLE_M_TBL(defined_class); | ||
|             if (mtbl && rb_id_table_lookup(mtbl, id, (VALUE *)&cme)) { | ||
|             if (mtbl && rb_id_table_lookup(mtbl, id, &cme_data)) { | ||
|                 cme = (rb_callable_method_entry_t *)cme_data; | ||
|                 RB_DEBUG_COUNTER_INC(mc_cme_complement_hit); | ||
|                 VM_ASSERT(callable_method_entry_p(cme)); | ||
|                 VM_ASSERT(!METHOD_ENTRY_INVALIDATED(cme)); | ||
| ... | ... | |
|     ASSERT_vm_locking(); | ||
|     struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); | ||
|     struct rb_class_cc_entries *ccs; | ||
|     VALUE ccs_data; | ||
|     if (cc_tbl && rb_id_table_lookup(cc_tbl, mid, (VALUE *)&ccs)) { | ||
|     if (cc_tbl && rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { | ||
|         struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_data; | ||
|         VM_ASSERT(vm_ccs_p(ccs)); | ||
|         if (LIKELY(!METHOD_ENTRY_INVALIDATED(ccs->cme))) { | ||
| ... | ... | |
|     struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass); | ||
|     struct rb_class_cc_entries *ccs; | ||
|     VALUE ccs_data; | ||
|     if (!cc_tbl) { | ||
|         cc_tbl = RCLASS_CC_TBL(klass) = rb_id_table_create(2); | ||
|     } | ||
|     if (rb_id_table_lookup(cc_tbl, mid, (VALUE *)&ccs)) { | ||
|     if (rb_id_table_lookup(cc_tbl, mid, &ccs_data)) { | ||
|         ccs = (struct rb_class_cc_entries *)ccs_data; | ||
|         VM_ASSERT(ccs->cme == cme); | ||
|     } | ||
|     else { | ||
| ... | ... | |
| { | ||
|     rb_vm_t *vm = GET_VM(); | ||
|     const rb_callable_method_entry_t *cme; | ||
|     VALUE cme_data; | ||
|     if (!rb_id_table_lookup(vm->negative_cme_table, mid, (VALUE *)&cme)) { | ||
|     if (rb_id_table_lookup(vm->negative_cme_table, mid, &cme_data)) { | ||
|         cme = (rb_callable_method_entry_t *)cme_data; | ||
|     } | ||
|     else { | ||
|         cme = (rb_callable_method_entry_t *)rb_method_entry_alloc(mid, Qnil, Qnil, NULL); | ||
|         rb_id_table_insert(vm->negative_cme_table, mid, (VALUE)cme); | ||
|     } | ||