Unverified Commit 35b0a879 authored by Joshua Haberman's avatar Joshua Haberman Committed by GitHub

Merge pull request #6521 from haberman/layout_mark

Optimized layout_mark() for Ruby
parents 6b3024f6 c02a6fbf
...@@ -155,6 +155,9 @@ static const void *newoneofhandlerdata(upb_handlers *h, ...@@ -155,6 +155,9 @@ static const void *newoneofhandlerdata(upb_handlers *h,
// create a separate ID space. In addition, using the field tag number here // create a separate ID space. In addition, using the field tag number here
// lets us easily look up the field in the oneof accessor. // lets us easily look up the field in the oneof accessor.
hd->oneof_case_num = upb_fielddef_number(f); hd->oneof_case_num = upb_fielddef_number(f);
if (is_value_field(f)) {
hd->oneof_case_num |= ONEOF_CASE_MASK;
}
hd->subklass = field_type_class(desc->layout, f); hd->subklass = field_type_class(desc->layout, f);
upb_handlers_addcleanup(h, hd, xfree); upb_handlers_addcleanup(h, hd, xfree);
return hd; return hd;
...@@ -706,12 +709,13 @@ void add_handlers_for_message(const void *closure, upb_handlers *h) { ...@@ -706,12 +709,13 @@ void add_handlers_for_message(const void *closure, upb_handlers *h) {
!upb_msg_field_done(&i); !upb_msg_field_done(&i);
upb_msg_field_next(&i)) { upb_msg_field_next(&i)) {
const upb_fielddef *f = upb_msg_iter_field(&i); const upb_fielddef *f = upb_msg_iter_field(&i);
const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset + size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset +
sizeof(MessageHeader); sizeof(MessageHeader);
if (upb_fielddef_containingoneof(f)) { if (oneof) {
size_t oneof_case_offset = size_t oneof_case_offset =
desc->layout->fields[upb_fielddef_index(f)].case_offset + desc->layout->oneofs[upb_oneofdef_index(oneof)].case_offset +
sizeof(MessageHeader); sizeof(MessageHeader);
add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc); add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc);
} else if (is_map_field(f)) { } else if (is_map_field(f)) {
...@@ -1256,19 +1260,18 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc, ...@@ -1256,19 +1260,18 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
!upb_msg_field_done(&i); !upb_msg_field_done(&i);
upb_msg_field_next(&i)) { upb_msg_field_next(&i)) {
upb_fielddef *f = upb_msg_iter_field(&i); upb_fielddef *f = upb_msg_iter_field(&i);
const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
bool is_matching_oneof = false; bool is_matching_oneof = false;
uint32_t offset = uint32_t offset =
desc->layout->fields[upb_fielddef_index(f)].offset + desc->layout->fields[upb_fielddef_index(f)].offset +
sizeof(MessageHeader); sizeof(MessageHeader);
if (upb_fielddef_containingoneof(f)) { if (oneof) {
uint32_t oneof_case_offset = uint32_t oneof_case =
desc->layout->fields[upb_fielddef_index(f)].case_offset + slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
sizeof(MessageHeader);
// For a oneof, check that this field is actually present -- skip all the // For a oneof, check that this field is actually present -- skip all the
// below if not. // below if not.
if (DEREF(msg, oneof_case_offset, uint32_t) != if (oneof_case != upb_fielddef_number(f)) {
upb_fielddef_number(f)) {
continue; continue;
} }
// Otherwise, fall through to the appropriate singular-field handler // Otherwise, fall through to the appropriate singular-field handler
...@@ -1464,18 +1467,17 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) { ...@@ -1464,18 +1467,17 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
!upb_msg_field_done(&it); !upb_msg_field_done(&it);
upb_msg_field_next(&it)) { upb_msg_field_next(&it)) {
upb_fielddef *f = upb_msg_iter_field(&it); upb_fielddef *f = upb_msg_iter_field(&it);
const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
uint32_t offset = uint32_t offset =
desc->layout->fields[upb_fielddef_index(f)].offset + desc->layout->fields[upb_fielddef_index(f)].offset +
sizeof(MessageHeader); sizeof(MessageHeader);
if (upb_fielddef_containingoneof(f)) { if (oneof) {
uint32_t oneof_case_offset = uint32_t oneof_case =
desc->layout->fields[upb_fielddef_index(f)].case_offset + slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
sizeof(MessageHeader);
// For a oneof, check that this field is actually present -- skip all the // For a oneof, check that this field is actually present -- skip all the
// below if not. // below if not.
if (DEREF(msg, oneof_case_offset, uint32_t) != if (oneof_case != upb_fielddef_number(f)) {
upb_fielddef_number(f)) {
continue; continue;
} }
// Otherwise, fall through to the appropriate singular-field handler // Otherwise, fall through to the appropriate singular-field handler
......
...@@ -86,27 +86,11 @@ VALUE Message_alloc(VALUE klass) { ...@@ -86,27 +86,11 @@ VALUE Message_alloc(VALUE klass) {
} }
static const upb_fielddef* which_oneof_field(MessageHeader* self, const upb_oneofdef* o) { static const upb_fielddef* which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
upb_oneof_iter it;
size_t case_ofs;
uint32_t oneof_case; uint32_t oneof_case;
const upb_fielddef* first_field;
const upb_fielddef* f; const upb_fielddef* f;
// If no fields in the oneof, always nil. oneof_case =
if (upb_oneofdef_numfields(o) == 0) { slot_read_oneof_case(self->descriptor->layout, Message_data(self), o);
return NULL;
}
// Grab the first field in the oneof so we can get its layout info to find the
// oneof_case field.
upb_oneof_begin(&it, o);
assert(!upb_oneof_done(&it));
first_field = upb_oneof_iter_field(&it);
assert(upb_fielddef_containingoneof(first_field) != NULL);
case_ofs =
self->descriptor->layout->
fields[upb_fielddef_index(first_field)].case_offset;
oneof_case = *((uint32_t*)((char*)Message_data(self) + case_ofs));
if (oneof_case == ONEOF_CASE_NONE) { if (oneof_case == ONEOF_CASE_NONE) {
return NULL; return NULL;
......
...@@ -59,6 +59,7 @@ typedef struct OneofDescriptor OneofDescriptor; ...@@ -59,6 +59,7 @@ typedef struct OneofDescriptor OneofDescriptor;
typedef struct EnumDescriptor EnumDescriptor; typedef struct EnumDescriptor EnumDescriptor;
typedef struct MessageLayout MessageLayout; typedef struct MessageLayout MessageLayout;
typedef struct MessageField MessageField; typedef struct MessageField MessageField;
typedef struct MessageOneof MessageOneof;
typedef struct MessageHeader MessageHeader; typedef struct MessageHeader MessageHeader;
typedef struct MessageBuilderContext MessageBuilderContext; typedef struct MessageBuilderContext MessageBuilderContext;
typedef struct OneofBuilderContext OneofBuilderContext; typedef struct OneofBuilderContext OneofBuilderContext;
...@@ -367,6 +368,9 @@ bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2); ...@@ -367,6 +368,9 @@ bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2);
VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value); VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value);
void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE value); void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE value);
uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
const upb_oneofdef* oneof);
bool is_value_field(const upb_fielddef* f);
extern rb_encoding* kRubyStringUtf8Encoding; extern rb_encoding* kRubyStringUtf8Encoding;
extern rb_encoding* kRubyStringASCIIEncoding; extern rb_encoding* kRubyStringASCIIEncoding;
...@@ -496,13 +500,16 @@ VALUE Map_iter_value(Map_iter* iter); ...@@ -496,13 +500,16 @@ VALUE Map_iter_value(Map_iter* iter);
// Message layout / storage. // Message layout / storage.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#define MESSAGE_FIELD_NO_CASE ((size_t)-1) #define MESSAGE_FIELD_NO_HASBIT ((uint32_t)-1)
#define MESSAGE_FIELD_NO_HASBIT ((size_t)-1)
struct MessageField { struct MessageField {
size_t offset; uint32_t offset;
size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE. uint32_t hasbit;
size_t hasbit; };
struct MessageOneof {
uint32_t offset;
uint32_t case_offset;
}; };
// MessageLayout is owned by the enclosing Descriptor, which must outlive us. // MessageLayout is owned by the enclosing Descriptor, which must outlive us.
...@@ -510,9 +517,14 @@ struct MessageLayout { ...@@ -510,9 +517,14 @@ struct MessageLayout {
const Descriptor* desc; const Descriptor* desc;
const upb_msgdef* msgdef; const upb_msgdef* msgdef;
MessageField* fields; MessageField* fields;
size_t size; MessageOneof* oneofs;
uint32_t size;
uint32_t value_offset;
int value_count;
}; };
#define ONEOF_CASE_MASK 0x80000000
MessageLayout* create_layout(const Descriptor* desc); MessageLayout* create_layout(const Descriptor* desc);
void free_layout(MessageLayout* layout); void free_layout(MessageLayout* layout);
bool field_contains_hasbit(MessageLayout* layout, bool field_contains_hasbit(MessageLayout* layout,
......
...@@ -473,10 +473,16 @@ static size_t align_up_to(size_t offset, size_t granularity) { ...@@ -473,10 +473,16 @@ static size_t align_up_to(size_t offset, size_t granularity) {
return (offset + granularity - 1) & ~(granularity - 1); return (offset + granularity - 1) & ~(granularity - 1);
} }
bool is_value_field(const upb_fielddef* f) {
return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) ||
upb_fielddef_isstring(f);
}
MessageLayout* create_layout(const Descriptor* desc) { MessageLayout* create_layout(const 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);
int noneofs = upb_msgdef_numoneofs(msgdef);
upb_msg_field_iter it; upb_msg_field_iter it;
upb_msg_oneof_iter oit; upb_msg_oneof_iter oit;
size_t off = 0; size_t off = 0;
...@@ -484,6 +490,11 @@ MessageLayout* create_layout(const Descriptor* desc) { ...@@ -484,6 +490,11 @@ MessageLayout* create_layout(const Descriptor* desc) {
layout->desc = desc; layout->desc = desc;
layout->fields = ALLOC_N(MessageField, nfields); layout->fields = ALLOC_N(MessageField, nfields);
layout->oneofs = NULL;
if (noneofs > 0) {
layout->oneofs = ALLOC_N(MessageOneof, noneofs);
}
for (upb_msg_field_begin(&it, msgdef); for (upb_msg_field_begin(&it, msgdef);
!upb_msg_field_done(&it); !upb_msg_field_done(&it);
...@@ -501,29 +512,41 @@ MessageLayout* create_layout(const Descriptor* desc) { ...@@ -501,29 +512,41 @@ MessageLayout* create_layout(const Descriptor* desc) {
off += (hasbit + 8 - 1) / 8; off += (hasbit + 8 - 1) / 8;
} }
off = align_up_to(off, sizeof(VALUE));
layout->value_offset = off;
layout->value_count = 0;
// Place all (non-oneof) VALUE fields first.
for (upb_msg_field_begin(&it, msgdef);
!upb_msg_field_done(&it);
upb_msg_field_next(&it)) {
const upb_fielddef* field = upb_msg_iter_field(&it);
if (upb_fielddef_containingoneof(field) || !is_value_field(field)) {
continue;
}
layout->fields[upb_fielddef_index(field)].offset = off;
off += sizeof(VALUE);
layout->value_count++;
}
// Now place all other (non-oneof) fields.
for (upb_msg_field_begin(&it, msgdef); for (upb_msg_field_begin(&it, msgdef);
!upb_msg_field_done(&it); !upb_msg_field_done(&it);
upb_msg_field_next(&it)) { upb_msg_field_next(&it)) {
const upb_fielddef* field = upb_msg_iter_field(&it); const upb_fielddef* field = upb_msg_iter_field(&it);
size_t field_size; size_t field_size;
if (upb_fielddef_containingoneof(field)) { if (upb_fielddef_containingoneof(field) || is_value_field(field)) {
// Oneofs are handled separately below.
continue; continue;
} }
// Allocate |field_size| bytes for this field in the layout. // Allocate |field_size| bytes for this field in the layout.
field_size = 0; field_size = native_slot_size(upb_fielddef_type(field));
if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
field_size = sizeof(VALUE);
} else {
field_size = native_slot_size(upb_fielddef_type(field));
}
// Align current offset up to |size| granularity. // Align current offset up to |size| granularity.
off = align_up_to(off, field_size); off = align_up_to(off, field_size);
layout->fields[upb_fielddef_index(field)].offset = off; layout->fields[upb_fielddef_index(field)].offset = off;
layout->fields[upb_fielddef_index(field)].case_offset =
MESSAGE_FIELD_NO_CASE;
off += field_size; off += field_size;
} }
...@@ -557,6 +580,7 @@ MessageLayout* create_layout(const Descriptor* desc) { ...@@ -557,6 +580,7 @@ MessageLayout* create_layout(const Descriptor* desc) {
upb_oneof_next(&fit)) { upb_oneof_next(&fit)) {
const upb_fielddef* field = upb_oneof_iter_field(&fit); const upb_fielddef* field = upb_oneof_iter_field(&fit);
layout->fields[upb_fielddef_index(field)].offset = off; layout->fields[upb_fielddef_index(field)].offset = off;
layout->oneofs[upb_oneofdef_index(oneof)].offset = off;
} }
off += field_size; off += field_size;
} }
...@@ -566,18 +590,10 @@ MessageLayout* create_layout(const Descriptor* desc) { ...@@ -566,18 +590,10 @@ MessageLayout* create_layout(const Descriptor* desc) {
!upb_msg_oneof_done(&oit); !upb_msg_oneof_done(&oit);
upb_msg_oneof_next(&oit)) { upb_msg_oneof_next(&oit)) {
const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
upb_oneof_iter fit;
size_t field_size = sizeof(uint32_t); size_t field_size = sizeof(uint32_t);
// Align the offset. // Align the offset.
off = (off + field_size - 1) & ~(field_size - 1); off = (off + field_size - 1) & ~(field_size - 1);
// Assign all fields in the oneof this same offset. layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
for (upb_oneof_begin(&fit, oneof);
!upb_oneof_done(&fit);
upb_oneof_next(&fit)) {
const upb_fielddef* field = upb_oneof_iter_field(&fit);
layout->fields[upb_fielddef_index(field)].case_offset = off;
}
off += field_size; off += field_size;
} }
...@@ -589,6 +605,7 @@ MessageLayout* create_layout(const Descriptor* desc) { ...@@ -589,6 +605,7 @@ MessageLayout* create_layout(const Descriptor* desc) {
void free_layout(MessageLayout* layout) { void free_layout(MessageLayout* layout) {
xfree(layout->fields); xfree(layout->fields);
xfree(layout->oneofs);
xfree(layout); xfree(layout);
} }
...@@ -615,9 +632,15 @@ static void* slot_memory(MessageLayout* layout, ...@@ -615,9 +632,15 @@ static void* slot_memory(MessageLayout* layout,
static uint32_t* slot_oneof_case(MessageLayout* layout, static uint32_t* slot_oneof_case(MessageLayout* layout,
const void* storage, const void* storage,
const upb_fielddef* field) { const upb_oneofdef* oneof) {
return (uint32_t *)(((uint8_t *)storage) + return (uint32_t*)(((uint8_t*)storage) +
layout->fields[upb_fielddef_index(field)].case_offset); layout->oneofs[upb_oneofdef_index(oneof)].case_offset);
}
uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
const upb_oneofdef* oneof) {
uint32_t* ptr = slot_oneof_case(layout, storage, oneof);
return *ptr & ~ONEOF_CASE_MASK;
} }
static void slot_set_hasbit(MessageLayout* layout, static void slot_set_hasbit(MessageLayout* layout,
...@@ -660,13 +683,14 @@ void layout_clear(MessageLayout* layout, ...@@ -660,13 +683,14 @@ void layout_clear(MessageLayout* layout,
const void* storage, const void* storage,
const upb_fielddef* field) { const upb_fielddef* field) {
void* memory = slot_memory(layout, storage, field); void* memory = slot_memory(layout, storage, field);
uint32_t* oneof_case = slot_oneof_case(layout, storage, field); const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
if (field_contains_hasbit(layout, field)) { if (field_contains_hasbit(layout, field)) {
slot_clear_hasbit(layout, storage, field); slot_clear_hasbit(layout, storage, field);
} }
if (upb_fielddef_containingoneof(field)) { if (oneof) {
uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
memset(memory, 0, NATIVE_SLOT_MAX_SIZE); memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
*oneof_case = ONEOF_CASE_NONE; *oneof_case = ONEOF_CASE_NONE;
} else if (is_map_field(field)) { } else if (is_map_field(field)) {
...@@ -752,8 +776,7 @@ VALUE layout_get(MessageLayout* layout, ...@@ -752,8 +776,7 @@ VALUE layout_get(MessageLayout* layout,
const void* storage, const void* storage,
const upb_fielddef* field) { const upb_fielddef* field) {
void* memory = slot_memory(layout, storage, field); void* memory = slot_memory(layout, storage, field);
uint32_t* oneof_case = slot_oneof_case(layout, storage, field); const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
bool field_set; bool field_set;
if (field_contains_hasbit(layout, field)) { if (field_contains_hasbit(layout, field)) {
field_set = slot_is_hasbit_set(layout, storage, field); field_set = slot_is_hasbit_set(layout, storage, field);
...@@ -761,8 +784,9 @@ VALUE layout_get(MessageLayout* layout, ...@@ -761,8 +784,9 @@ VALUE layout_get(MessageLayout* layout,
field_set = true; field_set = true;
} }
if (upb_fielddef_containingoneof(field)) { if (oneof) {
if (*oneof_case != upb_fielddef_number(field)) { uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
if (oneof_case != upb_fielddef_number(field)) {
return layout_get_default(field); return layout_get_default(field);
} }
return native_slot_get(upb_fielddef_type(field), return native_slot_get(upb_fielddef_type(field),
...@@ -825,9 +849,10 @@ void layout_set(MessageLayout* layout, ...@@ -825,9 +849,10 @@ void layout_set(MessageLayout* layout,
const upb_fielddef* field, const upb_fielddef* field,
VALUE val) { VALUE val) {
void* memory = slot_memory(layout, storage, field); void* memory = slot_memory(layout, storage, field);
uint32_t* oneof_case = slot_oneof_case(layout, storage, field); const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
if (upb_fielddef_containingoneof(field)) { if (oneof) {
uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
if (val == Qnil) { if (val == Qnil) {
// Assigning nil to a oneof field clears the oneof completely. // Assigning nil to a oneof field clears the oneof completely.
*oneof_case = ONEOF_CASE_NONE; *oneof_case = ONEOF_CASE_NONE;
...@@ -845,11 +870,14 @@ void layout_set(MessageLayout* layout, ...@@ -845,11 +870,14 @@ void layout_set(MessageLayout* layout,
// sync with the value slot whenever the Ruby VM has been called. Thus, we // sync with the value slot whenever the Ruby VM has been called. Thus, we
// use native_slot_set_value_and_case(), which ensures that both the value // use native_slot_set_value_and_case(), which ensures that both the value
// and case number are altered atomically (w.r.t. the Ruby VM). // and case number are altered atomically (w.r.t. the Ruby VM).
uint32_t case_value = upb_fielddef_number(field);
if (upb_fielddef_issubmsg(field) || upb_fielddef_isstring(field)) {
case_value |= ONEOF_CASE_MASK;
}
native_slot_set_value_and_case( native_slot_set_value_and_case(
upb_fielddef_name(field), upb_fielddef_name(field), upb_fielddef_type(field),
upb_fielddef_type(field), field_type_class(layout, field), field_type_class(layout, field), memory, val, oneof_case, case_value);
memory, val,
oneof_case, upb_fielddef_number(field));
} }
} else if (is_map_field(field)) { } else if (is_map_field(field)) {
check_map_field_type(layout, val, field); check_map_field_type(layout, val, field);
...@@ -880,22 +908,19 @@ void layout_init(MessageLayout* layout, ...@@ -880,22 +908,19 @@ void layout_init(MessageLayout* layout,
} }
void layout_mark(MessageLayout* layout, void* storage) { void layout_mark(MessageLayout* layout, void* storage) {
upb_msg_field_iter it; VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
for (upb_msg_field_begin(&it, layout->msgdef); int noneofs = upb_msgdef_numoneofs(layout->msgdef);
!upb_msg_field_done(&it); int i;
upb_msg_field_next(&it)) {
const upb_fielddef* field = upb_msg_iter_field(&it);
void* memory = slot_memory(layout, storage, field);
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
if (upb_fielddef_containingoneof(field)) { for (i = 0; i < layout->value_count; i++) {
if (*oneof_case == upb_fielddef_number(field)) { rb_gc_mark(values[i]);
native_slot_mark(upb_fielddef_type(field), memory); }
}
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { for (i = 0; i < noneofs; i++) {
rb_gc_mark(DEREF(memory, VALUE)); MessageOneof* oneof = &layout->oneofs[i];
} else { uint32_t* case_ptr = (uint32_t*)CHARPTR_AT(storage, oneof->case_offset);
native_slot_mark(upb_fielddef_type(field), memory); if (*case_ptr & ONEOF_CASE_MASK) {
rb_gc_mark(DEREF_OFFSET(storage, oneof->offset, VALUE));
} }
} }
} }
...@@ -906,14 +931,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) { ...@@ -906,14 +931,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
!upb_msg_field_done(&it); !upb_msg_field_done(&it);
upb_msg_field_next(&it)) { upb_msg_field_next(&it)) {
const upb_fielddef* field = upb_msg_iter_field(&it); const upb_fielddef* field = upb_msg_iter_field(&it);
const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
void* to_memory = slot_memory(layout, to, field); void* to_memory = slot_memory(layout, to, field);
uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
void* from_memory = slot_memory(layout, from, field); void* from_memory = slot_memory(layout, from, field);
uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
if (upb_fielddef_containingoneof(field)) { if (oneof) {
if (*from_oneof_case == upb_fielddef_number(field)) { uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
if (slot_read_oneof_case(layout, from, oneof) ==
upb_fielddef_number(field)) {
*to_oneof_case = *from_oneof_case; *to_oneof_case = *from_oneof_case;
native_slot_dup(upb_fielddef_type(field), to_memory, from_memory); native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
} }
...@@ -938,14 +965,16 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) { ...@@ -938,14 +965,16 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
!upb_msg_field_done(&it); !upb_msg_field_done(&it);
upb_msg_field_next(&it)) { upb_msg_field_next(&it)) {
const upb_fielddef* field = upb_msg_iter_field(&it); const upb_fielddef* field = upb_msg_iter_field(&it);
const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
void* to_memory = slot_memory(layout, to, field); void* to_memory = slot_memory(layout, to, field);
uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
void* from_memory = slot_memory(layout, from, field); void* from_memory = slot_memory(layout, from, field);
uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
if (upb_fielddef_containingoneof(field)) { if (oneof) {
if (*from_oneof_case == upb_fielddef_number(field)) { uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
if (slot_read_oneof_case(layout, from, oneof) ==
upb_fielddef_number(field)) {
*to_oneof_case = *from_oneof_case; *to_oneof_case = *from_oneof_case;
native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory); native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
} }
...@@ -972,17 +1001,18 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) { ...@@ -972,17 +1001,18 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
!upb_msg_field_done(&it); !upb_msg_field_done(&it);
upb_msg_field_next(&it)) { upb_msg_field_next(&it)) {
const upb_fielddef* field = upb_msg_iter_field(&it); const upb_fielddef* field = upb_msg_iter_field(&it);
const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
void* msg1_memory = slot_memory(layout, msg1, field); void* msg1_memory = slot_memory(layout, msg1, field);
uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
void* msg2_memory = slot_memory(layout, msg2, field); void* msg2_memory = slot_memory(layout, msg2, field);
uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
if (upb_fielddef_containingoneof(field)) { if (oneof) {
uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, oneof);
uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, oneof);
if (*msg1_oneof_case != *msg2_oneof_case || if (*msg1_oneof_case != *msg2_oneof_case ||
(*msg1_oneof_case == upb_fielddef_number(field) && (slot_read_oneof_case(layout, msg1, oneof) ==
!native_slot_eq(upb_fielddef_type(field), upb_fielddef_number(field) &&
msg1_memory, !native_slot_eq(upb_fielddef_type(field), msg1_memory,
msg2_memory))) { msg2_memory))) {
return Qfalse; return Qfalse;
} }
...@@ -998,9 +1028,8 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) { ...@@ -998,9 +1028,8 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
} }
} else { } else {
if (slot_is_hasbit_set(layout, msg1, field) != if (slot_is_hasbit_set(layout, msg1, field) !=
slot_is_hasbit_set(layout, msg2, field) || slot_is_hasbit_set(layout, msg2, field) ||
!native_slot_eq(upb_fielddef_type(field), !native_slot_eq(upb_fielddef_type(field), msg1_memory, msg2_memory)) {
msg1_memory, msg2_memory)) {
return Qfalse; return Qfalse;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment