[macruby-changes] [1030] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Fri Mar 20 17:29:42 PDT 2009
Revision: 1030
http://trac.macosforge.org/projects/ruby/changeset/1030
Author: lsansonetti at apple.com
Date: 2009-03-20 17:29:41 -0700 (Fri, 20 Mar 2009)
Log Message:
-----------
now caching the node arity for both method and block dispatch
Modified Paths:
--------------
MacRuby/branches/experimental/roxor.cpp
MacRuby/branches/experimental/roxor.h
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-03-20 23:31:29 UTC (rev 1029)
+++ MacRuby/branches/experimental/roxor.cpp 2009-03-21 00:29:41 UTC (rev 1030)
@@ -345,6 +345,7 @@
Class klass;
IMP imp;
NODE *node;
+ rb_vm_arity_t arity;
} rcall;
struct {
Class klass;
@@ -1705,18 +1706,11 @@
return NULL;
}
-struct node_arity {
- short min;
- short max;
- short left_req;
- short real;
-};
-
-static inline node_arity
+static inline rb_vm_arity_t
rb_vm_node_arity(NODE *node)
{
const int type = nd_type(node);
- struct node_arity arity;
+ rb_vm_arity_t arity;
if (type == NODE_SCOPE) {
NODE *n = node->nd_args;
@@ -2097,7 +2091,7 @@
switch (nd_type(node)) {
case NODE_SCOPE:
{
- node_arity arity = rb_vm_node_arity(node);
+ rb_vm_arity_t arity = rb_vm_node_arity(node);
const int nargs = bb == NULL ? 0 : arity.real;
// Get dynamic vars.
@@ -3380,7 +3374,7 @@
params.push_back(compile_current_class());
- node_arity arity = rb_vm_node_arity(body);
+ rb_vm_arity_t arity = rb_vm_node_arity(body);
const SEL sel = mid_to_sel(mid, arity.real);
params.push_back(compile_const_pointer((void *)sel));
@@ -4274,7 +4268,7 @@
{
assert(node != NULL);
- const node_arity arity = rb_vm_node_arity(node);
+ const rb_vm_arity_t arity = rb_vm_node_arity(node);
assert(arity.real < MAX_ARITY);
assert(klass != NULL);
@@ -4344,7 +4338,7 @@
}
static inline VALUE
-__rb_vm_rcall(VALUE self, NODE *node, IMP pimp, const node_arity &arity,
+__rb_vm_rcall(VALUE self, NODE *node, IMP pimp, const rb_vm_arity_t &arity,
int argc, const VALUE *argv)
{
// TODO investigate why this function is not inlined!
@@ -4552,7 +4546,8 @@
}
static VALUE
-method_missing(VALUE obj, SEL sel, int argc, const VALUE *argv, unsigned char call_status)
+method_missing(VALUE obj, SEL sel, int argc, const VALUE *argv,
+ unsigned char call_status)
{
GET_VM()->method_missing_reason = call_status;
@@ -4601,6 +4596,9 @@
method = class_getInstanceMethod(klass, sel);
}
+#define rcache cache->as.rcall
+#define ocache cache->as.ocall
+
if (method != NULL) {
IMP imp = method_getImplementation(method);
NODE *node = GET_VM()->method_node_get(imp);
@@ -4608,20 +4606,21 @@
if (node != NULL) {
// ruby call
cache->flag = MCACHE_RCALL;
- cache->as.rcall.klass = klass;
- cache->as.rcall.imp = imp;
- cache->as.rcall.node = node;
+ rcache.klass = klass;
+ rcache.imp = imp;
+ rcache.node = node;
+ rcache.arity = rb_vm_node_arity(node);
}
else {
// objc call
cache->flag = MCACHE_OCALL;
- cache->as.ocall.klass = klass;
- cache->as.ocall.imp = imp;
- cache->as.ocall.helper = (struct ocall_helper *)malloc(sizeof(struct ocall_helper));
- cache->as.ocall.helper->bs_method = rb_bs_find_method(klass, sel);
+ ocache.klass = klass;
+ ocache.imp = imp;
+ ocache.helper = (struct ocall_helper *)malloc(
+ sizeof(struct ocall_helper));
+ ocache.helper->bs_method = rb_bs_find_method(klass, sel);
assert(rb_objc_fill_sig(self, klass, sel,
- &cache->as.ocall.helper->sig,
- cache->as.ocall.helper->bs_method));
+ &ocache.helper->sig, ocache.helper->bs_method));
}
}
else {
@@ -4631,14 +4630,14 @@
}
if (cache->flag == MCACHE_RCALL) {
- if (cache->as.rcall.klass != klass) {
+ if (rcache.klass != klass) {
goto recache;
}
- // TODO we should cache the arity
- const node_arity arity = rb_vm_node_arity(cache->as.rcall.node);
- if ((argc < arity.min) || ((arity.max != -1) && (argc > arity.max))) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, arity.min);
+ if ((argc < rcache.arity.min)
+ || ((rcache.arity.max != -1) && (argc > rcache.arity.max))) {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
+ argc, rcache.arity.min);
}
#if ROXOR_VM_DEBUG
@@ -4647,37 +4646,42 @@
class_getName(klass),
(void *)self,
sel_getName(sel),
- cache->as.rcall.imp,
+ rcache.imp,
cached ? "true" : "false");
#endif
- assert(cache->as.rcall.node != NULL);
- const int node_type = nd_type(cache->as.rcall.node);
+ assert(rcache.node != NULL);
+ const int node_type = nd_type(rcache.node);
- if (node_type == NODE_SCOPE && cache->as.rcall.node->nd_body == NULL) {
+ if (node_type == NODE_SCOPE && rcache.node->nd_body == NULL) {
// Calling an empty method, let's just return nil!
return Qnil;
}
- if (node_type == NODE_FBODY && arity.max != arity.min) {
+ if (node_type == NODE_FBODY
+ && rcache.arity.max != rcache.arity.min) {
// Calling a function defined with rb_objc_define_method with
// a negative arity, which means a different calling convention.
- if (arity.real == 2) {
- return ((VALUE (*)(VALUE, SEL, int, const VALUE *))cache->as.rcall.imp)(self, 0, argc, argv);
+ if (rcache.arity.real == 2) {
+ return ((VALUE (*)(VALUE, SEL, int, const VALUE *))rcache.imp)
+ (self, 0, argc, argv);
}
- else if (arity.real == 1) {
- return ((VALUE (*)(VALUE, SEL, ...))cache->as.rcall.imp)(self, 0, rb_ary_new4(argc, argv));
+ else if (rcache.arity.real == 1) {
+ return ((VALUE (*)(VALUE, SEL, ...))rcache.imp)
+ (self, 0, rb_ary_new4(argc, argv));
}
else {
- printf("invalid negative arity for C function %d\n", arity.real);
+ printf("invalid negative arity for C function %d\n",
+ rcache.arity.real);
abort();
}
}
- return __rb_vm_rcall(self, cache->as.rcall.node, cache->as.rcall.imp, arity, argc, argv);
+ return __rb_vm_rcall(self, rcache.node, rcache.imp, rcache.arity,
+ argc, argv);
}
else if (cache->flag == MCACHE_OCALL) {
- if (cache->as.ocall.klass != klass) {
- free(cache->as.ocall.helper);
+ if (ocache.klass != klass) {
+ free(ocache.helper);
goto recache;
}
@@ -4693,16 +4697,15 @@
return rb_objc_call2((VALUE)self,
(VALUE)klass,
sel,
- cache->as.ocall.imp,
- &cache->as.ocall.helper->sig,
- cache->as.ocall.helper->bs_method,
+ ocache.imp,
+ &ocache.helper->sig,
+ ocache.helper->bs_method,
argc,
(VALUE *)argv);
}
-printf("BOUH %s\n", (char *)sel);
+ printf("BOUH %s\n", (char *)sel);
abort();
- return NULL;
}
extern "C"
@@ -4893,10 +4896,12 @@
if (nd_type(node) == NODE_IFUNC) {
assert(llvm_function == NULL);
b->imp = (IMP)node->u1.node;
+ memset(&b->arity, 0, sizeof(rb_vm_arity_t)); // not used
}
else {
assert(llvm_function != NULL);
b->imp = GET_VM()->compile((Function *)llvm_function);
+ b->arity = rb_vm_node_arity(node);
}
b->is_lambda = true;
b->dvars_size = dvars_size;
@@ -5040,7 +5045,7 @@
arity = method_getNumberOfArguments(m) - 2;
}
else {
- node_arity n_arity = rb_vm_node_arity(node);
+ rb_vm_arity_t n_arity = rb_vm_node_arity(node);
arity = n_arity.min;
if (n_arity.min != n_arity.max) {
arity = -arity - 1;
@@ -5060,28 +5065,30 @@
return m;
}
-extern "C"
-VALUE
-rb_vm_block_eval(rb_vm_block_t *b, int argc, const VALUE *argv)
+static inline VALUE
+rb_vm_block_eval0(rb_vm_block_t *b, int argc, const VALUE *argv)
{
if (nd_type(b->node) == NODE_IFUNC) {
// Special case for blocks passed with rb_objc_block_call(), to
// preserve API compatibility.
VALUE data = (VALUE)b->node->u2.node;
-
+
VALUE (*pimp)(VALUE, VALUE, int, const VALUE *) =
(VALUE (*)(VALUE, VALUE, int, const VALUE *))b->imp;
return (*pimp)(argc == 0 ? Qnil : argv[0], data, argc, argv);
}
- else if (nd_type(b->node) == NODE_SCOPE && b->node->nd_body == NULL) {
- // Trying to call an empty block!
- return Qnil;
+ else if (nd_type(b->node) == NODE_SCOPE) {
+ if (b->node->nd_body == NULL) {
+ // Trying to call an empty block!
+ return Qnil;
+ }
}
- node_arity arity = rb_vm_node_arity(b->node);
+
int dvars_size = b->dvars_size;
+ rb_vm_arity_t arity = b->arity;
- if (dvars_size > 0 || argc < arity.min || argc > arity.max) {
+ if (dvars_size > 0 || argc < arity.min || argc > b->arity.max) {
VALUE *new_argv;
if (argc == 1 && TYPE(argv[0]) == T_ARRAY && arity.max > 1) {
// Expand the array
@@ -5093,7 +5100,7 @@
argv = new_argv;
argc = ary_len;
if (dvars_size == 0 && argc >= arity.min
- && (argc <= arity.max || arity.max == -1)) {
+ && (argc <= arity.max || b->arity.max == -1)) {
return __rb_vm_rcall(b->self, b->node, b->imp, arity, argc,
argv);
}
@@ -5102,7 +5109,7 @@
if (argc <= arity.min) {
new_argc = dvars_size + arity.min;
}
- else if (argc > arity.max && arity.max != -1) {
+ else if (argc > arity.max && b->arity.max != -1) {
new_argc = dvars_size + arity.max;
}
else {
@@ -5127,8 +5134,8 @@
}
}
#if ROXOR_VM_DEBUG
- printf("yield block %p argc %d arity %d dvars %d\n", b, argc, arity.real,
- b->dvars_size);
+ printf("yield block %p argc %d arity %d dvars %d\n", b, argc,
+ arity.real, b->dvars_size);
#endif
// We need to preserve dynamic variable slots here because our block may
@@ -5137,9 +5144,9 @@
// previous slots are not restored.
VALUE **old_dvars;
- if (b->dvars_size > 0) {
- old_dvars = (VALUE **)alloca(sizeof(VALUE *) * b->dvars_size);
- memcpy(old_dvars, b->dvars, sizeof(VALUE) * b->dvars_size);
+ if (dvars_size > 0) {
+ old_dvars = (VALUE **)alloca(sizeof(VALUE *) * dvars_size);
+ memcpy(old_dvars, b->dvars, sizeof(VALUE) * dvars_size);
}
else {
old_dvars = NULL;
@@ -5148,7 +5155,7 @@
VALUE v = __rb_vm_rcall(b->self, b->node, b->imp, arity, argc, argv);
if (old_dvars != NULL) {
- memcpy(b->dvars, old_dvars, sizeof(VALUE) * b->dvars_size);
+ memcpy(b->dvars, old_dvars, sizeof(VALUE) * dvars_size);
}
return v;
@@ -5156,18 +5163,31 @@
extern "C"
VALUE
-rb_vm_yield(int argc, const VALUE *argv)
+rb_vm_block_eval(rb_vm_block_t *b, int argc, const VALUE *argv)
{
+ return rb_vm_block_eval0(b, argc, argv);
+}
+
+static inline VALUE
+rb_vm_yield0(int argc, const VALUE *argv)
+{
rb_vm_block_t *b = GET_VM()->top_block();
GET_VM()->pop_block();
- VALUE retval = rb_vm_block_eval(b, argc, argv);
+ VALUE retval = rb_vm_block_eval0(b, argc, argv);
GET_VM()->push_block(b);
return retval;
}
extern "C"
+VALUE
+rb_vm_yield(int argc, const VALUE *argv)
+{
+ return rb_vm_yield0(argc, argv);
+}
+
+extern "C"
VALUE
rb_vm_yield_args(int argc, ...)
{
@@ -5181,7 +5201,7 @@
}
va_end(ar);
}
- return rb_vm_yield(argc, argv);
+ return rb_vm_yield0(argc, argv);
}
extern "C"
Modified: MacRuby/branches/experimental/roxor.h
===================================================================
--- MacRuby/branches/experimental/roxor.h 2009-03-20 23:31:29 UTC (rev 1029)
+++ MacRuby/branches/experimental/roxor.h 2009-03-21 00:29:41 UTC (rev 1030)
@@ -79,8 +79,16 @@
rb_vm_method_t *rb_vm_get_method(VALUE klass, VALUE obj, ID mid, int scope);
typedef struct {
+ short min;
+ short max;
+ short left_req;
+ short real;
+} rb_vm_arity_t;
+
+typedef struct {
VALUE self;
NODE *node;
+ rb_vm_arity_t arity;
IMP imp;
bool is_lambda;
int dvars_size;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090320/812b1ac4/attachment-0001.html>
More information about the macruby-changes
mailing list