|
@@ -465,11 +465,17 @@ static size_t align_up_to(size_t offset, size_t granularity) {
|
|
|
MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
|
MessageLayout* layout = ALLOC(MessageLayout);
|
|
|
int nfields = upb_msgdef_numfields(msgdef);
|
|
|
+ int noneofs = upb_msgdef_numoneofs(msgdef);
|
|
|
upb_msg_field_iter it;
|
|
|
upb_msg_oneof_iter oit;
|
|
|
size_t off = 0;
|
|
|
|
|
|
layout->fields = ALLOC_N(MessageField, nfields);
|
|
|
+ layout->oneofs = NULL;
|
|
|
+
|
|
|
+ if (noneofs > 0) {
|
|
|
+ layout->oneofs = ALLOC_N(MessageOneof, noneofs);
|
|
|
+ }
|
|
|
|
|
|
size_t hasbit = 0;
|
|
|
for (upb_msg_field_begin(&it, msgdef);
|
|
@@ -480,7 +486,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
|
layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
|
|
|
} else {
|
|
|
layout->fields[upb_fielddef_index(field)].hasbit =
|
|
|
- MESSAGE_FIELD_NO_HASBIT;
|
|
|
+ MESSAGE_FIELD_NO_HASBIT;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -509,8 +515,6 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
|
// Align current offset up to |size| granularity.
|
|
|
off = align_up_to(off, field_size);
|
|
|
layout->fields[upb_fielddef_index(field)].offset = off;
|
|
|
- layout->fields[upb_fielddef_index(field)].case_offset =
|
|
|
- MESSAGE_FIELD_NO_CASE;
|
|
|
off += field_size;
|
|
|
}
|
|
|
|
|
@@ -558,13 +562,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
|
size_t field_size = sizeof(uint32_t);
|
|
|
// Align the offset.
|
|
|
off = (off + field_size - 1) & ~(field_size - 1);
|
|
|
- // Assign all fields in the oneof this same offset.
|
|
|
- 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;
|
|
|
- }
|
|
|
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
|
|
|
off += field_size;
|
|
|
}
|
|
|
|
|
@@ -578,6 +576,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
|
|
|
|
void free_layout(MessageLayout* layout) {
|
|
|
xfree(layout->fields);
|
|
|
+ xfree(layout->oneofs);
|
|
|
upb_msgdef_unref(layout->msgdef, &layout->msgdef);
|
|
|
xfree(layout);
|
|
|
}
|
|
@@ -605,9 +604,15 @@ static void* slot_memory(MessageLayout* layout,
|
|
|
|
|
|
static uint32_t* slot_oneof_case(MessageLayout* layout,
|
|
|
const void* storage,
|
|
|
- const upb_fielddef* field) {
|
|
|
- return (uint32_t *)(((uint8_t *)storage) +
|
|
|
- layout->fields[upb_fielddef_index(field)].case_offset);
|
|
|
+ const upb_oneofdef* oneof) {
|
|
|
+ return (uint32_t*)(((uint8_t*)storage) +
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
static void slot_set_hasbit(MessageLayout* layout,
|
|
@@ -650,13 +655,14 @@ void layout_clear(MessageLayout* layout,
|
|
|
const void* storage,
|
|
|
const upb_fielddef* 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)) {
|
|
|
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);
|
|
|
*oneof_case = ONEOF_CASE_NONE;
|
|
|
} else if (is_map_field(field)) {
|
|
@@ -742,8 +748,7 @@ VALUE layout_get(MessageLayout* layout,
|
|
|
const void* storage,
|
|
|
const upb_fielddef* 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;
|
|
|
if (field_contains_hasbit(layout, field)) {
|
|
|
field_set = slot_is_hasbit_set(layout, storage, field);
|
|
@@ -751,8 +756,9 @@ VALUE layout_get(MessageLayout* layout,
|
|
|
field_set = true;
|
|
|
}
|
|
|
|
|
|
- if (upb_fielddef_containingoneof(field)) {
|
|
|
- if (*oneof_case != upb_fielddef_number(field)) {
|
|
|
+ if (oneof) {
|
|
|
+ uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
|
|
|
+ if (oneof_case != upb_fielddef_number(field)) {
|
|
|
return layout_get_default(field);
|
|
|
}
|
|
|
return native_slot_get(upb_fielddef_type(field),
|
|
@@ -834,9 +840,10 @@ void layout_set(MessageLayout* layout,
|
|
|
const upb_fielddef* field,
|
|
|
VALUE val) {
|
|
|
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) {
|
|
|
// Assigning nil to a oneof field clears the oneof completely.
|
|
|
*oneof_case = ONEOF_CASE_NONE;
|
|
@@ -895,11 +902,12 @@ void layout_mark(MessageLayout* layout, void* storage) {
|
|
|
!upb_msg_field_done(&it);
|
|
|
upb_msg_field_next(&it)) {
|
|
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
|
|
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
|
|
|
void* memory = slot_memory(layout, storage, field);
|
|
|
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
|
|
|
|
|
- if (upb_fielddef_containingoneof(field)) {
|
|
|
- if (*oneof_case == upb_fielddef_number(field)) {
|
|
|
+ if (oneof) {
|
|
|
+ uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
|
|
|
+ if (oneof_case == upb_fielddef_number(field)) {
|
|
|
native_slot_mark(upb_fielddef_type(field), memory);
|
|
|
}
|
|
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
|
@@ -916,14 +924,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
|
|
|
!upb_msg_field_done(&it);
|
|
|
upb_msg_field_next(&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);
|
|
|
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, 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 (*from_oneof_case == upb_fielddef_number(field)) {
|
|
|
+ if (oneof) {
|
|
|
+ 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;
|
|
|
native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
|
|
|
}
|
|
@@ -948,14 +958,16 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
|
|
|
!upb_msg_field_done(&it);
|
|
|
upb_msg_field_next(&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);
|
|
|
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, 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 (*from_oneof_case == upb_fielddef_number(field)) {
|
|
|
+ if (oneof) {
|
|
|
+ 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;
|
|
|
native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
|
|
|
}
|
|
@@ -982,17 +994,18 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
|
|
|
!upb_msg_field_done(&it);
|
|
|
upb_msg_field_next(&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);
|
|
|
- uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, 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 ||
|
|
|
- (*msg1_oneof_case == upb_fielddef_number(field) &&
|
|
|
- !native_slot_eq(upb_fielddef_type(field),
|
|
|
- msg1_memory,
|
|
|
+ (slot_read_oneof_case(layout, msg1, oneof) ==
|
|
|
+ upb_fielddef_number(field) &&
|
|
|
+ !native_slot_eq(upb_fielddef_type(field), msg1_memory,
|
|
|
msg2_memory))) {
|
|
|
return Qfalse;
|
|
|
}
|
|
@@ -1008,9 +1021,8 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
|
|
|
}
|
|
|
} else {
|
|
|
if (slot_is_hasbit_set(layout, msg1, field) !=
|
|
|
- slot_is_hasbit_set(layout, msg2, field) ||
|
|
|
- !native_slot_eq(upb_fielddef_type(field),
|
|
|
- msg1_memory, msg2_memory)) {
|
|
|
+ slot_is_hasbit_set(layout, msg2, field) ||
|
|
|
+ !native_slot_eq(upb_fielddef_type(field), msg1_memory, msg2_memory)) {
|
|
|
return Qfalse;
|
|
|
}
|
|
|
}
|