[macruby-changes] [619] MacRuby/trunk/objc.m
source_changes at macosforge.org
source_changes at macosforge.org
Wed Sep 24 18:37:23 PDT 2008
Revision: 619
http://trac.macosforge.org/projects/ruby/changeset/619
Author: lsansonetti at apple.com
Date: 2008-09-24 18:37:23 -0700 (Wed, 24 Sep 2008)
Log Message:
-----------
faster struct accessors
Modified Paths:
--------------
MacRuby/trunk/objc.m
Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m 2008-09-24 07:28:33 UTC (rev 618)
+++ MacRuby/trunk/objc.m 2008-09-25 01:37:23 UTC (rev 619)
@@ -2074,108 +2074,7 @@
return Data_Wrap_Struct(recv, NULL, NULL, data);
}
-static ID
-rb_bs_struct_field_ivar_id(void)
-{
- const char *frame_str;
- char ivar_name[128];
- size_t len;
-
- frame_str = rb_id2name(rb_frame_this_func());
- len = snprintf(ivar_name, sizeof ivar_name, "@%s", frame_str);
-
- if (ivar_name[len - 1] == ':')
- len--;
- if (ivar_name[len - 1] == '=')
- len--;
- ivar_name[len] = '\0';
-
- return rb_intern(ivar_name);
-}
-
static VALUE
-rb_bs_struct_get(VALUE recv)
-{
- bs_element_boxed_t *bs_boxed = rb_klass_get_bs_boxed(CLASS_OF(recv));
- bs_element_struct_t *bs_struct = (bs_element_struct_t *)bs_boxed->value;
- unsigned i;
- const char *ivar_id_str;
- VALUE *data;
-
- /* FIXME we should cache the ivar IDs somewhere in the
- * bs_element_struct_fields
- */
-
- ivar_id_str = rb_id2name(rb_bs_struct_field_ivar_id());
- ivar_id_str++; /* skip first '@' */
-
- Data_Get_Struct(recv, VALUE, data);
- assert(data != NULL);
-
- for (i = 0; i < bs_struct->fields_count; i++) {
- bs_element_struct_field_t *bs_field =
- (bs_element_struct_field_t *)&bs_struct->fields[i];
-
- if (strcmp(ivar_id_str, bs_field->name) == 0) {
- return data[i];
- }
- }
-
- rb_bug("can't find field `%s' in recv `%s'", ivar_id_str,
- RSTRING_PTR(rb_inspect(recv)));
-
- return Qnil;
-}
-
-static VALUE
-rb_bs_struct_set(VALUE recv, VALUE value)
-{
- bs_element_boxed_t *bs_boxed = rb_klass_get_bs_boxed(CLASS_OF(recv));
- bs_element_struct_t *bs_struct = (bs_element_struct_t *)bs_boxed->value;
- unsigned i;
- const char *ivar_id_str;
- VALUE *data;
- size_t pos;
-
- /* FIXME we should cache the ivar IDs somewhere in the
- * bs_element_struct_fields
- */
-
- ivar_id_str = rb_id2name(rb_bs_struct_field_ivar_id());
- ivar_id_str++; /* skip first '@' */
-
- Data_Get_Struct(recv, VALUE, data);
- assert(data != NULL);
-
- for (i = 0, pos = 0; i < bs_struct->fields_count; i++) {
- bs_element_struct_field_t *bs_field =
- (bs_element_struct_field_t *)&bs_struct->fields[i];
-
- if (strcmp(ivar_id_str, bs_field->name) == 0) {
- size_t fdata_size;
- void *fdata;
- VALUE fval;
-
- fdata_size = rb_objc_octype_to_ffitype(bs_field->type)->size;
- fdata = alloca(fdata_size);
-
- rb_objc_rval_to_ocval(value, bs_field->type, fdata);
- rb_objc_ocval_to_rval(fdata, bs_field->type, &fval);
-
- GC_WB(&data[i], fval);
-
- return value;
- }
- pos += rb_objc_octype_to_ffitype(bs_field->type)->size;
- }
-
- rb_bug("can't find field `%s' in recv `%s'", ivar_id_str,
- RSTRING_PTR(rb_inspect(recv)));
-
- return Qnil;
-}
-
-static VALUE
rb_bs_struct_to_a(VALUE recv)
{
bs_element_boxed_t *bs_boxed = rb_klass_get_bs_boxed(CLASS_OF(recv));
@@ -2325,7 +2224,108 @@
return ary;
}
+static ffi_cif *struct_reader_cif = NULL;
+static ffi_cif *struct_writer_cif = NULL;
+
+struct rb_struct_accessor_context {
+ bs_element_struct_field_t *field;
+ int num;
+};
+
static void
+rb_struct_reader_closure_handler(ffi_cif *cif, void *resp, void **args,
+ void *userdata)
+{
+ struct rb_struct_accessor_context *ctx;
+ VALUE recv, *data;
+
+ recv = (*(VALUE **)args)[0];
+ Data_Get_Struct(recv, VALUE, data);
+ assert(data != NULL);
+
+ ctx = (struct rb_struct_accessor_context *)userdata;
+ *(VALUE *)resp = data[ctx->num];
+}
+
+static void
+rb_struct_writer_closure_handler(ffi_cif *cif, void *resp, void **args,
+ void *userdata)
+{
+ struct rb_struct_accessor_context *ctx;
+ VALUE recv, value, *data, fval;
+ size_t fdata_size;
+ void *fdata;
+
+ recv = (*(VALUE **)args)[0];
+ value = (*(VALUE **)args)[1];
+ Data_Get_Struct(recv, VALUE, data);
+ assert(data != NULL);
+
+ ctx = (struct rb_struct_accessor_context *)userdata;
+
+ fdata_size = rb_objc_octype_to_ffitype(ctx->field->type)->size;
+ fdata = alloca(fdata_size);
+
+ rb_objc_rval_to_ocval(value, ctx->field->type, fdata);
+ rb_objc_ocval_to_rval(fdata, ctx->field->type, &fval);
+
+ GC_WB(&data[ctx->num], fval);
+
+ *(VALUE *)resp = fval;
+}
+
+static void
+rb_struct_gen_accessors(VALUE klass, bs_element_struct_field_t *field, int num)
+{
+ ffi_closure *closure;
+ struct rb_struct_accessor_context *ctx;
+ char buf[100];
+
+ ctx = (struct rb_struct_accessor_context *)
+ malloc(sizeof(struct rb_struct_accessor_context));
+ ctx->field = field;
+ ctx->num = num;
+
+ if (struct_reader_cif == NULL) {
+ ffi_type **args;
+
+ struct_reader_cif = (ffi_cif *)malloc(sizeof(ffi_cif));
+ args = (ffi_type **)malloc(sizeof(ffi_type *) * 1);
+ args[0] = &ffi_type_pointer;
+ if (ffi_prep_cif(struct_reader_cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_pointer, args) != FFI_OK)
+ rb_fatal("can't prepare struct_reader_cif");
+ }
+ closure = (ffi_closure *)malloc(sizeof(ffi_closure));
+ if (ffi_prep_closure(closure, struct_reader_cif,
+ rb_struct_reader_closure_handler, ctx)
+ != FFI_OK)
+ rb_fatal("can't prepare struct reader closure");
+
+ rb_define_method(klass, field->name, (VALUE(*)(ANYARGS))closure, 0);
+
+ if (struct_writer_cif == NULL) {
+ ffi_type **args;
+
+ struct_writer_cif = (ffi_cif *)malloc(sizeof(ffi_cif));
+ args = (ffi_type **)malloc(sizeof(ffi_type *) * 2);
+ args[0] = &ffi_type_pointer;
+ args[1] = &ffi_type_pointer;
+ if (ffi_prep_cif(struct_writer_cif, FFI_DEFAULT_ABI, 2,
+ &ffi_type_pointer, args) != FFI_OK)
+ rb_fatal("can't prepare struct_writer_cif");
+ }
+ closure = (ffi_closure *)malloc(sizeof(ffi_closure));
+ if (ffi_prep_closure(closure, struct_writer_cif,
+ rb_struct_writer_closure_handler, ctx)
+ != FFI_OK)
+ rb_fatal("can't prepare struct writer closure");
+
+ snprintf(buf, sizeof buf, "%s=", field->name);
+ rb_define_method(klass, buf, (VALUE(*)(ANYARGS))closure, 1);
+}
+
+static void
setup_bs_boxed_type(bs_element_type_t type, void *value)
{
bs_element_boxed_t *bs_boxed;
@@ -2344,7 +2344,6 @@
if (type == BS_ELEMENT_STRUCT) {
bs_element_struct_t *bs_struct = (bs_element_struct_t *)value;
- char buf[128];
int i;
/* Needs to be lazily created, because the type of some fields
@@ -2355,10 +2354,7 @@
if (!bs_struct->opaque) {
for (i = 0; i < bs_struct->fields_count; i++) {
bs_element_struct_field_t *field = &bs_struct->fields[i];
- rb_define_method(klass, field->name, rb_bs_struct_get, 0);
- strlcpy(buf, field->name, sizeof buf);
- strlcat(buf, "=", sizeof buf);
- rb_define_method(klass, buf, rb_bs_struct_set, 1);
+ rb_struct_gen_accessors(klass, field, i);
}
rb_define_method(klass, "to_a", rb_bs_struct_to_a, 0);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080924/a5b5996a/attachment.html
More information about the macruby-changes
mailing list