Skip to content

Instantly share code, notes, and snippets.

@tenderlove
Created February 23, 2015 00:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tenderlove/a8e30c1f764040de7536 to your computer and use it in GitHub Desktop.
Save tenderlove/a8e30c1f764040de7536 to your computer and use it in GitHub Desktop.
diff --git a/insns.def b/insns.def
index 81aca8f..1c14bb9 100644
--- a/insns.def
+++ b/insns.def
@@ -318,8 +318,15 @@ putspecialobject
val = rb_mRubyVMFrozenCore;
break;
case VM_SPECIAL_OBJECT_CBASE:
- val = vm_get_cbase(GET_ISEQ(), GET_EP());
+ {
+ rb_control_frame_t *class_cfp = find_magic_class(th->cfp);
+ if (class_cfp) {
+ val = class_cfp->cklass;
+ } else {
+ val = vm_get_cbase(GET_ISEQ(), GET_EP());
+ }
break;
+ }
case VM_SPECIAL_OBJECT_CONST_BASE:
val = vm_get_const_base(GET_ISEQ(), GET_EP());
break;
@@ -914,6 +921,7 @@ defineclass
(VALUE val)
{
VALUE klass;
+ rb_control_frame_t *cft;
rb_vm_defineclass_type_t type = VM_DEFINECLASS_TYPE(flags);
switch (type) {
@@ -994,10 +1002,12 @@ defineclass
COPY_CREF(class_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC, NULL));
/* enter scope */
- vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS,
+ cft = vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS,
klass, 0, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
class_iseq->iseq_encoded, GET_SP(),
class_iseq->local_size, 0, class_iseq->stack_max);
+ cft->cklass = klass;
+
RESTORE_REGS();
NEXT_INSN();
}
diff --git a/vm_core.h b/vm_core.h
index 8fd8ef4..32da076 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -529,6 +529,7 @@ typedef struct rb_control_frame_struct {
#if VM_DEBUG_BP_CHECK
VALUE *bp_check; /* cfp[10] */
#endif
+ VALUE cklass;
} rb_control_frame_t;
typedef struct rb_block_struct {
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index eb34119..b7e5794 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -287,6 +287,21 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
return cref;
}
+static rb_control_frame_t *
+find_magic_class(rb_control_frame_t *frame)
+{
+ rb_thread_t *th = GET_THREAD();
+ rb_control_frame_t *cfp_limit;
+
+ cfp_limit = (rb_control_frame_t *)(th->stack + th->stack_size);
+ while (cfp_limit > frame) {
+ if (frame->flag == VM_FRAME_MAGIC_CLASS)
+ return frame;
+ frame = RUBY_VM_PREVIOUS_CONTROL_FRAME(frame);
+ }
+ return 0;
+}
+
static inline VALUE
vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep)
{
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment