Avoid too much overhead in layout_init (#6716)
* Avoid initializing primitive fields in layout_init * Avoid initializing string/bytes/message fields in layout_init * Lazily create map when needed * Lazily create repeated fields * Change layout_init to only do memcpy * Fix test for php-7.0 * Fix conformance test where default value of string/message map is not encoded * Fix test for zts * Clean up * Fix commentspull/6820/head
parent
3fa17ca0bd
commit
c53e5b8e11
|
@ -139,6 +139,8 @@ composer.lock
|
|||
php/tests/generated/
|
||||
php/tests/old_protoc
|
||||
php/tests/protobuf/
|
||||
php/tests/core
|
||||
php/tests/vgcore*
|
||||
php/ext/google/protobuf/.libs/
|
||||
php/ext/google/protobuf/Makefile.fragments
|
||||
php/ext/google/protobuf/Makefile.global
|
||||
|
|
|
@ -259,6 +259,19 @@ void repeated_field_push_native(RepeatedField *intern, void *value) {
|
|||
}
|
||||
}
|
||||
|
||||
void repeated_field_ensure_created(
|
||||
const upb_fielddef *field,
|
||||
CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
|
||||
if (ZVAL_IS_NULL(CACHED_PTR_TO_ZVAL_PTR(repeated_field))) {
|
||||
zval_ptr_dtor(repeated_field);
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
MAKE_STD_ZVAL(CACHED_PTR_TO_ZVAL_PTR(repeated_field));
|
||||
#endif
|
||||
repeated_field_create_with_field(repeated_field_type, field,
|
||||
repeated_field PHP_PROTO_TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
void repeated_field_create_with_field(
|
||||
zend_class_entry *ce, const upb_fielddef *field,
|
||||
CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC) {
|
||||
|
|
|
@ -139,6 +139,15 @@ static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
|
|||
return hd_ofs;
|
||||
}
|
||||
|
||||
static const void* newhandlerfielddata(
|
||||
upb_handlers* h, const upb_fielddef* field) {
|
||||
const void** hd_field = malloc(sizeof(void*));
|
||||
PHP_PROTO_ASSERT(hd_field != NULL);
|
||||
*hd_field = field;
|
||||
upb_handlers_addcleanup(h, hd_field, free);
|
||||
return hd_field;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
void* closure;
|
||||
stringsink sink;
|
||||
|
@ -163,16 +172,18 @@ static const void *newunknownfieldshandlerdata(upb_handlers* h) {
|
|||
}
|
||||
|
||||
typedef struct {
|
||||
const upb_fielddef *fd;
|
||||
size_t ofs;
|
||||
const upb_msgdef *md;
|
||||
} submsg_handlerdata_t;
|
||||
|
||||
// Creates a handlerdata that contains offset and submessage type information.
|
||||
// Creates a handlerdata that contains field and submessage type information.
|
||||
static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
|
||||
const upb_fielddef* f) {
|
||||
submsg_handlerdata_t* hd =
|
||||
(submsg_handlerdata_t*)malloc(sizeof(submsg_handlerdata_t));
|
||||
PHP_PROTO_ASSERT(hd != NULL);
|
||||
hd->fd = f;
|
||||
hd->ofs = ofs;
|
||||
hd->md = upb_fielddef_msgsubdef(f);
|
||||
upb_handlers_addcleanup(h, hd, free);
|
||||
|
@ -221,8 +232,11 @@ static const void *newoneofhandlerdata(upb_handlers *h,
|
|||
// this field (such an instance always exists even in an empty message).
|
||||
static void *startseq_handler(void* closure, const void* hd) {
|
||||
MessageHeader* msg = closure;
|
||||
const size_t *ofs = hd;
|
||||
return CACHED_PTR_TO_ZVAL_PTR(DEREF(message_data(msg), *ofs, CACHED_VALUE*));
|
||||
const upb_fielddef** field = (const upb_fielddef**) hd;
|
||||
CACHED_VALUE* cache = find_zval_property(msg, *field);
|
||||
TSRMLS_FETCH();
|
||||
repeated_field_ensure_created(*field, cache PHP_PROTO_TSRMLS_CC);
|
||||
return CACHED_PTR_TO_ZVAL_PTR(cache);
|
||||
}
|
||||
|
||||
// Handlers that append primitive values to a repeated field.
|
||||
|
@ -322,15 +336,6 @@ static void *empty_php_string(zval* value_ptr) {
|
|||
}
|
||||
#endif
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
static void *empty_php_string2(zval** value_ptr) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
|
||||
if (Z_TYPE_PP(value_ptr) == IS_STRING &&
|
||||
!IS_INTERNED(Z_STRVAL_PP(value_ptr))) {
|
||||
FREE(Z_STRVAL_PP(value_ptr));
|
||||
}
|
||||
ZVAL_EMPTY_STRING(*value_ptr);
|
||||
return (void*)(*value_ptr);
|
||||
}
|
||||
static void new_php_string(zval** value_ptr, const char* str, size_t len) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
|
||||
if (Z_TYPE_PP(value_ptr) == IS_STRING &&
|
||||
|
@ -340,13 +345,6 @@ static void new_php_string(zval** value_ptr, const char* str, size_t len) {
|
|||
ZVAL_STRINGL(*value_ptr, str, len, 1);
|
||||
}
|
||||
#else
|
||||
static void *empty_php_string2(zval* value_ptr) {
|
||||
if (Z_TYPE_P(value_ptr) == IS_STRING) {
|
||||
zend_string_release(Z_STR_P(value_ptr));
|
||||
}
|
||||
ZVAL_EMPTY_STRING(value_ptr);
|
||||
return value_ptr;
|
||||
}
|
||||
static void new_php_string(zval* value_ptr, const char* str, size_t len) {
|
||||
if (Z_TYPE_P(value_ptr) == IS_STRING) {
|
||||
zend_string_release(Z_STR_P(value_ptr));
|
||||
|
@ -371,6 +369,21 @@ static void* str_handler(void *closure,
|
|||
}
|
||||
|
||||
static bool str_end_handler(void *closure, const void *hd) {
|
||||
stringfields_parseframe_t* frame = closure;
|
||||
const upb_fielddef **field = (const upb_fielddef **) hd;
|
||||
MessageHeader* msg = (MessageHeader*)frame->closure;
|
||||
|
||||
CACHED_VALUE* cached = find_zval_property(msg, *field);
|
||||
|
||||
new_php_string(cached, frame->sink.ptr, frame->sink.len);
|
||||
|
||||
stringsink_uninit(&frame->sink);
|
||||
free(frame);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool map_str_end_handler(void *closure, const void *hd) {
|
||||
stringfields_parseframe_t* frame = closure;
|
||||
const size_t *ofs = hd;
|
||||
MessageHeader* msg = (MessageHeader*)frame->closure;
|
||||
|
@ -430,26 +443,60 @@ static void *submsg_handler(void *closure, const void *hd) {
|
|||
zval* submsg_php;
|
||||
MessageHeader* submsg;
|
||||
|
||||
if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(message_data(msg), submsgdata->ofs,
|
||||
CACHED_VALUE*))) == IS_NULL) {
|
||||
CACHED_VALUE* cached = find_zval_property(msg, submsgdata->fd);
|
||||
|
||||
if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
zval val;
|
||||
ZVAL_OBJ(&val, subklass->create_object(subklass TSRMLS_CC));
|
||||
MessageHeader* intern = UNBOX(MessageHeader, &val);
|
||||
custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
|
||||
REPLACE_ZVAL_VALUE(DEREF(message_data(msg), submsgdata->ofs, zval**),
|
||||
&val, 1);
|
||||
REPLACE_ZVAL_VALUE(cached, &val, 1);
|
||||
zval_dtor(&val);
|
||||
#else
|
||||
zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
|
||||
ZVAL_OBJ(DEREF(message_data(msg), submsgdata->ofs, zval*), obj);
|
||||
ZVAL_OBJ(cached, obj);
|
||||
MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
|
||||
custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
|
||||
#endif
|
||||
}
|
||||
|
||||
submsg_php = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), submsgdata->ofs, CACHED_VALUE*));
|
||||
submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
|
||||
|
||||
submsg = UNBOX(MessageHeader, submsg_php);
|
||||
return submsg;
|
||||
}
|
||||
|
||||
static void *map_submsg_handler(void *closure, const void *hd) {
|
||||
MessageHeader* msg = closure;
|
||||
const submsg_handlerdata_t* submsgdata = hd;
|
||||
TSRMLS_FETCH();
|
||||
Descriptor* subdesc =
|
||||
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
|
||||
zend_class_entry* subklass = subdesc->klass;
|
||||
zval* submsg_php;
|
||||
MessageHeader* submsg;
|
||||
|
||||
CACHED_VALUE* cached =
|
||||
DEREF(message_data(msg), submsgdata->ofs, CACHED_VALUE*);
|
||||
|
||||
if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(cached)) == IS_NULL) {
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
zval val;
|
||||
ZVAL_OBJ(&val, subklass->create_object(subklass TSRMLS_CC));
|
||||
MessageHeader* intern = UNBOX(MessageHeader, &val);
|
||||
custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
|
||||
REPLACE_ZVAL_VALUE(cached, &val, 1);
|
||||
zval_dtor(&val);
|
||||
#else
|
||||
zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
|
||||
ZVAL_OBJ(cached, obj);
|
||||
MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
|
||||
custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
|
||||
#endif
|
||||
}
|
||||
|
||||
submsg_php = CACHED_PTR_TO_ZVAL_PTR(cached);
|
||||
|
||||
submsg = UNBOX(MessageHeader, submsg_php);
|
||||
return submsg;
|
||||
|
@ -457,7 +504,7 @@ static void *submsg_handler(void *closure, const void *hd) {
|
|||
|
||||
// Handler data for startmap/endmap handlers.
|
||||
typedef struct {
|
||||
size_t ofs;
|
||||
const upb_fielddef* fd;
|
||||
const upb_msgdef* value_md;
|
||||
upb_fieldtype_t key_field_type;
|
||||
upb_fieldtype_t value_field_type;
|
||||
|
@ -612,9 +659,10 @@ static void map_slot_value(upb_fieldtype_t type, const void* from,
|
|||
static void *startmapentry_handler(void *closure, const void *hd) {
|
||||
MessageHeader* msg = closure;
|
||||
const map_handlerdata_t* mapdata = hd;
|
||||
CACHED_VALUE* cache = find_zval_property(msg, mapdata->fd);
|
||||
TSRMLS_FETCH();
|
||||
zval* map = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), mapdata->ofs, CACHED_VALUE*));
|
||||
map_field_ensure_created(mapdata->fd, cache PHP_PROTO_TSRMLS_CC);
|
||||
zval* map = CACHED_PTR_TO_ZVAL_PTR(cache);
|
||||
|
||||
map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
|
||||
frame->data = ALLOC(map_parse_frame_data_t);
|
||||
|
@ -662,7 +710,7 @@ static bool endmap_handler(void* closure, const void* hd, upb_status* s) {
|
|||
// key/value and endmsg handlers. The reason is that there is no easy way to
|
||||
// pass the handlerdata down to the sub-message handler setup.
|
||||
static map_handlerdata_t* new_map_handlerdata(
|
||||
size_t ofs,
|
||||
const upb_fielddef* field,
|
||||
const upb_msgdef* mapentry_def,
|
||||
Descriptor* desc) {
|
||||
const upb_fielddef* key_field;
|
||||
|
@ -671,7 +719,7 @@ static map_handlerdata_t* new_map_handlerdata(
|
|||
map_handlerdata_t* hd =
|
||||
(map_handlerdata_t*)malloc(sizeof(map_handlerdata_t));
|
||||
PHP_PROTO_ASSERT(hd != NULL);
|
||||
hd->ofs = ofs;
|
||||
hd->fd = field;
|
||||
key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD);
|
||||
PHP_PROTO_ASSERT(key_field != NULL);
|
||||
hd->key_field_type = upb_fielddef_type(key_field);
|
||||
|
@ -844,7 +892,7 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|||
const upb_fielddef *f,
|
||||
size_t offset) {
|
||||
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
||||
attr.handler_data = newhandlerdata(h, offset);
|
||||
attr.handler_data = newhandlerfielddata(h, f);
|
||||
upb_handlers_setstartseq(h, f, startseq_handler, &attr);
|
||||
|
||||
switch (upb_fielddef_type(f)) {
|
||||
|
@ -884,7 +932,7 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|||
// Set up handlers for a singular field.
|
||||
static void add_handlers_for_singular_field(upb_handlers *h,
|
||||
const upb_fielddef *f,
|
||||
size_t offset) {
|
||||
size_t offset, bool is_map) {
|
||||
switch (upb_fielddef_type(f)) {
|
||||
#define SET_HANDLER(utype, ltype) \
|
||||
case utype: { \
|
||||
|
@ -908,16 +956,29 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|||
case UPB_TYPE_STRING:
|
||||
case UPB_TYPE_BYTES: {
|
||||
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
||||
attr.handler_data = newhandlerdata(h, offset);
|
||||
if (is_map) {
|
||||
attr.handler_data = newhandlerdata(h, offset);
|
||||
} else {
|
||||
attr.handler_data = newhandlerfielddata(h, f);
|
||||
}
|
||||
upb_handlers_setstartstr(h, f, str_handler, &attr);
|
||||
upb_handlers_setstring(h, f, stringdata_handler, &attr);
|
||||
upb_handlers_setendstr(h, f, str_end_handler, &attr);
|
||||
if (is_map) {
|
||||
upb_handlers_setendstr(h, f, map_str_end_handler, &attr);
|
||||
} else {
|
||||
upb_handlers_setendstr(h, f, str_end_handler, &attr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UPB_TYPE_MESSAGE: {
|
||||
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
||||
attr.handler_data = newsubmsghandlerdata(h, offset, f);
|
||||
upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
|
||||
if (is_map) {
|
||||
attr.handler_data = newsubmsghandlerdata(h, offset, f);
|
||||
upb_handlers_setstartsubmsg(h, f, map_submsg_handler, &attr);
|
||||
} else {
|
||||
attr.handler_data = newsubmsghandlerdata(h, 0, f);
|
||||
upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -929,7 +990,7 @@ static void add_handlers_for_mapfield(upb_handlers* h,
|
|||
size_t offset,
|
||||
Descriptor* desc) {
|
||||
const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
|
||||
map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
|
||||
map_handlerdata_t* hd = new_map_handlerdata(fielddef, map_msgdef, desc);
|
||||
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
||||
|
||||
upb_handlers_addcleanup(h, hd, free);
|
||||
|
@ -951,10 +1012,10 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
|
|||
|
||||
add_handlers_for_singular_field(h, key_field,
|
||||
offsetof(map_parse_frame_data_t,
|
||||
key_storage));
|
||||
key_storage), true);
|
||||
add_handlers_for_singular_field(h, value_field,
|
||||
offsetof(map_parse_frame_data_t,
|
||||
value_storage));
|
||||
value_storage), true);
|
||||
}
|
||||
|
||||
// Set up handlers for a oneof field.
|
||||
|
@ -1063,7 +1124,7 @@ void add_handlers_for_message(const void* closure, upb_handlers* h) {
|
|||
} else if (upb_fielddef_isseq(f)) {
|
||||
add_handlers_for_repeated_field(h, f, offset);
|
||||
} else {
|
||||
add_handlers_for_singular_field(h, f, offset);
|
||||
add_handlers_for_singular_field(h, f, offset, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1259,16 +1320,13 @@ static void putjsonany(MessageHeader* msg, const Descriptor* desc,
|
|||
const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
|
||||
const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE);
|
||||
|
||||
uint32_t type_url_offset;
|
||||
zval* type_url_php_str;
|
||||
const upb_msgdef *payload_type = NULL;
|
||||
|
||||
upb_sink_startmsg(sink);
|
||||
|
||||
/* Handle type url */
|
||||
type_url_offset = desc->layout->fields[upb_fielddef_index(type_field)].offset;
|
||||
type_url_php_str = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), type_url_offset, CACHED_VALUE*));
|
||||
type_url_php_str = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, type_field));
|
||||
if (Z_STRLEN_P(type_url_php_str) > 0) {
|
||||
putstr(type_url_php_str, type_field, sink, false);
|
||||
}
|
||||
|
@ -1294,14 +1352,11 @@ static void putjsonany(MessageHeader* msg, const Descriptor* desc,
|
|||
}
|
||||
|
||||
{
|
||||
uint32_t value_offset;
|
||||
zval* value_php_str;
|
||||
const char* value_str;
|
||||
size_t value_len;
|
||||
|
||||
value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset;
|
||||
value_php_str = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), value_offset, CACHED_VALUE*));
|
||||
value_php_str = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, value_field));
|
||||
value_str = Z_STRVAL_P(value_php_str);
|
||||
value_len = Z_STRLEN_P(value_php_str);
|
||||
|
||||
|
@ -1355,17 +1410,21 @@ static void putjsonlistvalue(
|
|||
|
||||
upb_sink_startmsg(sink);
|
||||
|
||||
array = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), offset, CACHED_VALUE*));
|
||||
intern = UNBOX(RepeatedField, array);
|
||||
ht = PHP_PROTO_HASH_OF(intern->array);
|
||||
size = zend_hash_num_elements(ht);
|
||||
|
||||
if (size == 0) {
|
||||
array = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
|
||||
if (ZVAL_IS_NULL(array)) {
|
||||
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
||||
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
||||
} else {
|
||||
putarray(array, f, sink, depth, true TSRMLS_CC);
|
||||
intern = UNBOX(RepeatedField, array);
|
||||
ht = PHP_PROTO_HASH_OF(intern->array);
|
||||
size = zend_hash_num_elements(ht);
|
||||
|
||||
if (size == 0) {
|
||||
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
||||
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
||||
} else {
|
||||
putarray(array, f, sink, depth, true TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
upb_sink_endmsg(sink, &status);
|
||||
|
@ -1384,16 +1443,20 @@ static void putjsonstruct(
|
|||
|
||||
upb_sink_startmsg(sink);
|
||||
|
||||
map = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), offset, CACHED_VALUE*));
|
||||
intern = UNBOX(Map, map);
|
||||
size = upb_strtable_count(&intern->table);
|
||||
|
||||
if (size == 0) {
|
||||
map = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
|
||||
if (ZVAL_IS_NULL(map)) {
|
||||
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
||||
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
||||
} else {
|
||||
putmap(map, f, sink, depth, true TSRMLS_CC);
|
||||
intern = UNBOX(Map, map);
|
||||
size = upb_strtable_count(&intern->table);
|
||||
|
||||
if (size == 0) {
|
||||
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
||||
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
||||
} else {
|
||||
putmap(map, f, sink, depth, true TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
upb_sink_endmsg(sink, &status);
|
||||
|
@ -1455,28 +1518,24 @@ static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
|
|||
}
|
||||
|
||||
if (is_map_field(f)) {
|
||||
zval* map = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), offset, CACHED_VALUE*));
|
||||
if (map != NULL) {
|
||||
zval* map = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
|
||||
if (!ZVAL_IS_NULL(map)) {
|
||||
putmap(map, f, sink, depth, is_json TSRMLS_CC);
|
||||
}
|
||||
} else if (upb_fielddef_isseq(f)) {
|
||||
zval* array = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), offset, CACHED_VALUE*));
|
||||
if (array != NULL) {
|
||||
zval* array = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
|
||||
if (!ZVAL_IS_NULL(array)) {
|
||||
putarray(array, f, sink, depth, is_json TSRMLS_CC);
|
||||
}
|
||||
} else if (upb_fielddef_isstring(f)) {
|
||||
zval* str = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), offset, CACHED_VALUE*));
|
||||
zval* str = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
|
||||
if (containing_oneof || (is_json && is_wrapper_msg(desc->msgdef)) ||
|
||||
Z_STRLEN_P(str) > 0) {
|
||||
putstr(str, f, sink, is_json && is_wrapper_msg(desc->msgdef));
|
||||
}
|
||||
} else if (upb_fielddef_issubmsg(f)) {
|
||||
putsubmsg(CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), offset, CACHED_VALUE*)),
|
||||
f, sink, depth, is_json TSRMLS_CC);
|
||||
zval* submsg = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
|
||||
putsubmsg(submsg, f, sink, depth, is_json TSRMLS_CC);
|
||||
} else {
|
||||
upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
||||
|
||||
|
@ -1847,9 +1906,8 @@ static void discard_unknown_fields(MessageHeader* msg) {
|
|||
value_field = map_field_value(f);
|
||||
if (!upb_fielddef_issubmsg(value_field)) continue;
|
||||
|
||||
zval* map_php = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), offset, CACHED_VALUE*));
|
||||
if (map_php == NULL) continue;
|
||||
zval* map_php = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
|
||||
if (ZVAL_IS_NULL(map_php)) continue;
|
||||
|
||||
Map* intern = UNBOX(Map, map_php);
|
||||
for (map_begin(map_php, &map_it TSRMLS_CC);
|
||||
|
@ -1868,9 +1926,8 @@ static void discard_unknown_fields(MessageHeader* msg) {
|
|||
} else if (upb_fielddef_isseq(f)) {
|
||||
if (!upb_fielddef_issubmsg(f)) continue;
|
||||
|
||||
zval* array_php = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), offset, CACHED_VALUE*));
|
||||
if (array_php == NULL) continue;
|
||||
zval* array_php = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
|
||||
if (ZVAL_IS_NULL(array_php)) continue;
|
||||
|
||||
int size, i;
|
||||
RepeatedField* intern = UNBOX(RepeatedField, array_php);
|
||||
|
@ -1890,8 +1947,7 @@ static void discard_unknown_fields(MessageHeader* msg) {
|
|||
discard_unknown_fields(submsg);
|
||||
}
|
||||
} else if (upb_fielddef_issubmsg(f)) {
|
||||
zval* submsg_php = CACHED_PTR_TO_ZVAL_PTR(
|
||||
DEREF(message_data(msg), offset, CACHED_VALUE*));
|
||||
zval* submsg_php = CACHED_PTR_TO_ZVAL_PTR(find_zval_property(msg, f));
|
||||
if (Z_TYPE_P(submsg_php) == IS_NULL) continue;
|
||||
MessageHeader* submsg = UNBOX(MessageHeader, submsg_php);
|
||||
discard_unknown_fields(submsg);
|
||||
|
|
|
@ -243,6 +243,18 @@ map_field_handlers->write_dimension = map_field_write_dimension;
|
|||
map_field_handlers->get_gc = map_field_get_gc;
|
||||
PHP_PROTO_INIT_CLASS_END
|
||||
|
||||
void map_field_ensure_created(const upb_fielddef *field,
|
||||
CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) {
|
||||
if (ZVAL_IS_NULL(CACHED_PTR_TO_ZVAL_PTR(map_field))) {
|
||||
zval_ptr_dtor(map_field);
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
MAKE_STD_ZVAL(CACHED_PTR_TO_ZVAL_PTR(map_field));
|
||||
#endif
|
||||
map_field_create_with_field(map_field_type, field,
|
||||
map_field PHP_PROTO_TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
void map_field_create_with_field(const zend_class_entry *ce,
|
||||
const upb_fielddef *field,
|
||||
CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC) {
|
||||
|
|
|
@ -178,7 +178,7 @@ static zval* message_get_property_internal(zval* object,
|
|||
zend_get_property_info(Z_OBJCE_P(object), Z_STR_P(member), true);
|
||||
#endif
|
||||
return layout_get(
|
||||
self->descriptor->layout, message_data(self), field,
|
||||
self->descriptor->layout, self, field,
|
||||
OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ static void message_get_oneof_property_internal(zval* object, zval* member,
|
|||
return;
|
||||
}
|
||||
|
||||
layout_get(self->descriptor->layout, message_data(self), field,
|
||||
layout_get(self->descriptor->layout, self, field,
|
||||
ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,6 @@ void custom_data_init(const zend_class_entry* ce,
|
|||
MessageHeader* intern PHP_PROTO_TSRMLS_DC) {
|
||||
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(ce));
|
||||
intern->data = ALLOC_N(uint8_t, desc->layout->size);
|
||||
memset(message_data(intern), 0, desc->layout->size);
|
||||
// We wrap first so that everything in the message object is GC-rooted in
|
||||
// case a collection happens during object creation in layout_init().
|
||||
intern->descriptor = desc;
|
||||
|
@ -575,9 +574,9 @@ PHP_METHOD(Message, readOneof) {
|
|||
const upb_fielddef* field = upb_msgdef_itof(msg->descriptor->msgdef, index);
|
||||
|
||||
// Unlike singular fields, oneof fields share cached property. So we cannot
|
||||
// let lay_get modify the cached property. Instead, we pass in the return
|
||||
// let layout_get modify the cached property. Instead, we pass in the return
|
||||
// value directly.
|
||||
layout_get(msg->descriptor->layout, message_data(msg), field,
|
||||
layout_get(msg->descriptor->layout, msg, field,
|
||||
ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@
|
|||
|
||||
#define CACHED_VALUE zval*
|
||||
#define CACHED_TO_ZVAL_PTR(VALUE) (VALUE)
|
||||
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*VALUE)
|
||||
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*(CACHED_VALUE*)(VALUE))
|
||||
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE)
|
||||
#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (VALUE)
|
||||
#define ZVAL_TO_CACHED_VALUE(VALUE) (&VALUE)
|
||||
|
@ -475,7 +475,7 @@ static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht,
|
|||
|
||||
#define CACHED_VALUE zval
|
||||
#define CACHED_TO_ZVAL_PTR(VALUE) (&VALUE)
|
||||
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (VALUE)
|
||||
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) ((CACHED_VALUE*)(VALUE))
|
||||
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE)
|
||||
#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (*VALUE)
|
||||
#define ZVAL_TO_CACHED_VALUE(VALUE) (VALUE)
|
||||
|
@ -935,6 +935,7 @@ struct MessageField {
|
|||
|
||||
struct MessageLayout {
|
||||
const upb_msgdef* msgdef;
|
||||
void* empty_template; // Can memcpy() onto a layout to clear it.
|
||||
MessageField* fields;
|
||||
size_t size;
|
||||
};
|
||||
|
@ -948,7 +949,7 @@ PHP_PROTO_WRAP_OBJECT_END
|
|||
MessageLayout* create_layout(const upb_msgdef* msgdef);
|
||||
void layout_init(MessageLayout* layout, void* storage,
|
||||
zend_object* object PHP_PROTO_TSRMLS_DC);
|
||||
zval* layout_get(MessageLayout* layout, const void* storage,
|
||||
zval* layout_get(MessageLayout* layout, MessageHeader* header,
|
||||
const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC);
|
||||
void layout_set(MessageLayout* layout, MessageHeader* header,
|
||||
const upb_fielddef* field, zval* val TSRMLS_DC);
|
||||
|
@ -1089,6 +1090,8 @@ upb_value map_iter_value(MapIter* iter, int* len);
|
|||
const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
|
||||
const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
|
||||
|
||||
void map_field_ensure_created(const upb_fielddef *field,
|
||||
CACHED_VALUE *map_field PHP_PROTO_TSRMLS_DC);
|
||||
void map_field_create_with_field(const zend_class_entry* ce,
|
||||
const upb_fielddef* field,
|
||||
CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC);
|
||||
|
@ -1147,6 +1150,9 @@ PHP_PROTO_WRAP_OBJECT_START(RepeatedFieldIter)
|
|||
long position;
|
||||
PHP_PROTO_WRAP_OBJECT_END
|
||||
|
||||
void repeated_field_ensure_created(
|
||||
const upb_fielddef *field,
|
||||
CACHED_VALUE *repeated_field PHP_PROTO_TSRMLS_DC);
|
||||
void repeated_field_create_with_field(
|
||||
zend_class_entry* ce, const upb_fielddef* field,
|
||||
CACHED_VALUE* repeated_field PHP_PROTO_TSRMLS_DC);
|
||||
|
@ -1489,6 +1495,9 @@ size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
|
|||
#define FREE(object) efree(object)
|
||||
#define PEFREE(object) pefree(object, 1)
|
||||
|
||||
// Find corresponding zval property for the field.
|
||||
CACHED_VALUE* find_zval_property(MessageHeader* msg, const upb_fielddef* field);
|
||||
|
||||
// String argument.
|
||||
#define STR(str) (str), strlen(str)
|
||||
|
||||
|
|
|
@ -75,11 +75,9 @@ static bool native_slot_is_default(upb_fieldtype_t type, const void* memory) {
|
|||
#undef CASE_TYPE
|
||||
case UPB_TYPE_STRING:
|
||||
case UPB_TYPE_BYTES:
|
||||
return Z_STRLEN_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(memory, CACHED_VALUE*))) ==
|
||||
0;
|
||||
return Z_STRLEN_P(CACHED_PTR_TO_ZVAL_PTR(memory)) == 0;
|
||||
case UPB_TYPE_MESSAGE:
|
||||
return Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(memory, CACHED_VALUE*))) ==
|
||||
IS_NULL;
|
||||
return Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(memory)) == IS_NULL;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
@ -599,6 +597,8 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|||
// Reserve space for unknown fields.
|
||||
off += sizeof(void*);
|
||||
|
||||
layout->empty_template = NULL;
|
||||
|
||||
TSRMLS_FETCH();
|
||||
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msgdef));
|
||||
layout->fields = ALLOC_N(MessageField, nfields);
|
||||
|
@ -744,64 +744,35 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|||
layout->size = off;
|
||||
layout->msgdef = msgdef;
|
||||
|
||||
// Create the empty message template.
|
||||
layout->empty_template = ALLOC_N(char, layout->size);
|
||||
memset(layout->empty_template, 0, layout->size);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
void free_layout(MessageLayout* layout) {
|
||||
FREE(layout->empty_template);
|
||||
FREE(layout->fields);
|
||||
FREE(layout);
|
||||
}
|
||||
|
||||
void layout_init(MessageLayout* layout, void* storage,
|
||||
zend_object* object PHP_PROTO_TSRMLS_DC) {
|
||||
int i;
|
||||
upb_msg_field_iter it;
|
||||
|
||||
// Init unknown fields
|
||||
memset(storage, 0, sizeof(void*));
|
||||
|
||||
for (upb_msg_field_begin(&it, layout->msgdef), i = 0; !upb_msg_field_done(&it);
|
||||
upb_msg_field_next(&it), i++) {
|
||||
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);
|
||||
int cache_index = slot_property_cache(layout, storage, field);
|
||||
CACHED_VALUE* property_ptr = OBJ_PROP(object, cache_index);
|
||||
|
||||
if (upb_fielddef_containingoneof(field)) {
|
||||
memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
|
||||
*oneof_case = ONEOF_CASE_NONE;
|
||||
} else if (is_map_field(field)) {
|
||||
zval_ptr_dtor(property_ptr);
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
MAKE_STD_ZVAL(*property_ptr);
|
||||
#endif
|
||||
map_field_create_with_field(map_field_type, field,
|
||||
property_ptr PHP_PROTO_TSRMLS_CC);
|
||||
DEREF(memory, CACHED_VALUE*) = property_ptr;
|
||||
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
||||
zval_ptr_dtor(property_ptr);
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
MAKE_STD_ZVAL(*property_ptr);
|
||||
#endif
|
||||
repeated_field_create_with_field(repeated_field_type, field,
|
||||
property_ptr PHP_PROTO_TSRMLS_CC);
|
||||
DEREF(memory, CACHED_VALUE*) = property_ptr;
|
||||
} else {
|
||||
native_slot_init(upb_fielddef_type(field), memory, property_ptr);
|
||||
}
|
||||
}
|
||||
memcpy(storage, layout->empty_template, layout->size);
|
||||
}
|
||||
|
||||
// For non-singular fields, the related memory needs to point to the actual
|
||||
// zval in properties table first.
|
||||
static void* value_memory(const upb_fielddef* field, void* memory) {
|
||||
switch (upb_fielddef_type(field)) {
|
||||
// Switch memory for processing for singular fields based on field type.
|
||||
// * primitive fields: memory
|
||||
// * others (string, bytes and message): cache (the correspond zval
|
||||
// property)
|
||||
static void* value_memory(
|
||||
upb_fieldtype_t type, void* memory, CACHED_VALUE* cache) {
|
||||
switch (type) {
|
||||
case UPB_TYPE_STRING:
|
||||
case UPB_TYPE_BYTES:
|
||||
case UPB_TYPE_MESSAGE:
|
||||
memory = DEREF(memory, CACHED_VALUE*);
|
||||
break;
|
||||
return cache;
|
||||
default:
|
||||
// No operation
|
||||
break;
|
||||
|
@ -809,8 +780,17 @@ static void* value_memory(const upb_fielddef* field, void* memory) {
|
|||
return memory;
|
||||
}
|
||||
|
||||
zval* layout_get(MessageLayout* layout, const void* storage,
|
||||
CACHED_VALUE* find_zval_property(
|
||||
MessageHeader* header, const upb_fielddef* field) {
|
||||
int property_cache_index =
|
||||
header->descriptor->layout->fields[upb_fielddef_index(field)]
|
||||
.cache_index;
|
||||
return OBJ_PROP(&header->std, property_cache_index);
|
||||
}
|
||||
|
||||
zval* layout_get(MessageLayout* layout, MessageHeader* header,
|
||||
const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC) {
|
||||
const void* storage = message_data(header);
|
||||
void* memory = slot_memory(layout, storage, field);
|
||||
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
||||
|
||||
|
@ -818,14 +798,21 @@ zval* layout_get(MessageLayout* layout, const void* storage,
|
|||
if (*oneof_case != upb_fielddef_number(field)) {
|
||||
native_slot_get_default(upb_fielddef_type(field), cache TSRMLS_CC);
|
||||
} else {
|
||||
native_slot_get(upb_fielddef_type(field), value_memory(field, memory),
|
||||
cache TSRMLS_CC);
|
||||
upb_fieldtype_t type = upb_fielddef_type(field);
|
||||
CACHED_VALUE* stored_cache = find_zval_property(header, field);
|
||||
native_slot_get(
|
||||
type, value_memory(type, memory, stored_cache), cache TSRMLS_CC);
|
||||
}
|
||||
return CACHED_PTR_TO_ZVAL_PTR(cache);
|
||||
} else if (is_map_field(field)) {
|
||||
map_field_ensure_created(field, cache PHP_PROTO_TSRMLS_CC);
|
||||
return CACHED_PTR_TO_ZVAL_PTR(cache);
|
||||
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
||||
repeated_field_ensure_created(field, cache PHP_PROTO_TSRMLS_CC);
|
||||
return CACHED_PTR_TO_ZVAL_PTR(cache);
|
||||
} else {
|
||||
native_slot_get(upb_fielddef_type(field), value_memory(field, memory),
|
||||
upb_fieldtype_t type = upb_fielddef_type(field);
|
||||
native_slot_get(type, value_memory(type, memory, cache),
|
||||
cache TSRMLS_CC);
|
||||
return CACHED_PTR_TO_ZVAL_PTR(cache);
|
||||
}
|
||||
|
@ -868,8 +855,8 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
|
|||
*oneof_case = upb_fielddef_number(field);
|
||||
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
||||
// Works for both repeated and map fields
|
||||
memory = DEREF(memory, void**);
|
||||
zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
|
||||
CACHED_VALUE* cached = find_zval_property(header, field);
|
||||
zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR(cached);
|
||||
|
||||
if (EXPECTED(property_ptr != val)) {
|
||||
zend_class_entry *subce = NULL;
|
||||
|
@ -901,7 +888,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
|
|||
&converted_value);
|
||||
}
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
REPLACE_ZVAL_VALUE((zval**)memory, &converted_value, 1);
|
||||
REPLACE_ZVAL_VALUE((zval**)cached, &converted_value, 1);
|
||||
#else
|
||||
php_proto_zval_ptr_dtor(property_ptr);
|
||||
ZVAL_ZVAL(property_ptr, &converted_value, 1, 0);
|
||||
|
@ -916,12 +903,16 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
|
|||
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg));
|
||||
ce = desc->klass;
|
||||
}
|
||||
native_slot_set(type, ce, value_memory(field, memory), val TSRMLS_CC);
|
||||
CACHED_VALUE* cache = find_zval_property(header, field);
|
||||
native_slot_set(
|
||||
type, ce, value_memory(upb_fielddef_type(field), memory, cache),
|
||||
val TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
static void native_slot_merge(const upb_fielddef* field, const void* from_memory,
|
||||
void* to_memory PHP_PROTO_TSRMLS_DC) {
|
||||
static void native_slot_merge(
|
||||
const upb_fielddef* field, const void* from_memory,
|
||||
void* to_memory PHP_PROTO_TSRMLS_DC) {
|
||||
upb_fieldtype_t type = upb_fielddef_type(field);
|
||||
zend_class_entry* ce = NULL;
|
||||
if (!native_slot_is_default(type, from_memory)) {
|
||||
|
@ -943,9 +934,8 @@ static void native_slot_merge(const upb_fielddef* field, const void* from_memory
|
|||
#undef CASE_TYPE
|
||||
case UPB_TYPE_STRING:
|
||||
case UPB_TYPE_BYTES:
|
||||
native_slot_set(type, NULL, value_memory(field, to_memory),
|
||||
CACHED_PTR_TO_ZVAL_PTR(DEREF(
|
||||
from_memory, CACHED_VALUE*)) PHP_PROTO_TSRMLS_CC);
|
||||
native_slot_set(type, NULL, to_memory,
|
||||
CACHED_PTR_TO_ZVAL_PTR(from_memory) PHP_PROTO_TSRMLS_CC);
|
||||
break;
|
||||
case UPB_TYPE_MESSAGE: {
|
||||
const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
|
||||
|
@ -953,22 +943,21 @@ static void native_slot_merge(const upb_fielddef* field, const void* from_memory
|
|||
ce = desc->klass;
|
||||
if (native_slot_is_default(type, to_memory)) {
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
SEPARATE_ZVAL_IF_NOT_REF((zval**)value_memory(field, to_memory));
|
||||
SEPARATE_ZVAL_IF_NOT_REF((zval**)to_memory);
|
||||
#endif
|
||||
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(
|
||||
CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*)), ce);
|
||||
CACHED_PTR_TO_ZVAL_PTR(to_memory), ce);
|
||||
MessageHeader* submsg =
|
||||
UNBOX(MessageHeader,
|
||||
CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*)));
|
||||
UNBOX(MessageHeader, CACHED_PTR_TO_ZVAL_PTR(to_memory));
|
||||
custom_data_init(ce, submsg PHP_PROTO_TSRMLS_CC);
|
||||
}
|
||||
|
||||
MessageHeader* sub_from =
|
||||
UNBOX(MessageHeader,
|
||||
CACHED_PTR_TO_ZVAL_PTR(DEREF(from_memory, CACHED_VALUE*)));
|
||||
CACHED_PTR_TO_ZVAL_PTR(from_memory));
|
||||
MessageHeader* sub_to =
|
||||
UNBOX(MessageHeader,
|
||||
CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*)));
|
||||
CACHED_PTR_TO_ZVAL_PTR(to_memory));
|
||||
|
||||
layout_merge(desc->layout, sub_from, sub_to PHP_PROTO_TSRMLS_CC);
|
||||
break;
|
||||
|
@ -1069,10 +1058,17 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
|
|||
int size, key_length, value_length;
|
||||
MapIter map_it;
|
||||
|
||||
zval* to_map_php =
|
||||
CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*));
|
||||
zval* from_map_php =
|
||||
CACHED_PTR_TO_ZVAL_PTR(DEREF(from_memory, CACHED_VALUE*));
|
||||
CACHED_VALUE* from_cache = find_zval_property(from, field);
|
||||
CACHED_VALUE* to_cache = find_zval_property(to, field);
|
||||
|
||||
if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(from_cache)) == IS_NULL) {
|
||||
continue;
|
||||
}
|
||||
map_field_ensure_created(field, to_cache PHP_PROTO_TSRMLS_CC);
|
||||
|
||||
zval* to_map_php = CACHED_PTR_TO_ZVAL_PTR(to_cache);
|
||||
zval* from_map_php = CACHED_PTR_TO_ZVAL_PTR(from_cache);
|
||||
|
||||
Map* to_map = UNBOX(Map, to_map_php);
|
||||
Map* from_map = UNBOX(Map, from_map_php);
|
||||
|
||||
|
@ -1098,8 +1094,16 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
|
|||
}
|
||||
|
||||
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
||||
zval* to_array_php = CACHED_PTR_TO_ZVAL_PTR(DEREF(to_memory, CACHED_VALUE*));
|
||||
zval* from_array_php = CACHED_PTR_TO_ZVAL_PTR(DEREF(from_memory, CACHED_VALUE*));
|
||||
CACHED_VALUE* from_cache = find_zval_property(from, field);
|
||||
CACHED_VALUE* to_cache = find_zval_property(to, field);
|
||||
|
||||
if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(from_cache)) == IS_NULL) {
|
||||
continue;
|
||||
}
|
||||
repeated_field_ensure_created(field, to_cache PHP_PROTO_TSRMLS_CC);
|
||||
|
||||
zval* to_array_php = CACHED_PTR_TO_ZVAL_PTR(to_cache);
|
||||
zval* from_array_php = CACHED_PTR_TO_ZVAL_PTR(from_cache);
|
||||
RepeatedField* to_array = UNBOX(RepeatedField, to_array_php);
|
||||
RepeatedField* from_array = UNBOX(RepeatedField, from_array_php);
|
||||
|
||||
|
@ -1129,7 +1133,19 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
native_slot_merge(field, from_memory, to_memory PHP_PROTO_TSRMLS_CC);
|
||||
switch (upb_fielddef_type(field)) {
|
||||
case UPB_TYPE_STRING:
|
||||
case UPB_TYPE_BYTES:
|
||||
case UPB_TYPE_MESSAGE: {
|
||||
CACHED_VALUE* from_cache = find_zval_property(from, field);
|
||||
CACHED_VALUE* to_cache = find_zval_property(to, field);
|
||||
native_slot_merge(field, from_cache, to_cache PHP_PROTO_TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
native_slot_merge(field, from_memory, to_memory PHP_PROTO_TSRMLS_CC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue