Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

implemented super from a block

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@2531 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information...
commit 77f9768b2f98cc807fd1467e3e3cb14a39b20433 1 parent 0082403
Laurent Sansonetti authored
Showing with 97 additions and 36 deletions.
  1. +58 −11 compiler.cpp
  2. +2 −0  compiler.h
  3. +37 −25 vm.cpp
View
69 compiler.cpp
@@ -126,6 +126,7 @@ RoxorCompiler::RoxorCompiler(void)
setjmpFunc = NULL;
setScopeFunc = NULL;
setCurrentClassFunc = NULL;
+ getCacheFunc = NULL;
#if __LP64__
RubyObjTy = IntTy = Type::Int64Ty;
@@ -532,6 +533,24 @@ RoxorCompiler::compile_const_global_string(const char *str,
}
Value *
+RoxorCompiler::compile_get_mcache(Value *sel, bool super)
+{
+ if (getCacheFunc == NULL) {
+ // void *rb_vm_get_call_cache2(SEL sel, unsigned char super);
+ getCacheFunc =
+ cast<Function>(module->getOrInsertFunction(
+ "rb_vm_get_call_cache2", PtrTy, PtrTy, Type::Int8Ty,
+ NULL));
+ }
+
+ std::vector<Value *> params;
+ params.push_back(sel);
+ params.push_back(ConstantInt::get(Type::Int8Ty, super ? 1 : 0));
+
+ return CallInst::Create(getCacheFunc, params.begin(), params.end(), "", bb);
+}
+
+Value *
RoxorCompiler::compile_mcache(SEL sel, bool super)
{
struct mcache *cache = GET_CORE()->method_cache_get(sel, super);
@@ -3843,7 +3862,9 @@ RoxorCompiler::compile_node(NODE *node)
if (super_call) {
mid = current_mid;
}
- assert(mid > 0);
+ else {
+ assert(mid > 0);
+ }
Function::ArgumentListType &fargs =
bb->getParent()->getArgumentList();
@@ -3922,16 +3943,33 @@ RoxorCompiler::compile_node(NODE *node)
// Prepare the dispatcher parameters.
std::vector<Value *> params;
- // Method cache.
- const SEL sel = mid_to_sel(mid, positive_arity ? 1 : 0);
- params.push_back(compile_mcache(sel, super_call));
+ // Method cache (and prepare the selector).
+ Value *sel_val;
+ SEL sel;
+ if (mid != 0) {
+ sel = mid_to_sel(mid, positive_arity ? 1 : 0);
+ params.push_back(compile_mcache(sel, super_call));
+ sel_val = compile_sel(sel);
+ }
+ else {
+ assert(super_call);
+ sel = 0;
+ // A super call outside a method definition (probably
+ // in a block). Retrieve the SEL as the second parameter
+ // of the current function.
+ Function *f = bb->getParent();
+ Function::arg_iterator arg = f->arg_begin();
+ arg++; // skip self
+ sel_val = arg;
+ params.push_back(compile_get_mcache(sel_val, true));
+ }
// Self.
params.push_back(recv == NULL ? current_self
: compile_node(recv));
// Selector.
- params.push_back(compile_sel(sel));
+ params.push_back(sel_val);
// RubySpec requires that we compile the block *after* the
// arguments, so we do pass NULL as the block for the moment.
@@ -3954,11 +3992,17 @@ RoxorCompiler::compile_node(NODE *node)
// Arguments.
int argc = 0;
if (nd_type(node) == NODE_ZSUPER) {
- params.push_back(ConstantInt::get(Type::Int32Ty,
- fargs_arity));
+ const int arity = mid == 0
+ ? fargs_arity - 2 // skip dvars and current_block
+ : fargs_arity;
+ params.push_back(ConstantInt::get(Type::Int32Ty, arity));
Function::ArgumentListType::iterator iter = fargs.begin();
iter++; // skip self
iter++; // skip sel
+ if (mid == 0) {
+ iter++; // skip dvars
+ iter++; // skip current_block
+ }
const int rest_pos = current_arity.max == -1
? (current_arity.left_req
+ (current_arity.real - current_arity.min - 1))
@@ -6608,28 +6652,31 @@ RoxorCompiler::compile_block_caller(rb_vm_block_t *block)
{
// VALUE foo(VALUE rcv, SEL sel, int argc, VALUE *argv)
// {
- // return rb_vm_block_eval2(block, rcv, argc, argv);
+ // return rb_vm_block_eval2(block, rcv, sel, argc, argv);
// }
Function *f = cast<Function>(module->getOrInsertFunction("",
RubyObjTy, RubyObjTy, PtrTy, Type::Int32Ty, RubyObjPtrTy,
NULL));
Function::arg_iterator arg = f->arg_begin();
Value *rcv = arg++;
- arg++; // sel
+ Value *sel = arg++;
Value *argc = arg++;
Value *argv = arg++;
bb = BasicBlock::Create("EntryBlock", f);
if (blockEvalFunc == NULL) {
+ // VALUE rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, SEL sel,
+ // int argc, const VALUE *argv)
blockEvalFunc = cast<Function>(module->getOrInsertFunction(
"rb_vm_block_eval2",
- RubyObjTy, PtrTy, RubyObjTy, Type::Int32Ty, RubyObjPtrTy,
- NULL));
+ RubyObjTy, PtrTy, RubyObjTy, PtrTy, Type::Int32Ty,
+ RubyObjPtrTy, NULL));
}
std::vector<Value *> params;
params.push_back(compile_const_pointer(block));
params.push_back(rcv);
+ params.push_back(sel);
params.push_back(argc);
params.push_back(argv);
View
2  compiler.h
@@ -179,6 +179,7 @@ class RoxorCompiler {
Function *setjmpFunc;
Function *setScopeFunc;
Function *setCurrentClassFunc;
+ Function *getCacheFunc;
Constant *zeroVal;
Constant *oneVal;
@@ -265,6 +266,7 @@ class RoxorCompiler {
void compile_return_from_block_handler(int id);
Value *compile_jump(NODE *node);
virtual Value *compile_mcache(SEL sel, bool super);
+ Value *compile_get_mcache(Value *sel, bool super);
virtual Value *compile_ccache(ID id);
virtual Instruction *compile_sel(SEL sel, bool add_to_bb=true) {
return compile_const_pointer(sel, PtrTy, add_to_bb);
View
62 vm.cpp
@@ -816,7 +816,8 @@ RoxorCore::class_can_have_ivar_slots(VALUE klass)
const long klass_version = RCLASS_VERSION(klass);
if ((klass_version & RCLASS_IS_RUBY_CLASS) != RCLASS_IS_RUBY_CLASS
|| (klass_version & RCLASS_IS_OBJECT_SUBCLASS)
- != RCLASS_IS_OBJECT_SUBCLASS) {
+ != RCLASS_IS_OBJECT_SUBCLASS
+ || klass == rb_cClass || klass == rb_cModule) {
return false;
}
return true;
@@ -1070,8 +1071,9 @@ VALUE
rb_vm_ivar_get(VALUE obj, ID name, int *slot_cache)
{
#if ROXOR_VM_DEBUG
- printf("get ivar %p.%s slot %d\n", (void *)obj, rb_id2name(name),
- slot_cache == NULL ? -1 : *slot_cache);
+ printf("get ivar <%s %p>.%s slot %d\n",
+ class_getName((Class)CLASS_OF(obj)), (void *)obj,
+ rb_id2name(name), slot_cache == NULL ? -1 : *slot_cache);
#endif
if (slot_cache == NULL || *slot_cache == -1) {
return rb_ivar_get(obj, name);
@@ -1867,11 +1869,11 @@ RoxorCore::copy_methods(Class from_class, Class to_class)
continue;
}
-#if ROXOR_DEBUG_VM
+#if ROXOR_VM_DEBUG
printf("lazy copy %c[%s %s] to %s\n",
class_isMetaClass(from_class) ? '+' : '-',
class_getName(from_class),
- sel_getName(method_getName(method)),
+ sel_getName(sel),
class_getName(to_class));
#endif
@@ -2215,8 +2217,9 @@ __rb_vm_fix_args(const VALUE *argv, VALUE *new_argv,
}
static force_inline VALUE
-__rb_vm_bcall(VALUE self, VALUE dvars, rb_vm_block_t *b,
- IMP pimp, const rb_vm_arity_t &arity, int argc, const VALUE *argv)
+__rb_vm_bcall(VALUE self, SEL sel, VALUE dvars, rb_vm_block_t *b,
+ IMP pimp, const rb_vm_arity_t &arity, int argc,
+ const VALUE *argv)
{
if ((arity.real != argc) || (arity.max == -1)) {
VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * arity.real);
@@ -2231,25 +2234,25 @@ __rb_vm_bcall(VALUE self, VALUE dvars, rb_vm_block_t *b,
switch (argc) {
case 0:
- return (*imp)(self, 0, dvars, b);
+ return (*imp)(self, sel, dvars, b);
case 1:
- return (*imp)(self, 0, dvars, b, argv[0]);
+ return (*imp)(self, sel, dvars, b, argv[0]);
case 2:
- return (*imp)(self, 0, dvars, b, argv[0], argv[1]);
+ return (*imp)(self, sel, dvars, b, argv[0], argv[1]);
case 3:
- return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2]);
+ return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2]);
case 4:
- return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3]);
+ return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3]);
case 5:
- return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4]);
+ return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4]);
case 6:
- return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
+ return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
case 7:
- return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
+ return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
case 8:
- return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
+ return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
case 9:
- return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
+ return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
}
printf("invalid argc %d\n", argc);
abort();
@@ -3018,7 +3021,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE self, Class klass,
return method_missing((VALUE)self, sel, block, argc, argv, status);
}
-#define MAX_DISPATCH_ARGS 200
+#define MAX_DISPATCH_ARGS 500
static force_inline int
__rb_vm_resolve_args(VALUE *argv, int argc, va_list ar)
@@ -3807,6 +3810,13 @@ rb_vm_get_call_cache(SEL sel)
return GET_CORE()->method_cache_get(sel, false);
}
+extern "C"
+void *
+rb_vm_get_call_cache2(SEL sel, unsigned char super)
+{
+ return GET_CORE()->method_cache_get(sel, super);
+}
+
// Should be used inside a method implementation.
extern "C"
int
@@ -4002,7 +4012,8 @@ rb_vm_make_curry_proc(VALUE proc, VALUE passed, VALUE arity)
}
static inline VALUE
-rb_vm_block_eval0(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
+rb_vm_block_eval0(rb_vm_block_t *b, SEL sel, VALUE self, int argc,
+ const VALUE *argv)
{
if ((b->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
// Special case for blocks passed with rb_objc_block_call(), to
@@ -4092,7 +4103,7 @@ rb_vm_block_eval0(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
return rb_vm_call_with_cache2(m->cache, NULL, m->recv, m->oclass,
m->sel, argc, argv);
}
- return __rb_vm_bcall(self, (VALUE)b->dvars, b, b->imp, b->arity,
+ return __rb_vm_bcall(self, sel, (VALUE)b->dvars, b, b->imp, b->arity,
argc, argv);
}
@@ -4100,15 +4111,16 @@ extern "C"
VALUE
rb_vm_block_eval(rb_vm_block_t *b, int argc, const VALUE *argv)
{
- return rb_vm_block_eval0(b, b->self, argc, argv);
+ return rb_vm_block_eval0(b, NULL, b->self, argc, argv);
}
extern "C"
VALUE
-rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
+rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, SEL sel, int argc,
+ const VALUE *argv)
{
// TODO check given arity and raise exception
- return rb_vm_block_eval0(b, self, argc, argv);
+ return rb_vm_block_eval0(b, sel, self, argc, argv);
}
static inline VALUE
@@ -4134,7 +4146,7 @@ rb_vm_yield0(int argc, const VALUE *argv)
}
} finalizer(vm, b);
- return rb_vm_block_eval0(b, b->self, argc, argv);
+ return rb_vm_block_eval0(b, NULL, b->self, argc, argv);
}
extern "C"
@@ -4176,7 +4188,7 @@ rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv)
}
} finalizer(vm, b, old_class, old_self);
- return rb_vm_block_eval0(b, b->self, argc, argv);
+ return rb_vm_block_eval0(b, NULL, b->self, argc, argv);
}
extern "C"
Please sign in to comment.
Something went wrong with that request. Please try again.