[macruby-changes] [235] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed May 28 18:23:04 PDT 2008
Revision: 235
http://trac.macosforge.org/projects/ruby/changeset/235
Author: lsansonetti at apple.com
Date: 2008-05-28 18:23:04 -0700 (Wed, 28 May 2008)
Log Message:
-----------
introducing inline cache for struct types
Modified Paths:
--------------
MacRuby/trunk/objc.m
MacRuby/trunk/test/ruby/test_objc.rb
Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m 2008-05-28 23:51:40 UTC (rev 234)
+++ MacRuby/trunk/objc.m 2008-05-29 01:23:04 UTC (rev 235)
@@ -503,6 +503,7 @@
bool *success)
{
void *data;
+ size_t soffset;
assert(bs_boxed->ffi_type != NULL);
@@ -515,6 +516,8 @@
*success = false;
return NULL;
}
+
+ Data_Get_Struct(rval, void, data);
if (bs_boxed->type == BS_ELEMENT_STRUCT) {
bs_element_struct_t *bs_struct;
@@ -527,25 +530,23 @@
* could have been modified as a copy in the Ruby world.
*/
for (i = 0; i < bs_struct->fields_count; i++) {
- char buf[128];
- ID ivar_id;
-
- snprintf(buf, sizeof buf, "@%s", bs_struct->fields[i].name);
- ivar_id = rb_intern(buf);
- if (rb_ivar_defined(rval, ivar_id) == Qtrue) {
- VALUE val;
-
- val = rb_ivar_get(rval, ivar_id);
+ if (((VALUE *)data)[i] != 0) {
+ char buf[512];
snprintf(buf, sizeof buf, "%s=", bs_struct->fields[i].name);
- rb_funcall(rval, rb_intern(buf), 1, val);
+ rb_funcall(rval, rb_intern(buf), 1, ((VALUE *)data)[i]);
+ ((VALUE *)data)[i] = 0;
}
}
+
+ soffset = bs_struct->fields_count * sizeof(VALUE);
}
+ else {
+ soffset = 0;
+ }
- Data_Get_Struct(rval, void, data);
*success = true;
- return data;
+ return data + soffset;
}
static void
@@ -563,6 +564,7 @@
rb_bs_boxed_new_from_ocdata(bs_element_boxed_t *bs_boxed, void *ocval)
{
void *data;
+ size_t soffset;
if (ocval == NULL)
return Qnil;
@@ -572,9 +574,16 @@
rb_bs_boxed_assert_ffitype_ok(bs_boxed);
- data = xmalloc(bs_boxed->ffi_type->size);
- memcpy(data, ocval, bs_boxed->ffi_type->size);
+ soffset = 0;
+ if (bs_boxed->type == BS_ELEMENT_STRUCT) {
+ soffset = ((bs_element_struct_t *)bs_boxed->value)->fields_count
+ * sizeof(VALUE);
+ }
+ data = xmalloc(soffset + bs_boxed->ffi_type->size);
+ memset(data, 0, soffset);
+ memcpy(data + soffset, ocval, bs_boxed->ffi_type->size);
+
return Data_Wrap_Struct(bs_boxed->klass, NULL, NULL, data);
}
@@ -1653,14 +1662,18 @@
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
argc, bs_struct->fields_count);
- data = (void *)xmalloc(bs_boxed->ffi_type->size);
- memset(data, 0, bs_boxed->ffi_type->size);
+ pos = 0;
+ if (bs_boxed->type == BS_ELEMENT_STRUCT)
+ pos = bs_struct->fields_count * sizeof(VALUE);
- for (i = 0, pos = 0; i < argc; i++) {
+ data = (void *)xmalloc(pos + bs_boxed->ffi_type->size);
+ memset(data, 0, pos + bs_boxed->ffi_type->size);
+
+ for (i = 0; i < argc; i++) {
bs_element_struct_field_t *bs_field =
(bs_element_struct_field_t *)&bs_struct->fields[i];
- rb_objc_rval_to_ocval(argv[i], bs_field->type, data + pos);
+ rb_objc_rval_to_ocval(argv[i], bs_field->type, data + pos);
pos += rb_objc_octype_to_ffitype(bs_field->type)->size;
}
@@ -1682,10 +1695,17 @@
return rb_intern(ivar_name);
}
-static void *
-rb_bs_struct_get_field_data(bs_element_struct_t *bs_struct, VALUE recv,
- ID ivar_id, char **octype)
+static VALUE
+rb_bs_struct_get_field(bs_element_struct_t *bs_struct, VALUE recv,
+ ID ivar_id)
{
+}
+
+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;
void *data;
@@ -1695,67 +1715,78 @@
* bs_element_struct_fields
*/
- ivar_id_str = rb_id2name(ivar_id);
+ ivar_id_str = rb_id2name(rb_bs_struct_field_ivar_id());
ivar_id_str++; /* skip first '@' */
Data_Get_Struct(recv, void, data);
assert(data != NULL);
- for (i = 0, pos = 0; i < bs_struct->fields_count; i++) {
+ pos = bs_struct->fields_count * sizeof(VALUE);
+
+ 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) {
- *octype = bs_field->type;
- return data + pos;
+ VALUE val;
+
+ val = ((VALUE *)data)[i];
+ if (val == 0) {
+ rb_objc_ocval_to_rbval(data + pos, bs_field->type, &val);
+ ((VALUE *)data)[i] = val;
+ }
+ return val;
}
pos += rb_objc_octype_to_ffitype(bs_field->type)->size;
}
rb_bug("can't find field `%s' in recv `%s'", ivar_id_str,
RSTRING_CPTR(rb_inspect(recv)));
+
+ return Qnil;
}
static VALUE
-rb_bs_struct_get(VALUE recv)
+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;
- ID ivar_id;
- VALUE result;
+ bs_element_struct_t *bs_struct = (bs_element_struct_t *)bs_boxed->value;
+ unsigned i;
+ const char *ivar_id_str;
+ void *data;
+ size_t pos;
- ivar_id = rb_bs_struct_field_ivar_id();
+ /* FIXME we should cache the ivar IDs somewhere in the
+ * bs_element_struct_fields
+ */
- if (rb_ivar_defined(recv, ivar_id) == Qfalse) {
- void *data;
- char *octype;
- BOOL ok;
+ ivar_id_str = rb_id2name(rb_bs_struct_field_ivar_id());
+ ivar_id_str++; /* skip first '@' */
- data = rb_bs_struct_get_field_data(bs_struct, recv, ivar_id, &octype);
- rb_objc_ocval_to_rbval(data, octype, &result);
- rb_ivar_set(recv, ivar_id, result);
+ Data_Get_Struct(recv, void, data);
+ assert(data != NULL);
+
+ pos = bs_struct->fields_count * sizeof(VALUE);
+
+ 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) {
+ rb_objc_rval_to_ocval(value, bs_field->type, data + pos);
+ /* We do not update the cache because `value' may have been
+ * transformed (ex. fixnum to float).
+ */
+ ((VALUE *)data)[i] = 0;
+ return value;
+ }
+ pos += rb_objc_octype_to_ffitype(bs_field->type)->size;
}
- else {
- result = rb_ivar_get(recv, ivar_id);
- }
-
- return result;
-}
-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;
- ID ivar_id;
- void *data;
- char *octype;
+ rb_bug("can't find field `%s' in recv `%s'", ivar_id_str,
+ RSTRING_CPTR(rb_inspect(recv)));
- ivar_id = rb_bs_struct_field_ivar_id();
- data = rb_bs_struct_get_field_data(bs_struct, recv, ivar_id, &octype);
- rb_objc_rval_to_ocval(value, octype, data);
- rb_ivar_set(recv, ivar_id, value);
-
- return value;
+ return Qnil;
}
static VALUE
Modified: MacRuby/trunk/test/ruby/test_objc.rb
===================================================================
--- MacRuby/trunk/test/ruby/test_objc.rb 2008-05-28 23:51:40 UTC (rev 234)
+++ MacRuby/trunk/test/ruby/test_objc.rb 2008-05-29 01:23:04 UTC (rev 235)
@@ -94,11 +94,15 @@
def test_struct_create
p = NSPoint.new
assert_kind_of(NSPoint, p)
+ assert_kind_of(Float, p.x)
assert_equal(0.0, p.x)
+ assert_kind_of(Float, p.y)
assert_equal(0.0, p.y)
p = NSPoint.new(1, 2)
+ assert_kind_of(Float, p.x)
assert_equal(1.0, p.x)
+ assert_kind_of(Float, p.y)
assert_equal(2.0, p.y)
assert_raise(ArgumentError) { NSPoint.new(1) }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080528/2f471b31/attachment-0001.htm
More information about the macruby-changes
mailing list