Joshua Haberman 6 năm trước cách đây
mục cha
commit
1c9fb9d45b

+ 3 - 0
ruby/ext/google/protobuf_c/defs.c

@@ -487,6 +487,9 @@ void Descriptor_mark(void* _self) {
   Descriptor* self = _self;
   Descriptor* self = _self;
   rb_gc_mark(self->klass);
   rb_gc_mark(self->klass);
   rb_gc_mark(self->descriptor_pool);
   rb_gc_mark(self->descriptor_pool);
+  if (self->layout && self->layout->empty_template) {
+    layout_mark(self->layout, self->layout->empty_template);
+  }
 }
 }
 
 
 void Descriptor_free(void* _self) {
 void Descriptor_free(void* _self) {

+ 1 - 1
ruby/ext/google/protobuf_c/encode_decode.c

@@ -690,7 +690,7 @@ void add_handlers_for_message(const void *closure, upb_handlers *h) {
   // class is actually built, so to work around this, we just create the layout
   // class is actually built, so to work around this, we just create the layout
   // (and handlers, in the class-building function) on-demand.
   // (and handlers, in the class-building function) on-demand.
   if (desc->layout == NULL) {
   if (desc->layout == NULL) {
-    desc->layout = create_layout(desc);
+    create_layout(desc);
   }
   }
 
 
   // If this is a mapentry message type, set up a special set of handlers and
   // If this is a mapentry message type, set up a special set of handlers and

+ 1 - 1
ruby/ext/google/protobuf_c/message.c

@@ -64,7 +64,7 @@ VALUE Message_alloc(VALUE klass) {
   VALUE ret;
   VALUE ret;
 
 
   if (desc->layout == NULL) {
   if (desc->layout == NULL) {
-    desc->layout = create_layout(desc);
+    create_layout(desc);
   }
   }
 
 
   msg = (MessageHeader*)ALLOC_N(uint8_t,
   msg = (MessageHeader*)ALLOC_N(uint8_t,

+ 2 - 1
ruby/ext/google/protobuf_c/protobuf.h

@@ -509,11 +509,12 @@ struct MessageField {
 struct MessageLayout {
 struct MessageLayout {
   const Descriptor* desc;
   const Descriptor* desc;
   const upb_msgdef* msgdef;
   const upb_msgdef* msgdef;
+  void* empty_template;  // Can memcpy() onto a layout to clear it.
   MessageField* fields;
   MessageField* fields;
   size_t size;
   size_t size;
 };
 };
 
 
-MessageLayout* create_layout(const Descriptor* desc);
+void create_layout(Descriptor* desc);
 void free_layout(MessageLayout* layout);
 void free_layout(MessageLayout* layout);
 bool field_contains_hasbit(MessageLayout* layout,
 bool field_contains_hasbit(MessageLayout* layout,
                  const upb_fielddef* field);
                  const upb_fielddef* field);

+ 18 - 5
ruby/ext/google/protobuf_c/storage.c

@@ -473,7 +473,7 @@ static size_t align_up_to(size_t offset, size_t granularity) {
   return (offset + granularity - 1) & ~(granularity - 1);
   return (offset + granularity - 1) & ~(granularity - 1);
 }
 }
 
 
-MessageLayout* create_layout(const Descriptor* desc) {
+void create_layout(Descriptor* desc) {
   const upb_msgdef *msgdef = desc->msgdef;
   const upb_msgdef *msgdef = desc->msgdef;
   MessageLayout* layout = ALLOC(MessageLayout);
   MessageLayout* layout = ALLOC(MessageLayout);
   int nfields = upb_msgdef_numfields(msgdef);
   int nfields = upb_msgdef_numfields(msgdef);
@@ -482,7 +482,10 @@ MessageLayout* create_layout(const Descriptor* desc) {
   size_t off = 0;
   size_t off = 0;
   size_t hasbit = 0;
   size_t hasbit = 0;
 
 
+  layout->empty_template = NULL;
   layout->desc = desc;
   layout->desc = desc;
+  desc->layout = layout;
+
   layout->fields = ALLOC_N(MessageField, nfields);
   layout->fields = ALLOC_N(MessageField, nfields);
 
 
   for (upb_msg_field_begin(&it, msgdef);
   for (upb_msg_field_begin(&it, msgdef);
@@ -584,10 +587,19 @@ MessageLayout* create_layout(const Descriptor* desc) {
   layout->size = off;
   layout->size = off;
   layout->msgdef = msgdef;
   layout->msgdef = msgdef;
 
 
-  return layout;
+  // Create the empty message template.
+  layout->empty_template = ALLOC_N(char, layout->size);
+  memset(layout->empty_template, 0, layout->size);
+
+  for (upb_msg_field_begin(&it, layout->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    layout_clear(layout, layout->empty_template, upb_msg_iter_field(&it));
+  }
 }
 }
 
 
 void free_layout(MessageLayout* layout) {
 void free_layout(MessageLayout* layout) {
+  xfree(layout->empty_template);
   xfree(layout->fields);
   xfree(layout->fields);
   xfree(layout);
   xfree(layout);
 }
 }
@@ -868,15 +880,16 @@ void layout_set(MessageLayout* layout,
   }
   }
 }
 }
 
 
-void layout_init(MessageLayout* layout,
-                 void* storage) {
-
+void layout_init(MessageLayout* layout, void* storage) {
+  memcpy(storage, layout->empty_template, layout->size);
+  /*
   upb_msg_field_iter it;
   upb_msg_field_iter it;
   for (upb_msg_field_begin(&it, layout->msgdef);
   for (upb_msg_field_begin(&it, layout->msgdef);
        !upb_msg_field_done(&it);
        !upb_msg_field_done(&it);
        upb_msg_field_next(&it)) {
        upb_msg_field_next(&it)) {
     layout_clear(layout, storage, upb_msg_iter_field(&it));
     layout_clear(layout, storage, upb_msg_iter_field(&it));
   }
   }
+  */
 }
 }
 
 
 void layout_mark(MessageLayout* layout, void* storage) {
 void layout_mark(MessageLayout* layout, void* storage) {