[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