Commit edda0c92 authored by Paul Yang's avatar Paul Yang Committed by Rafi Kamal

Persistent Descriptor Pool (#6899)

* Make reserve names map persistent

* Add DescriptorInternal to map

* Use get_msgdef_desc in encode_decode.c

* Add persistent map for ce=>def and enum=>def

* Replace get_ce_obj

* Remove get_proto_obj

* Remove obsolete fields from Descriptor and EnumDescriptor

* Add cache for descriptor php values

* Add cache for descriptors

* Fix bug

* Avoid add generated file again if it has been added

* Fix the bug upb depends on null-ended str for look up.

* Initialize generated pool impl

* Turn down old generated pool

* Add init entry flag protobuf.keep_descriptor_pool_after_request

By default, it's off. Add protobuf.keep_descriptor_pool_after_request=1 to php.ini to enable it

* Fix zts build
parent cd7b27be
...@@ -148,19 +148,15 @@ static zend_function_entry descriptor_methods[] = { ...@@ -148,19 +148,15 @@ static zend_function_entry descriptor_methods[] = {
DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Descriptor"); DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Descriptor");
static void descriptor_free_c(Descriptor *self TSRMLS_DC) { static void descriptor_free_c(Descriptor *self TSRMLS_DC) {
if (self->layout) {
free_layout(self->layout);
}
} }
static void descriptor_init_c_instance(Descriptor *desc TSRMLS_DC) { static void descriptor_init_c_instance(Descriptor *desc TSRMLS_DC) {
desc->msgdef = NULL; desc->intern = NULL;
desc->layout = NULL;
desc->klass = NULL;
} }
PHP_METHOD(Descriptor, getClass) { PHP_METHOD(Descriptor, getClass) {
Descriptor *intern = UNBOX(Descriptor, getThis()); Descriptor* desc = UNBOX(Descriptor, getThis());
DescriptorInternal* intern = desc->intern;
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
const char* classname = intern->klass->name; const char* classname = intern->klass->name;
#else #else
...@@ -170,7 +166,8 @@ PHP_METHOD(Descriptor, getClass) { ...@@ -170,7 +166,8 @@ PHP_METHOD(Descriptor, getClass) {
} }
PHP_METHOD(Descriptor, getFullName) { PHP_METHOD(Descriptor, getFullName) {
Descriptor *intern = UNBOX(Descriptor, getThis()); Descriptor* desc = UNBOX(Descriptor, getThis());
DescriptorInternal* intern = desc->intern;
const char* fullname = upb_msgdef_fullname(intern->msgdef); const char* fullname = upb_msgdef_fullname(intern->msgdef);
PHP_PROTO_RETVAL_STRINGL(fullname, strlen(fullname), 1); PHP_PROTO_RETVAL_STRINGL(fullname, strlen(fullname), 1);
} }
...@@ -183,7 +180,8 @@ PHP_METHOD(Descriptor, getField) { ...@@ -183,7 +180,8 @@ PHP_METHOD(Descriptor, getField) {
return; return;
} }
Descriptor *intern = UNBOX(Descriptor, getThis()); Descriptor* desc = UNBOX(Descriptor, getThis());
DescriptorInternal* intern = desc->intern;
int field_num = upb_msgdef_numfields(intern->msgdef); int field_num = upb_msgdef_numfields(intern->msgdef);
if (index < 0 || index >= field_num) { if (index < 0 || index >= field_num) {
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
...@@ -224,7 +222,8 @@ PHP_METHOD(Descriptor, getField) { ...@@ -224,7 +222,8 @@ PHP_METHOD(Descriptor, getField) {
} }
PHP_METHOD(Descriptor, getFieldCount) { PHP_METHOD(Descriptor, getFieldCount) {
Descriptor *intern = UNBOX(Descriptor, getThis()); Descriptor* desc = UNBOX(Descriptor, getThis());
DescriptorInternal* intern = desc->intern;
RETURN_LONG(upb_msgdef_numfields(intern->msgdef)); RETURN_LONG(upb_msgdef_numfields(intern->msgdef));
} }
...@@ -236,7 +235,8 @@ PHP_METHOD(Descriptor, getOneofDecl) { ...@@ -236,7 +235,8 @@ PHP_METHOD(Descriptor, getOneofDecl) {
return; return;
} }
Descriptor *intern = UNBOX(Descriptor, getThis()); Descriptor* desc = UNBOX(Descriptor, getThis());
DescriptorInternal* intern = desc->intern;
int field_num = upb_msgdef_numoneofs(intern->msgdef); int field_num = upb_msgdef_numoneofs(intern->msgdef);
if (index < 0 || index >= field_num) { if (index < 0 || index >= field_num) {
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
...@@ -257,7 +257,8 @@ PHP_METHOD(Descriptor, getOneofDecl) { ...@@ -257,7 +257,8 @@ PHP_METHOD(Descriptor, getOneofDecl) {
} }
PHP_METHOD(Descriptor, getOneofDeclCount) { PHP_METHOD(Descriptor, getOneofDeclCount) {
Descriptor *intern = UNBOX(Descriptor, getThis()); Descriptor* desc = UNBOX(Descriptor, getThis());
DescriptorInternal* intern = desc->intern;
RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef)); RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef));
} }
...@@ -278,8 +279,7 @@ static void enum_descriptor_free_c(EnumDescriptor *self TSRMLS_DC) { ...@@ -278,8 +279,7 @@ static void enum_descriptor_free_c(EnumDescriptor *self TSRMLS_DC) {
} }
static void enum_descriptor_init_c_instance(EnumDescriptor *self TSRMLS_DC) { static void enum_descriptor_init_c_instance(EnumDescriptor *self TSRMLS_DC) {
self->enumdef = NULL; self->intern = NULL;
self->klass = NULL;
} }
PHP_METHOD(EnumDescriptor, getValue) { PHP_METHOD(EnumDescriptor, getValue) {
...@@ -290,7 +290,8 @@ PHP_METHOD(EnumDescriptor, getValue) { ...@@ -290,7 +290,8 @@ PHP_METHOD(EnumDescriptor, getValue) {
return; return;
} }
EnumDescriptor *intern = UNBOX(EnumDescriptor, getThis()); EnumDescriptor *desc = UNBOX(EnumDescriptor, getThis());
EnumDescriptorInternal *intern = desc->intern;
int field_num = upb_enumdef_numvals(intern->enumdef); int field_num = upb_enumdef_numvals(intern->enumdef);
if (index < 0 || index >= field_num) { if (index < 0 || index >= field_num) {
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
...@@ -312,7 +313,8 @@ PHP_METHOD(EnumDescriptor, getValue) { ...@@ -312,7 +313,8 @@ PHP_METHOD(EnumDescriptor, getValue) {
} }
PHP_METHOD(EnumDescriptor, getValueCount) { PHP_METHOD(EnumDescriptor, getValueCount) {
EnumDescriptor *intern = UNBOX(EnumDescriptor, getThis()); EnumDescriptor *desc = UNBOX(EnumDescriptor, getThis());
EnumDescriptorInternal *intern = desc->intern;
RETURN_LONG(upb_enumdef_numvals(intern->enumdef)); RETURN_LONG(upb_enumdef_numvals(intern->enumdef));
} }
...@@ -440,13 +442,32 @@ PHP_METHOD(FieldDescriptor, getEnumType) { ...@@ -440,13 +442,32 @@ PHP_METHOD(FieldDescriptor, getEnumType) {
return; return;
} }
const upb_enumdef *enumdef = upb_fielddef_enumsubdef(intern->fielddef); const upb_enumdef *enumdef = upb_fielddef_enumsubdef(intern->fielddef);
PHP_PROTO_HASHTABLE_VALUE desc = get_def_obj(enumdef); PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(enumdef);
if (desc_php == NULL) {
EnumDescriptorInternal* intern = get_enumdef_enumdesc(enumdef);
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
RETURN_ZVAL(desc, 1, 0); MAKE_STD_ZVAL(desc_php);
ZVAL_OBJ(desc_php, enum_descriptor_type->create_object(
enum_descriptor_type TSRMLS_CC));
Z_DELREF_P(desc_php);
#else #else
GC_ADDREF(desc); desc_php =
RETURN_OBJ(desc); enum_descriptor_type->create_object(enum_descriptor_type TSRMLS_CC);
GC_DELREF(desc_php);
#endif
EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE(EnumDescriptor, desc_php);
desc->intern = intern;
add_def_obj(enumdef, desc_php);
add_ce_obj(intern->klass, desc_php);
}
#if PHP_MAJOR_VERSION < 7
RETURN_ZVAL(desc_php, 1, 0);
#else
GC_ADDREF(desc_php);
RETURN_OBJ(desc_php);
#endif #endif
} }
...@@ -459,13 +480,32 @@ PHP_METHOD(FieldDescriptor, getMessageType) { ...@@ -459,13 +480,32 @@ PHP_METHOD(FieldDescriptor, getMessageType) {
return; return;
} }
const upb_msgdef *msgdef = upb_fielddef_msgsubdef(intern->fielddef); const upb_msgdef *msgdef = upb_fielddef_msgsubdef(intern->fielddef);
PHP_PROTO_HASHTABLE_VALUE desc = get_def_obj(msgdef); PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(msgdef);
if (desc_php == NULL) {
DescriptorInternal* intern = get_msgdef_desc(msgdef);
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(desc_php);
ZVAL_OBJ(desc_php, descriptor_type->create_object(
descriptor_type TSRMLS_CC));
Z_DELREF_P(desc_php);
#else
desc_php =
descriptor_type->create_object(descriptor_type TSRMLS_CC);
GC_DELREF(desc_php);
#endif
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
desc->intern = intern;
add_def_obj(msgdef, desc_php);
add_ce_obj(intern->klass, desc_php);
}
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
RETURN_ZVAL(desc, 1, 0); RETURN_ZVAL(desc_php, 1, 0);
#else #else
GC_ADDREF(desc); GC_ADDREF(desc_php);
RETURN_OBJ(desc); RETURN_OBJ(desc_php);
#endif #endif
} }
...@@ -579,7 +619,8 @@ zval* internal_generated_pool_php; ...@@ -579,7 +619,8 @@ zval* internal_generated_pool_php;
zend_object *generated_pool_php; zend_object *generated_pool_php;
zend_object *internal_generated_pool_php; zend_object *internal_generated_pool_php;
#endif #endif
InternalDescriptorPool *generated_pool; // The actual generated pool InternalDescriptorPoolImpl *generated_pool;
InternalDescriptorPoolImpl generated_pool_impl; // The actual generated pool
void init_generated_pool_once(TSRMLS_D) { void init_generated_pool_once(TSRMLS_D) {
if (generated_pool == NULL) { if (generated_pool == NULL) {
...@@ -589,22 +630,29 @@ void init_generated_pool_once(TSRMLS_D) { ...@@ -589,22 +630,29 @@ void init_generated_pool_once(TSRMLS_D) {
ZVAL_OBJ(internal_generated_pool_php, ZVAL_OBJ(internal_generated_pool_php,
internal_descriptor_pool_type->create_object( internal_descriptor_pool_type->create_object(
internal_descriptor_pool_type TSRMLS_CC)); internal_descriptor_pool_type TSRMLS_CC));
generated_pool = UNBOX(InternalDescriptorPool, internal_generated_pool_php);
ZVAL_OBJ(generated_pool_php, descriptor_pool_type->create_object( ZVAL_OBJ(generated_pool_php, descriptor_pool_type->create_object(
descriptor_pool_type TSRMLS_CC)); descriptor_pool_type TSRMLS_CC));
#else #else
internal_generated_pool_php = internal_descriptor_pool_type->create_object( internal_generated_pool_php = internal_descriptor_pool_type->create_object(
internal_descriptor_pool_type TSRMLS_CC); internal_descriptor_pool_type TSRMLS_CC);
generated_pool = (InternalDescriptorPool *)((char *)internal_generated_pool_php -
XtOffsetOf(InternalDescriptorPool, std));
generated_pool_php = generated_pool_php =
descriptor_pool_type->create_object(descriptor_pool_type TSRMLS_CC); descriptor_pool_type->create_object(descriptor_pool_type TSRMLS_CC);
#endif #endif
generated_pool = &generated_pool_impl;
} }
} }
static void internal_descriptor_pool_init_c_instance( static void internal_descriptor_pool_init_c_instance(
InternalDescriptorPool *pool TSRMLS_DC) { InternalDescriptorPool *pool TSRMLS_DC) {
pool->intern = &generated_pool_impl;
}
static void internal_descriptor_pool_free_c(
InternalDescriptorPool *pool TSRMLS_DC) {
}
void internal_descriptor_pool_impl_init(
InternalDescriptorPoolImpl *pool TSRMLS_DC) {
pool->symtab = upb_symtab_new(); pool->symtab = upb_symtab_new();
pool->fill_handler_cache = pool->fill_handler_cache =
upb_handlercache_new(add_handlers_for_message, NULL); upb_handlercache_new(add_handlers_for_message, NULL);
...@@ -615,8 +663,8 @@ static void internal_descriptor_pool_init_c_instance( ...@@ -615,8 +663,8 @@ static void internal_descriptor_pool_init_c_instance(
pool->json_fill_method_cache = upb_json_codecache_new(); pool->json_fill_method_cache = upb_json_codecache_new();
} }
static void internal_descriptor_pool_free_c( void internal_descriptor_pool_impl_destroy(
InternalDescriptorPool *pool TSRMLS_DC) { InternalDescriptorPoolImpl *pool TSRMLS_DC) {
upb_symtab_free(pool->symtab); upb_symtab_free(pool->symtab);
upb_handlercache_free(pool->fill_handler_cache); upb_handlercache_free(pool->fill_handler_cache);
upb_handlercache_free(pool->pb_serialize_handler_cache); upb_handlercache_free(pool->pb_serialize_handler_cache);
...@@ -837,7 +885,8 @@ static void fill_classname(const char *fullname, ...@@ -837,7 +885,8 @@ static void fill_classname(const char *fullname,
static zend_class_entry *register_class(const upb_filedef *file, static zend_class_entry *register_class(const upb_filedef *file,
const char *fullname, const char *fullname,
PHP_PROTO_HASHTABLE_VALUE desc_php, PHP_PROTO_HASHTABLE_VALUE desc_php,
bool use_nested_submsg TSRMLS_DC) { bool use_nested_submsg,
bool is_enum TSRMLS_DC) {
// Prepend '.' to package name to make it absolute. In the 5 additional // Prepend '.' to package name to make it absolute. In the 5 additional
// bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if // bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if
// given message is google.protobuf.Empty. // given message is google.protobuf.Empty.
...@@ -866,7 +915,15 @@ static zend_class_entry *register_class(const upb_filedef *file, ...@@ -866,7 +915,15 @@ static zend_class_entry *register_class(const upb_filedef *file,
} }
ret = PHP_PROTO_CE_UNREF(pce); ret = PHP_PROTO_CE_UNREF(pce);
add_ce_obj(ret, desc_php); add_ce_obj(ret, desc_php);
add_proto_obj(fullname, desc_php); if (is_enum) {
EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE(EnumDescriptor, desc_php);
add_ce_enumdesc(ret, desc->intern);
add_proto_enumdesc(fullname, desc->intern);
} else {
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
add_ce_desc(ret, desc->intern);
add_proto_desc(fullname, desc->intern);
}
stringsink_uninit(&namesink); stringsink_uninit(&namesink);
return ret; return ret;
} }
...@@ -888,7 +945,7 @@ bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) { ...@@ -888,7 +945,7 @@ bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) {
const upb_filedef *parse_and_add_descriptor(const char *data, const upb_filedef *parse_and_add_descriptor(const char *data,
PHP_PROTO_SIZE data_len, PHP_PROTO_SIZE data_len,
InternalDescriptorPool *pool, InternalDescriptorPoolImpl *pool,
upb_arena *arena) { upb_arena *arena) {
size_t n; size_t n;
google_protobuf_FileDescriptorSet *set; google_protobuf_FileDescriptorSet *set;
...@@ -901,14 +958,22 @@ const upb_filedef *parse_and_add_descriptor(const char *data, ...@@ -901,14 +958,22 @@ const upb_filedef *parse_and_add_descriptor(const char *data,
if (!set) { if (!set) {
zend_error(E_ERROR, "Failed to parse binary descriptor\n"); zend_error(E_ERROR, "Failed to parse binary descriptor\n");
return false; return NULL;
} }
files = google_protobuf_FileDescriptorSet_file(set, &n); files = google_protobuf_FileDescriptorSet_file(set, &n);
if (n != 1) { if (n != 1) {
zend_error(E_ERROR, "Serialized descriptors should have exactly one file"); zend_error(E_ERROR, "Serialized descriptors should have exactly one file");
return false; return NULL;
}
// Check whether file has already been added.
upb_strview name = google_protobuf_FileDescriptorProto_name(files[0]);
// TODO(teboring): Needs another look up method which takes data and length.
file = upb_symtab_lookupfile2(pool->symtab, name.data, name.size);
if (file != NULL) {
return NULL;
} }
// The PHP code generator currently special-cases descriptor.proto. It // The PHP code generator currently special-cases descriptor.proto. It
...@@ -919,7 +984,7 @@ const upb_filedef *parse_and_add_descriptor(const char *data, ...@@ -919,7 +984,7 @@ const upb_filedef *parse_and_add_descriptor(const char *data,
NULL) { NULL) {
if (!parse_and_add_descriptor((char *)descriptor_proto, if (!parse_and_add_descriptor((char *)descriptor_proto,
descriptor_proto_len, pool, arena)) { descriptor_proto_len, pool, arena)) {
return false; return NULL;
} }
} }
...@@ -930,7 +995,7 @@ const upb_filedef *parse_and_add_descriptor(const char *data, ...@@ -930,7 +995,7 @@ const upb_filedef *parse_and_add_descriptor(const char *data,
} }
void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len, void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
InternalDescriptorPool *pool, InternalDescriptorPoolImpl *pool,
bool use_nested_submsg TSRMLS_DC) { bool use_nested_submsg TSRMLS_DC) {
int i; int i;
upb_arena *arena; upb_arena *arena;
...@@ -949,9 +1014,14 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len, ...@@ -949,9 +1014,14 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
for (i = 0; i < upb_filedef_msgcount(file); i++) { for (i = 0; i < upb_filedef_msgcount(file); i++) {
const upb_msgdef *msgdef = upb_filedef_msg(file, i); const upb_msgdef *msgdef = upb_filedef_msg(file, i);
CREATE_HASHTABLE_VALUE(desc, desc_php, Descriptor, descriptor_type); CREATE_HASHTABLE_VALUE(desc, desc_php, Descriptor, descriptor_type);
desc->msgdef = msgdef; desc->intern = SYS_MALLOC(DescriptorInternal);
desc->pool = pool; desc->intern->msgdef = msgdef;
add_def_obj(desc->msgdef, desc_php); desc->intern->pool = pool;
desc->intern->layout = NULL;
desc->intern->klass = NULL;
add_def_obj(desc->intern->msgdef, desc_php);
add_msgdef_desc(desc->intern->msgdef, desc->intern);
// Unlike other messages, MapEntry is shared by all map fields and doesn't // Unlike other messages, MapEntry is shared by all map fields and doesn't
// have generated PHP class. // have generated PHP class.
...@@ -959,10 +1029,11 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len, ...@@ -959,10 +1029,11 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
continue; continue;
} }
desc->klass = register_class(file, upb_msgdef_fullname(msgdef), desc_php, desc->intern->klass =
use_nested_submsg TSRMLS_CC); register_class(file, upb_msgdef_fullname(msgdef), desc_php,
use_nested_submsg, false TSRMLS_CC);
if (desc->klass == NULL) { if (desc->intern->klass == NULL) {
return; return;
} }
...@@ -972,12 +1043,17 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len, ...@@ -972,12 +1043,17 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
for (i = 0; i < upb_filedef_enumcount(file); i++) { for (i = 0; i < upb_filedef_enumcount(file); i++) {
const upb_enumdef *enumdef = upb_filedef_enum(file, i); const upb_enumdef *enumdef = upb_filedef_enum(file, i);
CREATE_HASHTABLE_VALUE(desc, desc_php, EnumDescriptor, enum_descriptor_type); CREATE_HASHTABLE_VALUE(desc, desc_php, EnumDescriptor, enum_descriptor_type);
desc->enumdef = enumdef; desc->intern = SYS_MALLOC(EnumDescriptorInternal);
add_def_obj(desc->enumdef, desc_php); desc->intern->enumdef = enumdef;
desc->klass = register_class(file, upb_enumdef_fullname(enumdef), desc_php, desc->intern->klass = NULL;
use_nested_submsg TSRMLS_CC);
add_def_obj(desc->intern->enumdef, desc_php);
add_enumdef_enumdesc(desc->intern->enumdef, desc->intern);
desc->intern->klass =
register_class(file, upb_enumdef_fullname(enumdef), desc_php,
use_nested_submsg, true TSRMLS_CC);
if (desc->klass == NULL) { if (desc->intern->klass == NULL) {
return; return;
} }
} }
...@@ -997,14 +1073,11 @@ PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) { ...@@ -997,14 +1073,11 @@ PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
} }
InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis()); InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis());
internal_add_generated_file(data, data_len, pool, internal_add_generated_file(data, data_len, pool->intern,
use_nested_submsg TSRMLS_CC); use_nested_submsg TSRMLS_CC);
} }
PHP_METHOD(DescriptorPool, getDescriptorByClassName) { PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
DescriptorPool *public_pool = UNBOX(DescriptorPool, getThis());
InternalDescriptorPool *pool = public_pool->intern;
char *classname = NULL; char *classname = NULL;
PHP_PROTO_SIZE classname_len; PHP_PROTO_SIZE classname_len;
...@@ -1019,29 +1092,44 @@ PHP_METHOD(DescriptorPool, getDescriptorByClassName) { ...@@ -1019,29 +1092,44 @@ PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
RETURN_NULL(); RETURN_NULL();
} }
PHP_PROTO_HASHTABLE_VALUE desc = get_ce_obj(PHP_PROTO_CE_UNREF(pce)); PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(PHP_PROTO_CE_UNREF(pce));
if (desc == NULL) { if (desc_php == NULL) {
RETURN_NULL(); DescriptorInternal* intern = get_ce_desc(PHP_PROTO_CE_UNREF(pce));
if (intern == NULL) {
RETURN_NULL();
}
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(desc_php);
ZVAL_OBJ(desc_php, descriptor_type->create_object(
descriptor_type TSRMLS_CC));
Z_DELREF_P(desc_php);
#else
desc_php =
descriptor_type->create_object(descriptor_type TSRMLS_CC);
GC_DELREF(desc_php);
#endif
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
desc->intern = intern;
add_def_obj(intern->msgdef, desc_php);
add_ce_obj(PHP_PROTO_CE_UNREF(pce), desc_php);
} }
zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc); zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc_php);
if (!instanceof_function(instance_ce, descriptor_type TSRMLS_CC)) { if (!instanceof_function(instance_ce, descriptor_type TSRMLS_CC)) {
RETURN_NULL(); RETURN_NULL();
} }
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
RETURN_ZVAL(desc, 1, 0); RETURN_ZVAL(desc_php, 1, 0);
#else #else
GC_ADDREF(desc); GC_ADDREF(desc_php);
RETURN_OBJ(desc); RETURN_OBJ(desc_php);
#endif #endif
} }
PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) { PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
DescriptorPool *public_pool = UNBOX(DescriptorPool, getThis());
InternalDescriptorPool *pool = public_pool->intern;
char *classname = NULL; char *classname = NULL;
PHP_PROTO_SIZE classname_len; PHP_PROTO_SIZE classname_len;
...@@ -1056,21 +1144,39 @@ PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) { ...@@ -1056,21 +1144,39 @@ PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
RETURN_NULL(); RETURN_NULL();
} }
PHP_PROTO_HASHTABLE_VALUE desc = get_ce_obj(PHP_PROTO_CE_UNREF(pce)); PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(PHP_PROTO_CE_UNREF(pce));
if (desc == NULL) { if (desc_php == NULL) {
RETURN_NULL(); EnumDescriptorInternal* intern = get_ce_enumdesc(PHP_PROTO_CE_UNREF(pce));
if (intern == NULL) {
RETURN_NULL();
}
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(desc_php);
ZVAL_OBJ(desc_php, enum_descriptor_type->create_object(
enum_descriptor_type TSRMLS_CC));
Z_DELREF_P(desc_php);
#else
desc_php =
enum_descriptor_type->create_object(enum_descriptor_type TSRMLS_CC);
GC_DELREF(desc_php);
#endif
EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE(EnumDescriptor, desc_php);
desc->intern = intern;
add_def_obj(intern->enumdef, desc_php);
add_ce_obj(PHP_PROTO_CE_UNREF(pce), desc_php);
} }
zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc); zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc_php);
if (!instanceof_function(instance_ce, enum_descriptor_type TSRMLS_CC)) { if (!instanceof_function(instance_ce, enum_descriptor_type TSRMLS_CC)) {
RETURN_NULL(); RETURN_NULL();
} }
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
RETURN_ZVAL(desc, 1, 0); RETURN_ZVAL(desc_php, 1, 0);
#else #else
GC_ADDREF(desc); GC_ADDREF(desc_php);
RETURN_OBJ(desc); RETURN_OBJ(desc_php);
#endif #endif
} }
...@@ -428,8 +428,7 @@ static void *appendsubmsg_handler(void *closure, const void *hd) { ...@@ -428,8 +428,7 @@ static void *appendsubmsg_handler(void *closure, const void *hd) {
RepeatedField* intern = UNBOX(RepeatedField, array); RepeatedField* intern = UNBOX(RepeatedField, array);
const submsg_handlerdata_t *submsgdata = hd; const submsg_handlerdata_t *submsgdata = hd;
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
MessageHeader* submsg; MessageHeader* submsg;
...@@ -456,8 +455,7 @@ static void *appendwrappersubmsg_handler(void *closure, const void *hd) { ...@@ -456,8 +455,7 @@ static void *appendwrappersubmsg_handler(void *closure, const void *hd) {
RepeatedField* intern = UNBOX(RepeatedField, array); RepeatedField* intern = UNBOX(RepeatedField, array);
const submsg_handlerdata_t *submsgdata = hd; const submsg_handlerdata_t *submsgdata = hd;
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
MessageHeader* submsg; MessageHeader* submsg;
wrapperfields_parseframe_t* frame = wrapperfields_parseframe_t* frame =
...@@ -488,8 +486,7 @@ static void *submsg_handler(void *closure, const void *hd) { ...@@ -488,8 +486,7 @@ static void *submsg_handler(void *closure, const void *hd) {
MessageHeader* msg = closure; MessageHeader* msg = closure;
const submsg_handlerdata_t* submsgdata = hd; const submsg_handlerdata_t* submsgdata = hd;
TSRMLS_FETCH(); TSRMLS_FETCH();
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
zval* submsg_php; zval* submsg_php;
MessageHeader* submsg; MessageHeader* submsg;
...@@ -522,8 +519,7 @@ static void *map_submsg_handler(void *closure, const void *hd) { ...@@ -522,8 +519,7 @@ static void *map_submsg_handler(void *closure, const void *hd) {
MessageHeader* msg = closure; MessageHeader* msg = closure;
const submsg_handlerdata_t* submsgdata = hd; const submsg_handlerdata_t* submsgdata = hd;
TSRMLS_FETCH(); TSRMLS_FETCH();
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
zval* submsg_php; zval* submsg_php;
MessageHeader* submsg; MessageHeader* submsg;
...@@ -557,8 +553,7 @@ static void *map_wrapper_submsg_handler(void *closure, const void *hd) { ...@@ -557,8 +553,7 @@ static void *map_wrapper_submsg_handler(void *closure, const void *hd) {
MessageHeader* msg = closure; MessageHeader* msg = closure;
const submsg_handlerdata_t* submsgdata = hd; const submsg_handlerdata_t* submsgdata = hd;
TSRMLS_FETCH(); TSRMLS_FETCH();
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
zval* submsg_php; zval* submsg_php;
MessageHeader* submsg; MessageHeader* submsg;
...@@ -645,8 +640,7 @@ static void map_slot_init( ...@@ -645,8 +640,7 @@ static void map_slot_init(
break; break;
} }
case UPB_TYPE_MESSAGE: { case UPB_TYPE_MESSAGE: {
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(value_msg);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(value_msg));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
MessageHeader* submsg; MessageHeader* submsg;
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
...@@ -802,8 +796,7 @@ static bool endmap_handler(void* closure, const void* hd, upb_status* s) { ...@@ -802,8 +796,7 @@ static bool endmap_handler(void* closure, const void* hd, upb_status* s) {
// pass the handlerdata down to the sub-message handler setup. // pass the handlerdata down to the sub-message handler setup.
static map_handlerdata_t* new_map_handlerdata( static map_handlerdata_t* new_map_handlerdata(
const upb_fielddef* field, const upb_fielddef* field,
const upb_msgdef* mapentry_def, const upb_msgdef* mapentry_def) {
Descriptor* desc) {
const upb_fielddef* key_field; const upb_fielddef* key_field;
const upb_fielddef* value_field; const upb_fielddef* value_field;
// TODO(teboring): Use emalloc and efree. // TODO(teboring): Use emalloc and efree.
...@@ -944,8 +937,7 @@ static void* oneofsubmsg_handler(void* closure, const void* hd) { ...@@ -944,8 +937,7 @@ static void* oneofsubmsg_handler(void* closure, const void* hd) {
const oneof_handlerdata_t *oneofdata = hd; const oneof_handlerdata_t *oneofdata = hd;
uint32_t oldcase = DEREF(message_data(msg), oneofdata->case_ofs, uint32_t); uint32_t oldcase = DEREF(message_data(msg), oneofdata->case_ofs, uint32_t);
TSRMLS_FETCH(); TSRMLS_FETCH();
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(oneofdata->md);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)oneofdata->md));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
zval* submsg_php; zval* submsg_php;
MessageHeader* submsg; MessageHeader* submsg;
...@@ -983,8 +975,7 @@ static void* wrapper_submsg_handler(void* closure, const void* hd) { ...@@ -983,8 +975,7 @@ static void* wrapper_submsg_handler(void* closure, const void* hd) {
MessageHeader* msg = closure; MessageHeader* msg = closure;
const submsg_handlerdata_t* submsgdata = hd; const submsg_handlerdata_t* submsgdata = hd;
TSRMLS_FETCH(); TSRMLS_FETCH();
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(submsgdata->md);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
zval* submsg_php; zval* submsg_php;
MessageHeader* submsg; MessageHeader* submsg;
...@@ -1015,8 +1006,7 @@ static void* wrapper_oneofsubmsg_handler(void* closure, const void* hd) { ...@@ -1015,8 +1006,7 @@ static void* wrapper_oneofsubmsg_handler(void* closure, const void* hd) {
const oneof_handlerdata_t *oneofdata = hd; const oneof_handlerdata_t *oneofdata = hd;
uint32_t oldcase = DEREF(message_data(msg), oneofdata->case_ofs, uint32_t); uint32_t oldcase = DEREF(message_data(msg), oneofdata->case_ofs, uint32_t);
TSRMLS_FETCH(); TSRMLS_FETCH();
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(oneofdata->md);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)oneofdata->md));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
wrapperfields_parseframe_t* frame = wrapperfields_parseframe_t* frame =
(wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t)); (wrapperfields_parseframe_t*)malloc(sizeof(wrapperfields_parseframe_t));
...@@ -1164,10 +1154,9 @@ static void add_handlers_for_singular_field(upb_handlers *h, ...@@ -1164,10 +1154,9 @@ static void add_handlers_for_singular_field(upb_handlers *h,
// Adds handlers to a map field. // Adds handlers to a map field.
static void add_handlers_for_mapfield(upb_handlers* h, static void add_handlers_for_mapfield(upb_handlers* h,
const upb_fielddef* fielddef, const upb_fielddef* fielddef,
size_t offset, size_t offset) {
Descriptor* desc) {
const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef); const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
map_handlerdata_t* hd = new_map_handlerdata(fielddef, map_msgdef, desc); map_handlerdata_t* hd = new_map_handlerdata(fielddef, map_msgdef);
upb_handlerattr attr = UPB_HANDLERATTR_INIT; upb_handlerattr attr = UPB_HANDLERATTR_INIT;
upb_handlers_addcleanup(h, hd, free); upb_handlers_addcleanup(h, hd, free);
...@@ -1176,11 +1165,11 @@ static void add_handlers_for_mapfield(upb_handlers* h, ...@@ -1176,11 +1165,11 @@ static void add_handlers_for_mapfield(upb_handlers* h,
} }
// Adds handlers to a map-entry msgdef. // Adds handlers to a map-entry msgdef.
static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h, static void add_handlers_for_mapentry(
Descriptor* desc) { const upb_msgdef* msgdef, upb_handlers* h) {
const upb_fielddef* key_field = map_entry_key(msgdef); const upb_fielddef* key_field = map_entry_key(msgdef);
const upb_fielddef* value_field = map_entry_value(msgdef); const upb_fielddef* value_field = map_entry_value(msgdef);
map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc); map_handlerdata_t* hd = new_map_handlerdata(0, msgdef);
upb_handlerattr attr = UPB_HANDLERATTR_INIT; upb_handlerattr attr = UPB_HANDLERATTR_INIT;
upb_handlers_addcleanup(h, hd, free); upb_handlers_addcleanup(h, hd, free);
...@@ -1294,11 +1283,11 @@ static bool strwrapper_end_handler(void *closure, const void *hd) { ...@@ -1294,11 +1283,11 @@ static bool strwrapper_end_handler(void *closure, const void *hd) {
static void add_handlers_for_wrapper(const upb_msgdef* msgdef, static void add_handlers_for_wrapper(const upb_msgdef* msgdef,
upb_handlers* h) { upb_handlers* h) {
const upb_fielddef* f = upb_msgdef_itof(msgdef, 1); const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
Descriptor* desc; DescriptorInternal* desc;
size_t offset; size_t offset;
TSRMLS_FETCH(); TSRMLS_FETCH();
desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)msgdef)); desc = get_msgdef_desc(msgdef);
offset = desc->layout->fields[upb_fielddef_index(f)].offset; offset = desc->layout->fields[upb_fielddef_index(f)].offset;
switch (upb_msgdef_wellknowntype(msgdef)) { switch (upb_msgdef_wellknowntype(msgdef)) {
...@@ -1357,14 +1346,13 @@ static bool add_unknown_handler(void* closure, const void* hd, const char* buf, ...@@ -1357,14 +1346,13 @@ static bool add_unknown_handler(void* closure, const void* hd, const char* buf,
void add_handlers_for_message(const void* closure, upb_handlers* h) { void add_handlers_for_message(const void* closure, upb_handlers* h) {
const upb_msgdef* msgdef = upb_handlers_msgdef(h); const upb_msgdef* msgdef = upb_handlers_msgdef(h);
TSRMLS_FETCH(); TSRMLS_FETCH();
Descriptor* desc = DescriptorInternal* desc = get_msgdef_desc(msgdef);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)msgdef));
upb_msg_field_iter i; upb_msg_field_iter i;
// 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
// bail out of the normal (user-defined) message type handling. // bail out of the normal (user-defined) message type handling.
if (upb_msgdef_mapentry(msgdef)) { if (upb_msgdef_mapentry(msgdef)) {
add_handlers_for_mapentry(msgdef, h, desc); add_handlers_for_mapentry(msgdef, h);
return; return;
} }
...@@ -1402,7 +1390,7 @@ void add_handlers_for_message(const void* closure, upb_handlers* h) { ...@@ -1402,7 +1390,7 @@ void add_handlers_for_message(const void* closure, upb_handlers* h) {
add_handlers_for_oneof_field(h, desc->msgdef, f, offset, add_handlers_for_oneof_field(h, desc->msgdef, f, offset,
oneof_case_offset, property_cache_index); oneof_case_offset, property_cache_index);
} else if (is_map_field(f)) { } else if (is_map_field(f)) {
add_handlers_for_mapfield(h, f, offset, desc); add_handlers_for_mapfield(h, f, offset);
} else if (upb_fielddef_isseq(f)) { } else if (upb_fielddef_isseq(f)) {
add_handlers_for_repeated_field(h, f, offset); add_handlers_for_repeated_field(h, f, offset);
} else { } else {
...@@ -1413,15 +1401,15 @@ void add_handlers_for_message(const void* closure, upb_handlers* h) { ...@@ -1413,15 +1401,15 @@ void add_handlers_for_message(const void* closure, upb_handlers* h) {
// Constructs the handlers for filling a message's data into an in-memory // Constructs the handlers for filling a message's data into an in-memory
// object. // object.
const upb_handlers* get_fill_handlers(Descriptor* desc) { const upb_handlers* get_fill_handlers(DescriptorInternal* desc) {
return upb_handlercache_get(desc->pool->fill_handler_cache, desc->msgdef); return upb_handlercache_get(desc->pool->fill_handler_cache, desc->msgdef);
} }
static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) { static const upb_pbdecodermethod *msgdef_decodermethod(DescriptorInternal* desc) {
return upb_pbcodecache_get(desc->pool->fill_method_cache, desc->msgdef); return upb_pbcodecache_get(desc->pool->fill_method_cache, desc->msgdef);
} }
static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { static const upb_json_parsermethod *msgdef_jsonparsermethod(DescriptorInternal* desc) {
return upb_json_codecache_get(desc->pool->json_fill_method_cache, desc->msgdef); return upb_json_codecache_get(desc->pool->json_fill_method_cache, desc->msgdef);
} }
...@@ -1429,21 +1417,21 @@ static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { ...@@ -1429,21 +1417,21 @@ static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
// Serializing. // Serializing.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static void putmsg(zval* msg, const Descriptor* desc, upb_sink sink, static void putmsg(zval* msg, const DescriptorInternal* desc, upb_sink sink,
int depth, bool is_json TSRMLS_DC); int depth, bool is_json TSRMLS_DC);
static void putrawmsg(MessageHeader* msg, const Descriptor* desc, static void putrawmsg(MessageHeader* msg, const DescriptorInternal* desc,
upb_sink sink, int depth, bool is_json, upb_sink sink, int depth, bool is_json,
bool open_msg TSRMLS_DC); bool open_msg TSRMLS_DC);
static void putwrappervalue( static void putwrappervalue(
zval* value, const upb_fielddef* f, zval* value, const upb_fielddef* f,
upb_sink sink, int depth, bool is_json TSRMLS_DC); upb_sink sink, int depth, bool is_json TSRMLS_DC);
static void putjsonany(MessageHeader* msg, const Descriptor* desc, static void putjsonany(MessageHeader* msg, const DescriptorInternal* desc,
upb_sink sink, int depth TSRMLS_DC); upb_sink sink, int depth TSRMLS_DC);
static void putjsonlistvalue( static void putjsonlistvalue(
MessageHeader* msg, const Descriptor* desc, MessageHeader* msg, const DescriptorInternal* desc,
upb_sink sink, int depth TSRMLS_DC); upb_sink sink, int depth TSRMLS_DC);
static void putjsonstruct( static void putjsonstruct(
MessageHeader* msg, const Descriptor* desc, MessageHeader* msg, const DescriptorInternal* desc,
upb_sink sink, int depth TSRMLS_DC); upb_sink sink, int depth TSRMLS_DC);
static void putstr(zval* str, const upb_fielddef* f, upb_sink sink, static void putstr(zval* str, const upb_fielddef* f, upb_sink sink,
...@@ -1590,16 +1578,16 @@ static void putmap(zval* map, const upb_fielddef* f, upb_sink sink, ...@@ -1590,16 +1578,16 @@ static void putmap(zval* map, const upb_fielddef* f, upb_sink sink,
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
} }
static void putmsg(zval* msg_php, const Descriptor* desc, upb_sink sink, static void putmsg(zval* msg_php, const DescriptorInternal* desc, upb_sink sink,
int depth, bool is_json TSRMLS_DC) { int depth, bool is_json TSRMLS_DC) {
MessageHeader* msg = UNBOX(MessageHeader, msg_php); MessageHeader* msg = UNBOX(MessageHeader, msg_php);
putrawmsg(msg, desc, sink, depth, is_json, true TSRMLS_CC); putrawmsg(msg, desc, sink, depth, is_json, true TSRMLS_CC);
} }
static const upb_handlers* msgdef_json_serialize_handlers( static const upb_handlers* msgdef_json_serialize_handlers(
Descriptor* desc, bool preserve_proto_fieldnames); DescriptorInternal* desc, bool preserve_proto_fieldnames);
static void putjsonany(MessageHeader* msg, const Descriptor* desc, static void putjsonany(MessageHeader* msg, const DescriptorInternal* desc,
upb_sink sink, int depth TSRMLS_DC) { upb_sink sink, int depth TSRMLS_DC) {
upb_status status; upb_status status;
const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE); const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
...@@ -1646,8 +1634,7 @@ static void putjsonany(MessageHeader* msg, const Descriptor* desc, ...@@ -1646,8 +1634,7 @@ static void putjsonany(MessageHeader* msg, const Descriptor* desc,
value_len = Z_STRLEN_P(value_php_str); value_len = Z_STRLEN_P(value_php_str);
if (value_len > 0) { if (value_len > 0) {
Descriptor* payload_desc = DescriptorInternal* payload_desc = get_msgdef_desc(payload_type);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)payload_type));
zend_class_entry* payload_klass = payload_desc->klass; zend_class_entry* payload_klass = payload_desc->klass;
zval val; zval val;
upb_sink subsink; upb_sink subsink;
...@@ -1682,7 +1669,7 @@ static void putjsonany(MessageHeader* msg, const Descriptor* desc, ...@@ -1682,7 +1669,7 @@ static void putjsonany(MessageHeader* msg, const Descriptor* desc,
} }
static void putjsonlistvalue( static void putjsonlistvalue(
MessageHeader* msg, const Descriptor* desc, MessageHeader* msg, const DescriptorInternal* desc,
upb_sink sink, int depth TSRMLS_DC) { upb_sink sink, int depth TSRMLS_DC) {
upb_status status; upb_status status;
upb_sink subsink; upb_sink subsink;
...@@ -1716,7 +1703,7 @@ static void putjsonlistvalue( ...@@ -1716,7 +1703,7 @@ static void putjsonlistvalue(
} }
static void putjsonstruct( static void putjsonstruct(
MessageHeader* msg, const Descriptor* desc, MessageHeader* msg, const DescriptorInternal* desc,
upb_sink sink, int depth TSRMLS_DC) { upb_sink sink, int depth TSRMLS_DC) {
upb_status status; upb_status status;
upb_sink subsink; upb_sink subsink;
...@@ -1747,7 +1734,7 @@ static void putjsonstruct( ...@@ -1747,7 +1734,7 @@ static void putjsonstruct(
upb_sink_endmsg(sink, &status); upb_sink_endmsg(sink, &status);
} }
static void putrawmsg(MessageHeader* msg, const Descriptor* desc, static void putrawmsg(MessageHeader* msg, const DescriptorInternal* desc,
upb_sink sink, int depth, bool is_json, upb_sink sink, int depth, bool is_json,
bool open_msg TSRMLS_DC) { bool open_msg TSRMLS_DC) {
upb_msg_field_iter i; upb_msg_field_iter i;
...@@ -1976,8 +1963,8 @@ static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f, ...@@ -1976,8 +1963,8 @@ static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f,
upb_sink sink, int depth, bool is_json TSRMLS_DC) { upb_sink sink, int depth, bool is_json TSRMLS_DC) {
upb_sink subsink; upb_sink subsink;
Descriptor* subdesc = const upb_msgdef* m = upb_fielddef_msgsubdef(f);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(upb_fielddef_msgsubdef(f))); DescriptorInternal* subdesc = get_msgdef_desc(m);
upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink); upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
putrawmsg(submsg, subdesc, subsink, depth + 1, is_json, true TSRMLS_CC); putrawmsg(submsg, subdesc, subsink, depth + 1, is_json, true TSRMLS_CC);
...@@ -2051,13 +2038,13 @@ static void putarray(zval* array, const upb_fielddef* f, upb_sink sink, ...@@ -2051,13 +2038,13 @@ static void putarray(zval* array, const upb_fielddef* f, upb_sink sink,
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
} }
static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { static const upb_handlers* msgdef_pb_serialize_handlers(DescriptorInternal* desc) {
return upb_handlercache_get(desc->pool->pb_serialize_handler_cache, return upb_handlercache_get(desc->pool->pb_serialize_handler_cache,
desc->msgdef); desc->msgdef);
} }
static const upb_handlers* msgdef_json_serialize_handlers( static const upb_handlers* msgdef_json_serialize_handlers(
Descriptor* desc, bool preserve_proto_fieldnames) { DescriptorInternal* desc, bool preserve_proto_fieldnames) {
if (preserve_proto_fieldnames) { if (preserve_proto_fieldnames) {
return upb_handlercache_get( return upb_handlercache_get(
desc->pool->json_serialize_handler_preserve_cache, desc->msgdef); desc->pool->json_serialize_handler_preserve_cache, desc->msgdef);
...@@ -2072,8 +2059,7 @@ static const upb_handlers* msgdef_json_serialize_handlers( ...@@ -2072,8 +2059,7 @@ static const upb_handlers* msgdef_json_serialize_handlers(
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void serialize_to_string(zval* val, zval* return_value TSRMLS_DC) { void serialize_to_string(zval* val, zval* return_value TSRMLS_DC) {
Descriptor* desc = DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(val));
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val)));
stringsink sink; stringsink sink;
stringsink_init(&sink); stringsink_init(&sink);
...@@ -2100,7 +2086,7 @@ PHP_METHOD(Message, serializeToString) { ...@@ -2100,7 +2086,7 @@ PHP_METHOD(Message, serializeToString) {
serialize_to_string(getThis(), return_value TSRMLS_CC); serialize_to_string(getThis(), return_value TSRMLS_CC);
} }
void merge_from_string(const char* data, int data_len, Descriptor* desc, void merge_from_string(const char* data, int data_len, DescriptorInternal* desc,
MessageHeader* msg) { MessageHeader* msg) {
const upb_pbdecodermethod* method = msgdef_decodermethod(desc); const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
const upb_handlers* h = upb_pbdecodermethod_desthandlers(method); const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
...@@ -2133,8 +2119,7 @@ void merge_from_string(const char* data, int data_len, Descriptor* desc, ...@@ -2133,8 +2119,7 @@ void merge_from_string(const char* data, int data_len, Descriptor* desc,
} }
PHP_METHOD(Message, mergeFromString) { PHP_METHOD(Message, mergeFromString) {
Descriptor* desc = DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(getThis()));
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
MessageHeader* msg = UNBOX(MessageHeader, getThis()); MessageHeader* msg = UNBOX(MessageHeader, getThis());
char *data = NULL; char *data = NULL;
...@@ -2149,8 +2134,7 @@ PHP_METHOD(Message, mergeFromString) { ...@@ -2149,8 +2134,7 @@ PHP_METHOD(Message, mergeFromString) {
} }
PHP_METHOD(Message, serializeToJsonString) { PHP_METHOD(Message, serializeToJsonString) {
Descriptor* desc = DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(getThis()));
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
zend_bool preserve_proto_fieldnames = false; zend_bool preserve_proto_fieldnames = false;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
...@@ -2180,8 +2164,7 @@ PHP_METHOD(Message, serializeToJsonString) { ...@@ -2180,8 +2164,7 @@ PHP_METHOD(Message, serializeToJsonString) {
} }
PHP_METHOD(Message, mergeFromJsonString) { PHP_METHOD(Message, mergeFromJsonString) {
Descriptor* desc = DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(getThis()));
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
MessageHeader* msg = UNBOX(MessageHeader, getThis()); MessageHeader* msg = UNBOX(MessageHeader, getThis());
char *data = NULL; char *data = NULL;
...@@ -2244,7 +2227,7 @@ static void discard_unknown_fields(MessageHeader* msg) { ...@@ -2244,7 +2227,7 @@ static void discard_unknown_fields(MessageHeader* msg) {
} }
// Recursively discard unknown fields of submessages. // Recursively discard unknown fields of submessages.
Descriptor* desc = msg->descriptor; DescriptorInternal* desc = msg->descriptor;
TSRMLS_FETCH(); TSRMLS_FETCH();
for (upb_msg_field_begin(&it, desc->msgdef); for (upb_msg_field_begin(&it, desc->msgdef);
!upb_msg_field_done(&it); !upb_msg_field_done(&it);
......
...@@ -255,7 +255,7 @@ void* message_data(MessageHeader* msg) { ...@@ -255,7 +255,7 @@ void* message_data(MessageHeader* msg) {
void custom_data_init(const zend_class_entry* ce, void custom_data_init(const zend_class_entry* ce,
MessageHeader* intern PHP_PROTO_TSRMLS_DC) { MessageHeader* intern PHP_PROTO_TSRMLS_DC) {
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(ce)); DescriptorInternal* desc = get_ce_desc(ce);
intern->data = ALLOC_N(uint8_t, desc->layout->size); intern->data = ALLOC_N(uint8_t, desc->layout->size);
// We wrap first so that everything in the message object is GC-rooted in // We wrap first so that everything in the message object is GC-rooted in
// case a collection happens during object creation in layout_init(). // case a collection happens during object creation in layout_init().
...@@ -279,15 +279,15 @@ void build_class_from_descriptor( ...@@ -279,15 +279,15 @@ void build_class_from_descriptor(
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, php_descriptor); Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, php_descriptor);
// Map entries don't have existing php class. // Map entries don't have existing php class.
if (upb_msgdef_mapentry(desc->msgdef)) { if (upb_msgdef_mapentry(desc->intern->msgdef)) {
return; return;
} }
zend_class_entry* registered_ce = desc->klass; zend_class_entry* registered_ce = desc->intern->klass;
if (desc->layout == NULL) { if (desc->intern->layout == NULL) {
MessageLayout* layout = create_layout(desc->msgdef); MessageLayout* layout = create_layout(desc->intern->msgdef);
desc->layout = layout; desc->intern->layout = layout;
} }
registered_ce->create_object = message_create; registered_ce->create_object = message_create;
...@@ -395,8 +395,7 @@ void Message_construct(zval* msg, zval* array_wrapper) { ...@@ -395,8 +395,7 @@ void Message_construct(zval* msg, zval* array_wrapper) {
is_wrapper = is_wrapper_msg(submsgdef); is_wrapper = is_wrapper_msg(submsgdef);
if (is_wrapper) { if (is_wrapper) {
PHP_PROTO_HASHTABLE_VALUE subdesc_php = get_def_obj(submsgdef); DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
Descriptor* subdesc = UNBOX_HASHTABLE_VALUE(Descriptor, subdesc_php);
subklass = subdesc->klass; subklass = subdesc->klass;
} }
} }
...@@ -435,8 +434,7 @@ void Message_construct(zval* msg, zval* array_wrapper) { ...@@ -435,8 +434,7 @@ void Message_construct(zval* msg, zval* array_wrapper) {
is_wrapper = is_wrapper_msg(submsgdef); is_wrapper = is_wrapper_msg(submsgdef);
if (is_wrapper) { if (is_wrapper) {
PHP_PROTO_HASHTABLE_VALUE subdesc_php = get_def_obj(submsgdef); DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
Descriptor* subdesc = UNBOX_HASHTABLE_VALUE(Descriptor, subdesc_php);
subklass = subdesc->klass; subklass = subdesc->klass;
} }
} }
...@@ -459,8 +457,7 @@ void Message_construct(zval* msg, zval* array_wrapper) { ...@@ -459,8 +457,7 @@ void Message_construct(zval* msg, zval* array_wrapper) {
} }
} else if (upb_fielddef_issubmsg(field)) { } else if (upb_fielddef_issubmsg(field)) {
const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field); const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj(submsgdef); DescriptorInternal* desc = get_msgdef_desc(submsgdef);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
CACHED_VALUE* cached = NULL; CACHED_VALUE* cached = NULL;
if (upb_fielddef_containingoneof(field)) { if (upb_fielddef_containingoneof(field)) {
...@@ -530,7 +527,7 @@ PHP_METHOD(Message, __construct) { ...@@ -530,7 +527,7 @@ PHP_METHOD(Message, __construct) {
PHP_METHOD(Message, clear) { PHP_METHOD(Message, clear) {
MessageHeader* msg = UNBOX(MessageHeader, getThis()); MessageHeader* msg = UNBOX(MessageHeader, getThis());
Descriptor* desc = msg->descriptor; DescriptorInternal* desc = msg->descriptor;
zend_class_entry* ce = desc->klass; zend_class_entry* ce = desc->klass;
zend_object_std_dtor(&msg->std TSRMLS_CC); zend_object_std_dtor(&msg->std TSRMLS_CC);
...@@ -1536,14 +1533,13 @@ PHP_METHOD(Any, unpack) { ...@@ -1536,14 +1533,13 @@ PHP_METHOD(Any, unpack) {
} }
const char* fully_qualified_name = type_url + url_prefix_len; const char* fully_qualified_name = type_url + url_prefix_len;
PHP_PROTO_HASHTABLE_VALUE desc_php = get_proto_obj(fully_qualified_name); DescriptorInternal* desc = get_proto_desc(fully_qualified_name);
if (desc_php == NULL) { if (desc == NULL) {
zend_throw_exception( zend_throw_exception(
NULL, "Specified message in any hasn't been added to descriptor pool", NULL, "Specified message in any hasn't been added to descriptor pool",
0 TSRMLS_CC); 0 TSRMLS_CC);
return; return;
} }
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
zend_class_entry* klass = desc->klass; zend_class_entry* klass = desc->klass;
ZVAL_OBJ(return_value, klass->create_object(klass TSRMLS_CC)); ZVAL_OBJ(return_value, klass->create_object(klass TSRMLS_CC));
MessageHeader* msg = UNBOX(MessageHeader, return_value); MessageHeader* msg = UNBOX(MessageHeader, return_value);
...@@ -1589,8 +1585,7 @@ PHP_METHOD(Any, pack) { ...@@ -1589,8 +1585,7 @@ PHP_METHOD(Any, pack) {
PHP_PROTO_FAKE_SCOPE_END; PHP_PROTO_FAKE_SCOPE_END;
// Set type url. // Set type url.
Descriptor* desc = DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(val));
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val)));
const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef); const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
size_t type_url_len = size_t type_url_len =
strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1; strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
...@@ -1617,14 +1612,12 @@ PHP_METHOD(Any, is) { ...@@ -1617,14 +1612,12 @@ PHP_METHOD(Any, is) {
return; return;
} }
PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(klass); DescriptorInternal* desc = get_ce_desc(klass);
if (desc_php == NULL) { if (desc == NULL) {
RETURN_BOOL(false); RETURN_BOOL(false);
} }
// Create corresponded type url. // Create corresponded type url.
Descriptor* desc =
UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(klass));
const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef); const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
size_t type_url_len = size_t type_url_len =
strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1; strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <zend_hash.h> #include <zend_hash.h>
ZEND_DECLARE_MODULE_GLOBALS(protobuf)
static PHP_GINIT_FUNCTION(protobuf); static PHP_GINIT_FUNCTION(protobuf);
static PHP_GSHUTDOWN_FUNCTION(protobuf); static PHP_GSHUTDOWN_FUNCTION(protobuf);
static PHP_RINIT_FUNCTION(protobuf); static PHP_RINIT_FUNCTION(protobuf);
...@@ -43,13 +42,19 @@ static PHP_MSHUTDOWN_FUNCTION(protobuf); ...@@ -43,13 +42,19 @@ static PHP_MSHUTDOWN_FUNCTION(protobuf);
// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
// instances. // instances.
static HashTable* upb_def_to_php_obj_map; static HashTable* upb_def_to_php_obj_map;
static upb_inttable upb_def_to_desc_map_persistent;
static upb_inttable upb_def_to_enumdesc_map_persistent;
// Global map from message/enum's php class entry to corresponding wrapper // Global map from message/enum's php class entry to corresponding wrapper
// Descriptor/EnumDescriptor instances. // Descriptor/EnumDescriptor instances.
static HashTable* ce_to_php_obj_map; static HashTable* ce_to_php_obj_map;
static upb_inttable ce_to_desc_map_persistent;
static upb_inttable ce_to_enumdesc_map_persistent;
// Global map from message/enum's proto fully-qualified name to corresponding // Global map from message/enum's proto fully-qualified name to corresponding
// wrapper Descriptor/EnumDescriptor instances. // wrapper Descriptor/EnumDescriptor instances.
static HashTable* proto_to_php_obj_map; static upb_strtable proto_to_desc_map_persistent;
static HashTable* reserved_names; static upb_strtable proto_to_enumdesc_map_persistent;
upb_strtable reserved_names;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Global maps. // Global maps.
...@@ -78,12 +83,6 @@ static bool exist_in_table(const HashTable* t, const void* def) { ...@@ -78,12 +83,6 @@ static bool exist_in_table(const HashTable* t, const void* def) {
(void**)&value) == SUCCESS); (void**)&value) == SUCCESS);
} }
static void add_to_list(HashTable* t, void* value) {
zval* pDest = NULL;
php_proto_zend_hash_next_index_insert_mem(t, &value, sizeof(void*),
(void**)&pDest);
}
static void add_to_strtable(HashTable* t, const char* key, int key_size, static void add_to_strtable(HashTable* t, const char* key, int key_size,
void* value) { void* value) {
zval* pDest = NULL; zval* pDest = NULL;
...@@ -113,6 +112,40 @@ PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def) { ...@@ -113,6 +112,40 @@ PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def) {
return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(upb_def_to_php_obj_map, def); return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(upb_def_to_php_obj_map, def);
} }
void add_msgdef_desc(const upb_msgdef* m, DescriptorInternal* desc) {
upb_inttable_insertptr(&upb_def_to_desc_map_persistent,
m, upb_value_ptr(desc));
}
DescriptorInternal* get_msgdef_desc(const upb_msgdef* m) {
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_inttable_lookupptr(&upb_def_to_desc_map_persistent, m, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
}
void add_enumdef_enumdesc(const upb_enumdef* e, EnumDescriptorInternal* desc) {
upb_inttable_insertptr(&upb_def_to_enumdesc_map_persistent,
e, upb_value_ptr(desc));
}
EnumDescriptorInternal* get_enumdef_enumdesc(const upb_enumdef* e) {
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_inttable_lookupptr(&upb_def_to_enumdesc_map_persistent, e, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
}
void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value) { void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value) {
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
Z_ADDREF_P(value); Z_ADDREF_P(value);
...@@ -126,22 +159,77 @@ PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce) { ...@@ -126,22 +159,77 @@ PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce) {
return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(ce_to_php_obj_map, ce); return (PHP_PROTO_HASHTABLE_VALUE)get_from_table(ce_to_php_obj_map, ce);
} }
void add_ce_desc(const zend_class_entry* ce, DescriptorInternal* desc) {
upb_inttable_insertptr(&ce_to_desc_map_persistent,
ce, upb_value_ptr(desc));
}
DescriptorInternal* get_ce_desc(const zend_class_entry* ce) {
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_inttable_lookupptr(&ce_to_desc_map_persistent, ce, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
}
void add_ce_enumdesc(const zend_class_entry* ce, EnumDescriptorInternal* desc) {
upb_inttable_insertptr(&ce_to_enumdesc_map_persistent,
ce, upb_value_ptr(desc));
}
EnumDescriptorInternal* get_ce_enumdesc(const zend_class_entry* ce) {
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_inttable_lookupptr(&ce_to_enumdesc_map_persistent, ce, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
}
bool class_added(const void* ce) { bool class_added(const void* ce) {
return exist_in_table(ce_to_php_obj_map, ce); return exist_in_table(ce_to_php_obj_map, ce);
} }
void add_proto_obj(const char* proto, PHP_PROTO_HASHTABLE_VALUE value) { void add_proto_desc(const char* proto, DescriptorInternal* desc) {
#if PHP_MAJOR_VERSION < 7 upb_strtable_insert(&proto_to_desc_map_persistent, proto,
Z_ADDREF_P(value); upb_value_ptr(desc));
#else }
GC_ADDREF(value);
DescriptorInternal* get_proto_desc(const char* proto) {
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif #endif
add_to_strtable(proto_to_php_obj_map, proto, strlen(proto), value); if (!upb_strtable_lookup(&proto_to_desc_map_persistent, proto, &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
} }
PHP_PROTO_HASHTABLE_VALUE get_proto_obj(const char* proto) { void add_proto_enumdesc(const char* proto, EnumDescriptorInternal* desc) {
return (PHP_PROTO_HASHTABLE_VALUE)get_from_strtable(proto_to_php_obj_map, upb_strtable_insert2(&proto_to_enumdesc_map_persistent, proto,
proto, strlen(proto)); strlen(proto), upb_value_ptr(desc));
}
EnumDescriptorInternal* get_proto_enumdesc(const char* proto) {
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_PTR;
#endif
if (!upb_strtable_lookupptr(&proto_to_enumdesc_map_persistent,
proto, strlen(proto), &v)) {
return NULL;
} else {
return upb_value_getptr(v);
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -184,9 +272,11 @@ const char *const kReservedNames[] = { ...@@ -184,9 +272,11 @@ const char *const kReservedNames[] = {
const int kReservedNamesSize = 73; const int kReservedNamesSize = 73;
bool is_reserved_name(const char* name) { bool is_reserved_name(const char* name) {
void** value; upb_value v;
return (php_proto_zend_hash_find(reserved_names, name, strlen(name), #ifndef NDEBUG
(void**)&value) == SUCCESS); v.ctype = UPB_CTYPE_UINT64;
#endif
return upb_strtable_lookup2(&reserved_names, name, strlen(name), &v);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -241,30 +331,21 @@ static void php_proto_hashtable_descriptor_release(zval* value) { ...@@ -241,30 +331,21 @@ static void php_proto_hashtable_descriptor_release(zval* value) {
} }
efree(ptr); efree(ptr);
} }
#endif
static PHP_RINIT_FUNCTION(protobuf) {
int i = 0;
ALLOC_HASHTABLE(upb_def_to_php_obj_map);
zend_hash_init(upb_def_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
ALLOC_HASHTABLE(ce_to_php_obj_map); static void test_release(void* value) {
zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0); void* ptr = value;
}
#endif
ALLOC_HASHTABLE(proto_to_php_obj_map); static initialize_persistent_descriptor_pool(TSRMLS_D) {
zend_hash_init(proto_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0); upb_inttable_init(&upb_def_to_desc_map_persistent, UPB_CTYPE_PTR);
upb_inttable_init(&upb_def_to_enumdesc_map_persistent, UPB_CTYPE_PTR);
upb_inttable_init(&ce_to_desc_map_persistent, UPB_CTYPE_PTR);
upb_inttable_init(&ce_to_enumdesc_map_persistent, UPB_CTYPE_PTR);
upb_strtable_init(&proto_to_desc_map_persistent, UPB_CTYPE_PTR);
upb_strtable_init(&proto_to_enumdesc_map_persistent, UPB_CTYPE_PTR);
ALLOC_HASHTABLE(reserved_names); internal_descriptor_pool_impl_init(&generated_pool_impl TSRMLS_CC);
zend_hash_init(reserved_names, 16, NULL, NULL, 0);
for (i = 0; i < kReservedNamesSize; i++) {
php_proto_zend_hash_update(reserved_names, kReservedNames[i],
strlen(kReservedNames[i]));
}
generated_pool = NULL;
generated_pool_php = NULL;
internal_generated_pool_php = NULL;
is_inited_file_any = false; is_inited_file_any = false;
is_inited_file_api = false; is_inited_file_api = false;
...@@ -276,10 +357,72 @@ static PHP_RINIT_FUNCTION(protobuf) { ...@@ -276,10 +357,72 @@ static PHP_RINIT_FUNCTION(protobuf) {
is_inited_file_timestamp = false; is_inited_file_timestamp = false;
is_inited_file_type = false; is_inited_file_type = false;
is_inited_file_wrappers = false; is_inited_file_wrappers = false;
}
static PHP_RINIT_FUNCTION(protobuf) {
ALLOC_HASHTABLE(upb_def_to_php_obj_map);
zend_hash_init(upb_def_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
ALLOC_HASHTABLE(ce_to_php_obj_map);
zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
generated_pool = NULL;
generated_pool_php = NULL;
internal_generated_pool_php = NULL;
if (!PROTOBUF_G(keep_descriptor_pool_after_request)) {
initialize_persistent_descriptor_pool(TSRMLS_C);
}
return 0; return 0;
} }
static void cleanup_desc_table(upb_inttable* t) {
upb_inttable_iter i;
upb_value v;
DescriptorInternal* desc;
for(upb_inttable_begin(&i, t);
!upb_inttable_done(&i);
upb_inttable_next(&i)) {
v = upb_inttable_iter_value(&i);
desc = upb_value_getptr(v);
if (desc->layout) {
free_layout(desc->layout);
}
SYS_FREE(desc);
}
}
static void cleanup_enumdesc_table(upb_inttable* t) {
upb_inttable_iter i;
upb_value v;
EnumDescriptorInternal* desc;
for(upb_inttable_begin(&i, t);
!upb_inttable_done(&i);
upb_inttable_next(&i)) {
v = upb_inttable_iter_value(&i);
desc = upb_value_getptr(v);
SYS_FREE(desc);
}
}
static cleanup_persistent_descriptor_pool(TSRMLS_D) {
// Clean up
// Only needs to clean one map out of three (def=>desc, ce=>desc, proto=>desc)
cleanup_desc_table(&upb_def_to_desc_map_persistent);
cleanup_enumdesc_table(&upb_def_to_enumdesc_map_persistent);
internal_descriptor_pool_impl_destroy(&generated_pool_impl TSRMLS_CC);
upb_inttable_uninit(&upb_def_to_desc_map_persistent);
upb_inttable_uninit(&upb_def_to_enumdesc_map_persistent);
upb_inttable_uninit(&ce_to_desc_map_persistent);
upb_inttable_uninit(&ce_to_enumdesc_map_persistent);
upb_strtable_uninit(&proto_to_desc_map_persistent);
upb_strtable_uninit(&proto_to_enumdesc_map_persistent);
}
static PHP_RSHUTDOWN_FUNCTION(protobuf) { static PHP_RSHUTDOWN_FUNCTION(protobuf) {
zend_hash_destroy(upb_def_to_php_obj_map); zend_hash_destroy(upb_def_to_php_obj_map);
FREE_HASHTABLE(upb_def_to_php_obj_map); FREE_HASHTABLE(upb_def_to_php_obj_map);
...@@ -287,12 +430,6 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) { ...@@ -287,12 +430,6 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) {
zend_hash_destroy(ce_to_php_obj_map); zend_hash_destroy(ce_to_php_obj_map);
FREE_HASHTABLE(ce_to_php_obj_map); FREE_HASHTABLE(ce_to_php_obj_map);
zend_hash_destroy(proto_to_php_obj_map);
FREE_HASHTABLE(proto_to_php_obj_map);
zend_hash_destroy(reserved_names);
FREE_HASHTABLE(reserved_names);
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
if (generated_pool_php != NULL) { if (generated_pool_php != NULL) {
zval_dtor(generated_pool_php); zval_dtor(generated_pool_php);
...@@ -315,21 +452,42 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) { ...@@ -315,21 +452,42 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) {
} }
#endif #endif
is_inited_file_any = true; if (!PROTOBUF_G(keep_descriptor_pool_after_request)) {
is_inited_file_api = true; cleanup_persistent_descriptor_pool(TSRMLS_C);
is_inited_file_duration = true; }
is_inited_file_field_mask = true;
is_inited_file_empty = true;
is_inited_file_source_context = true;
is_inited_file_struct = true;
is_inited_file_timestamp = true;
is_inited_file_type = true;
is_inited_file_wrappers = true;
return 0; return 0;
} }
static void reserved_names_init() {
size_t i;
upb_value v;
#ifndef NDEBUG
v.ctype = UPB_CTYPE_UINT64;
#endif
for (i = 0; i < kReservedNamesSize; i++) {
upb_strtable_insert2(&reserved_names, kReservedNames[i],
strlen(kReservedNames[i]), v);
}
}
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("protobuf.keep_descriptor_pool_after_request", "0",
PHP_INI_SYSTEM, OnUpdateBool,
keep_descriptor_pool_after_request, zend_protobuf_globals,
protobuf_globals)
PHP_INI_END()
static PHP_MINIT_FUNCTION(protobuf) { static PHP_MINIT_FUNCTION(protobuf) {
REGISTER_INI_ENTRIES();
upb_strtable_init(&reserved_names, UPB_CTYPE_UINT64);
reserved_names_init();
if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
initialize_persistent_descriptor_pool(TSRMLS_C);
}
descriptor_pool_init(TSRMLS_C); descriptor_pool_init(TSRMLS_C);
descriptor_init(TSRMLS_C); descriptor_init(TSRMLS_C);
enum_descriptor_init(TSRMLS_C); enum_descriptor_init(TSRMLS_C);
...@@ -391,6 +549,12 @@ static PHP_MINIT_FUNCTION(protobuf) { ...@@ -391,6 +549,12 @@ static PHP_MINIT_FUNCTION(protobuf) {
} }
static PHP_MSHUTDOWN_FUNCTION(protobuf) { static PHP_MSHUTDOWN_FUNCTION(protobuf) {
if (PROTOBUF_G(keep_descriptor_pool_after_request)) {
cleanup_persistent_descriptor_pool(TSRMLS_C);
}
upb_strtable_uninit(&reserved_names);
PEFREE(message_handlers); PEFREE(message_handlers);
PEFREE(repeated_field_handlers); PEFREE(repeated_field_handlers);
PEFREE(repeated_field_iter_handlers); PEFREE(repeated_field_iter_handlers);
......
...@@ -171,7 +171,7 @@ ...@@ -171,7 +171,7 @@
LOWWERNAME##_methods); \ LOWWERNAME##_methods); \
LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \ LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
LOWWERNAME##_type->create_object = LOWWERNAME##_create; \ LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \ LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers, 1); \
memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \ memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
sizeof(zend_object_handlers)); sizeof(zend_object_handlers));
#define PHP_PROTO_INIT_CLASS_END \ #define PHP_PROTO_INIT_CLASS_END \
...@@ -440,7 +440,7 @@ static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht, ...@@ -440,7 +440,7 @@ static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht,
LOWWERNAME##_methods); \ LOWWERNAME##_methods); \
LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \ LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
LOWWERNAME##_type->create_object = LOWWERNAME##_create; \ LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \ LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers, 1); \
memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \ memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
sizeof(zend_object_handlers)); \ sizeof(zend_object_handlers)); \
LOWWERNAME##_handlers->free_obj = LOWWERNAME##_free; \ LOWWERNAME##_handlers->free_obj = LOWWERNAME##_free; \
...@@ -590,11 +590,13 @@ struct Api; ...@@ -590,11 +590,13 @@ struct Api;
struct BoolValue; struct BoolValue;
struct BytesValue; struct BytesValue;
struct Descriptor; struct Descriptor;
struct DescriptorInternal;
struct DescriptorPool; struct DescriptorPool;
struct DoubleValue; struct DoubleValue;
struct Duration; struct Duration;
struct Enum; struct Enum;
struct EnumDescriptor; struct EnumDescriptor;
struct EnumDescriptorInternal;
struct EnumValue; struct EnumValue;
struct EnumValueDescriptor; struct EnumValueDescriptor;
struct Field; struct Field;
...@@ -607,6 +609,7 @@ struct GPBEmpty; ...@@ -607,6 +609,7 @@ struct GPBEmpty;
struct Int32Value; struct Int32Value;
struct Int64Value; struct Int64Value;
struct InternalDescriptorPool; struct InternalDescriptorPool;
struct InternalDescriptorPoolImpl;
struct ListValue; struct ListValue;
struct Map; struct Map;
struct MapIter; struct MapIter;
...@@ -635,10 +638,12 @@ typedef struct Api Api; ...@@ -635,10 +638,12 @@ typedef struct Api Api;
typedef struct BoolValue BoolValue; typedef struct BoolValue BoolValue;
typedef struct BytesValue BytesValue; typedef struct BytesValue BytesValue;
typedef struct Descriptor Descriptor; typedef struct Descriptor Descriptor;
typedef struct DescriptorInternal DescriptorInternal;
typedef struct DescriptorPool DescriptorPool; typedef struct DescriptorPool DescriptorPool;
typedef struct DoubleValue DoubleValue; typedef struct DoubleValue DoubleValue;
typedef struct Duration Duration; typedef struct Duration Duration;
typedef struct EnumDescriptor EnumDescriptor; typedef struct EnumDescriptor EnumDescriptor;
typedef struct EnumDescriptorInternal EnumDescriptorInternal;
typedef struct Enum Enum; typedef struct Enum Enum;
typedef struct EnumValueDescriptor EnumValueDescriptor; typedef struct EnumValueDescriptor EnumValueDescriptor;
typedef struct EnumValue EnumValue; typedef struct EnumValue EnumValue;
...@@ -652,6 +657,7 @@ typedef struct GPBEmpty GPBEmpty; ...@@ -652,6 +657,7 @@ typedef struct GPBEmpty GPBEmpty;
typedef struct Int32Value Int32Value; typedef struct Int32Value Int32Value;
typedef struct Int64Value Int64Value; typedef struct Int64Value Int64Value;
typedef struct InternalDescriptorPool InternalDescriptorPool; typedef struct InternalDescriptorPool InternalDescriptorPool;
typedef struct InternalDescriptorPoolImpl InternalDescriptorPoolImpl;
typedef struct ListValue ListValue; typedef struct ListValue ListValue;
typedef struct MapIter MapIter; typedef struct MapIter MapIter;
typedef struct Map Map; typedef struct Map Map;
...@@ -680,8 +686,17 @@ typedef struct Value Value; ...@@ -680,8 +686,17 @@ typedef struct Value Value;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
ZEND_BEGIN_MODULE_GLOBALS(protobuf) ZEND_BEGIN_MODULE_GLOBALS(protobuf)
zend_bool keep_descriptor_pool_after_request;
ZEND_END_MODULE_GLOBALS(protobuf) ZEND_END_MODULE_GLOBALS(protobuf)
ZEND_DECLARE_MODULE_GLOBALS(protobuf)
#ifdef ZTS
#define PROTOBUF_G(v) TSRMG(protobuf_globals_id, zend_protobuf_globals *, v)
#else
#define PROTOBUF_G(v) (protobuf_globals.v)
#endif
// Init module and PHP classes. // Init module and PHP classes.
void any_init(TSRMLS_D); void any_init(TSRMLS_D);
void api_init(TSRMLS_D); void api_init(TSRMLS_D);
...@@ -743,17 +758,27 @@ void gpb_metadata_wrappers_init(TSRMLS_D); ...@@ -743,17 +758,27 @@ void gpb_metadata_wrappers_init(TSRMLS_D);
// instances. // instances.
void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value); void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value);
PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def); PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def);
void add_msgdef_desc(const upb_msgdef* m, DescriptorInternal* desc);
DescriptorInternal* get_msgdef_desc(const upb_msgdef* m);
void add_enumdef_enumdesc(const upb_enumdef* e, EnumDescriptorInternal* desc);
EnumDescriptorInternal* get_enumdef_enumdesc(const upb_enumdef* e);
// Global map from PHP class entries to wrapper Descriptor/EnumDescriptor // Global map from PHP class entries to wrapper Descriptor/EnumDescriptor
// instances. // instances.
void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value); void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value);
PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce); PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce);
bool class_added(const void* ce); bool class_added(const void* ce);
void add_ce_desc(const zend_class_entry* ce, DescriptorInternal* desc);
DescriptorInternal* get_ce_desc(const zend_class_entry* ce);
void add_ce_enumdesc(const zend_class_entry* ce, EnumDescriptorInternal* desc);
EnumDescriptorInternal* get_ce_enumdesc(const zend_class_entry* ce);
// Global map from message/enum's proto fully-qualified name to corresponding // Global map from message/enum's proto fully-qualified name to corresponding
// wrapper Descriptor/EnumDescriptor instances. // wrapper Descriptor/EnumDescriptor instances.
void add_proto_obj(const char* proto, PHP_PROTO_HASHTABLE_VALUE value); void add_proto_desc(const char* proto, DescriptorInternal* desc);
PHP_PROTO_HASHTABLE_VALUE get_proto_obj(const char* proto); DescriptorInternal* get_proto_desc(const char* proto);
void add_proto_enumdesc(const char* proto, EnumDescriptorInternal* desc);
EnumDescriptorInternal* get_proto_enumdesc(const char* proto);
extern zend_class_entry* map_field_type; extern zend_class_entry* map_field_type;
extern zend_class_entry* repeated_field_type; extern zend_class_entry* repeated_field_type;
...@@ -763,14 +788,14 @@ extern zend_class_entry* repeated_field_type; ...@@ -763,14 +788,14 @@ extern zend_class_entry* repeated_field_type;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
PHP_PROTO_WRAP_OBJECT_START(DescriptorPool) PHP_PROTO_WRAP_OBJECT_START(DescriptorPool)
InternalDescriptorPool* intern; InternalDescriptorPoolImpl* intern;
PHP_PROTO_WRAP_OBJECT_END PHP_PROTO_WRAP_OBJECT_END
PHP_METHOD(DescriptorPool, getGeneratedPool); PHP_METHOD(DescriptorPool, getGeneratedPool);
PHP_METHOD(DescriptorPool, getDescriptorByClassName); PHP_METHOD(DescriptorPool, getDescriptorByClassName);
PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName); PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName);
PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool) struct InternalDescriptorPoolImpl {
upb_symtab* symtab; upb_symtab* symtab;
upb_handlercache* fill_handler_cache; upb_handlercache* fill_handler_cache;
upb_handlercache* pb_serialize_handler_cache; upb_handlercache* pb_serialize_handler_cache;
...@@ -778,13 +803,17 @@ PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool) ...@@ -778,13 +803,17 @@ PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool)
upb_handlercache* json_serialize_handler_preserve_cache; upb_handlercache* json_serialize_handler_preserve_cache;
upb_pbcodecache* fill_method_cache; upb_pbcodecache* fill_method_cache;
upb_json_codecache* json_fill_method_cache; upb_json_codecache* json_fill_method_cache;
};
PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool)
InternalDescriptorPoolImpl* intern;
PHP_PROTO_WRAP_OBJECT_END PHP_PROTO_WRAP_OBJECT_END
PHP_METHOD(InternalDescriptorPool, getGeneratedPool); PHP_METHOD(InternalDescriptorPool, getGeneratedPool);
PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile); PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile);
void internal_add_generated_file(const char* data, PHP_PROTO_SIZE data_len, void internal_add_generated_file(const char* data, PHP_PROTO_SIZE data_len,
InternalDescriptorPool* pool, InternalDescriptorPoolImpl* pool,
bool use_nested_submsg TSRMLS_DC); bool use_nested_submsg TSRMLS_DC);
void init_generated_pool_once(TSRMLS_D); void init_generated_pool_once(TSRMLS_D);
void add_handlers_for_message(const void* closure, upb_handlers* h); void add_handlers_for_message(const void* closure, upb_handlers* h);
...@@ -801,13 +830,24 @@ extern zend_object *internal_generated_pool_php; ...@@ -801,13 +830,24 @@ extern zend_object *internal_generated_pool_php;
void descriptor_pool_free(zend_object* object); void descriptor_pool_free(zend_object* object);
void internal_descriptor_pool_free(zend_object* object); void internal_descriptor_pool_free(zend_object* object);
#endif #endif
extern InternalDescriptorPool* generated_pool; // The actual generated pool extern InternalDescriptorPoolImpl* generated_pool;
// The actual generated pool
extern InternalDescriptorPoolImpl generated_pool_impl;
PHP_PROTO_WRAP_OBJECT_START(Descriptor) void internal_descriptor_pool_impl_init(
InternalDescriptorPool* pool; InternalDescriptorPoolImpl *pool TSRMLS_DC);
void internal_descriptor_pool_impl_destroy(
InternalDescriptorPoolImpl *pool TSRMLS_DC);
struct DescriptorInternal {
InternalDescriptorPoolImpl* pool;
const upb_msgdef* msgdef; const upb_msgdef* msgdef;
MessageLayout* layout; MessageLayout* layout;
zend_class_entry* klass; // begins as NULL zend_class_entry* klass; // begins as NULL
};
PHP_PROTO_WRAP_OBJECT_START(Descriptor)
DescriptorInternal* intern;
PHP_PROTO_WRAP_OBJECT_END PHP_PROTO_WRAP_OBJECT_END
PHP_METHOD(Descriptor, getClass); PHP_METHOD(Descriptor, getClass);
...@@ -835,9 +875,13 @@ PHP_METHOD(FieldDescriptor, getMessageType); ...@@ -835,9 +875,13 @@ PHP_METHOD(FieldDescriptor, getMessageType);
extern zend_class_entry* field_descriptor_type; extern zend_class_entry* field_descriptor_type;
PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor) struct EnumDescriptorInternal {
const upb_enumdef* enumdef; const upb_enumdef* enumdef;
zend_class_entry* klass; // begins as NULL zend_class_entry* klass; // begins as NULL
};
PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor)
EnumDescriptorInternal* intern;
PHP_PROTO_WRAP_OBJECT_END PHP_PROTO_WRAP_OBJECT_END
PHP_METHOD(EnumDescriptor, getValue); PHP_METHOD(EnumDescriptor, getValue);
...@@ -943,7 +987,8 @@ struct MessageLayout { ...@@ -943,7 +987,8 @@ struct MessageLayout {
PHP_PROTO_WRAP_OBJECT_START(MessageHeader) PHP_PROTO_WRAP_OBJECT_START(MessageHeader)
void* data; // Point to the real message data. void* data; // Point to the real message data.
// Place needs to be consistent with map_parse_frame_data_t. // Place needs to be consistent with map_parse_frame_data_t.
Descriptor* descriptor; // Kept alive by self.class.descriptor reference. DescriptorInternal* descriptor; // Kept alive by self.class.descriptor
// reference.
PHP_PROTO_WRAP_OBJECT_END PHP_PROTO_WRAP_OBJECT_END
MessageLayout* create_layout(const upb_msgdef* msgdef); MessageLayout* create_layout(const upb_msgdef* msgdef);
...@@ -985,7 +1030,7 @@ PHP_METHOD(Message, __construct); ...@@ -985,7 +1030,7 @@ PHP_METHOD(Message, __construct);
const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc, const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc,
const void *owner); const void *owner);
void serialize_to_string(zval* val, zval* return_value TSRMLS_DC); void serialize_to_string(zval* val, zval* return_value TSRMLS_DC);
void merge_from_string(const char* data, int data_len, Descriptor* desc, void merge_from_string(const char* data, int data_len, DescriptorInternal* desc,
MessageHeader* msg); MessageHeader* msg);
PHP_METHOD(Message, serializeToString); PHP_METHOD(Message, serializeToString);
...@@ -1491,8 +1536,11 @@ size_t stringsink_string(void *_sink, const void *hd, const char *ptr, ...@@ -1491,8 +1536,11 @@ size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Memory management // Memory management
#define SYS_MALLOC(class_name) (class_name*) malloc(sizeof(class_name))
#define SYS_MALLOC_N(class_name, n) (class_name*) malloc(sizeof(class_name) * n)
#define SYS_FREE(ptr) free(ptr)
#define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name)) #define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name))
#define PEMALLOC(class_name) (class_name*) pemalloc(sizeof(class_name), 1) #define PEMALLOC(class_name, persistent) (class_name*) pemalloc(sizeof(class_name), persistent)
#define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n) #define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n)
#define FREE(object) efree(object) #define FREE(object) efree(object)
#define PEFREE(object) pefree(object, 1) #define PEFREE(object) pefree(object, 1)
......
...@@ -550,12 +550,11 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) { ...@@ -550,12 +550,11 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
const zend_class_entry* field_type_class( const zend_class_entry* field_type_class(
const upb_fielddef* field PHP_PROTO_TSRMLS_DC) { const upb_fielddef* field PHP_PROTO_TSRMLS_DC) {
if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) { if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
Descriptor* desc = UNBOX_HASHTABLE_VALUE( DescriptorInternal* desc = get_msgdef_desc(upb_fielddef_msgsubdef(field));
Descriptor, get_def_obj(upb_fielddef_msgsubdef(field)));
return desc->klass; return desc->klass;
} else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) { } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
EnumDescriptor* desc = UNBOX_HASHTABLE_VALUE( EnumDescriptorInternal* desc =
EnumDescriptor, get_def_obj(upb_fielddef_enumsubdef(field))); get_enumdef_enumdesc(upb_fielddef_enumsubdef(field));
return desc->klass; return desc->klass;
} }
return NULL; return NULL;
...@@ -587,7 +586,7 @@ void* slot_memory(MessageLayout* layout, const void* storage, ...@@ -587,7 +586,7 @@ void* slot_memory(MessageLayout* layout, const void* storage,
} }
MessageLayout* create_layout(const upb_msgdef* msgdef) { MessageLayout* create_layout(const upb_msgdef* msgdef) {
MessageLayout* layout = ALLOC(MessageLayout); MessageLayout* layout = SYS_MALLOC(MessageLayout);
int nfields = upb_msgdef_numfields(msgdef); int nfields = upb_msgdef_numfields(msgdef);
upb_msg_field_iter it; upb_msg_field_iter it;
upb_msg_oneof_iter oit; upb_msg_oneof_iter oit;
...@@ -600,8 +599,8 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) { ...@@ -600,8 +599,8 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
layout->empty_template = NULL; layout->empty_template = NULL;
TSRMLS_FETCH(); TSRMLS_FETCH();
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msgdef)); DescriptorInternal* desc = get_msgdef_desc(msgdef);
layout->fields = ALLOC_N(MessageField, nfields); layout->fields = SYS_MALLOC_N(MessageField, nfields);
for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it); for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it);
upb_msg_field_next(&it)) { upb_msg_field_next(&it)) {
...@@ -745,16 +744,16 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) { ...@@ -745,16 +744,16 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
layout->msgdef = msgdef; layout->msgdef = msgdef;
// Create the empty message template. // Create the empty message template.
layout->empty_template = ALLOC_N(char, layout->size); layout->empty_template = SYS_MALLOC_N(char, layout->size);
memset(layout->empty_template, 0, layout->size); memset(layout->empty_template, 0, layout->size);
return layout; return layout;
} }
void free_layout(MessageLayout* layout) { void free_layout(MessageLayout* layout) {
FREE(layout->empty_template); SYS_FREE(layout->empty_template);
FREE(layout->fields); SYS_FREE(layout->fields);
FREE(layout); SYS_FREE(layout);
} }
void layout_init(MessageLayout* layout, void* storage, void layout_init(MessageLayout* layout, void* storage,
...@@ -822,9 +821,7 @@ zval* layout_get(MessageLayout* layout, MessageHeader* header, ...@@ -822,9 +821,7 @@ zval* layout_get(MessageLayout* layout, MessageHeader* header,
const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field); const upb_msgdef* submsgdef = upb_fielddef_msgsubdef(field);
const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1); const upb_fielddef* value_field = upb_msgdef_itof(submsgdef, 1);
MessageHeader* submsg; MessageHeader* submsg;
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(submsgdef);
UNBOX_HASHTABLE_VALUE(
Descriptor, get_def_obj((void*)submsgdef));
zend_class_entry* subklass = subdesc->klass; zend_class_entry* subklass = subdesc->klass;
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
zval* val = NULL; zval* val = NULL;
...@@ -879,8 +876,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header, ...@@ -879,8 +876,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
if (upb_fielddef_descriptortype(valuefield) == if (upb_fielddef_descriptortype(valuefield) ==
UPB_DESCRIPTOR_TYPE_MESSAGE) { UPB_DESCRIPTOR_TYPE_MESSAGE) {
const upb_msgdef* submsg = upb_fielddef_msgsubdef(valuefield); const upb_msgdef* submsg = upb_fielddef_msgsubdef(valuefield);
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(submsg);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(submsg));
subce = subdesc->klass; subce = subdesc->klass;
} }
check_map_field(subce, upb_fielddef_descriptortype(keyfield), check_map_field(subce, upb_fielddef_descriptortype(keyfield),
...@@ -889,8 +885,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header, ...@@ -889,8 +885,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
} else { } else {
if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) { if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
const upb_msgdef* submsg = upb_fielddef_msgsubdef(field); const upb_msgdef* submsg = upb_fielddef_msgsubdef(field);
Descriptor* subdesc = DescriptorInternal* subdesc = get_msgdef_desc(submsg);
UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(submsg));
subce = subdesc->klass; subce = subdesc->klass;
} }
...@@ -912,7 +907,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header, ...@@ -912,7 +907,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
zend_class_entry *ce = NULL; zend_class_entry *ce = NULL;
if (type == UPB_TYPE_MESSAGE) { if (type == UPB_TYPE_MESSAGE) {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field); const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg)); DescriptorInternal* desc = get_msgdef_desc(msg);
ce = desc->klass; ce = desc->klass;
} }
CACHED_VALUE* cache = find_zval_property(header, field); CACHED_VALUE* cache = find_zval_property(header, field);
...@@ -950,7 +945,7 @@ static void native_slot_merge( ...@@ -950,7 +945,7 @@ static void native_slot_merge(
break; break;
case UPB_TYPE_MESSAGE: { case UPB_TYPE_MESSAGE: {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field); const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg)); DescriptorInternal* desc = get_msgdef_desc(msg);
ce = desc->klass; ce = desc->klass;
if (native_slot_is_default(type, to_memory)) { if (native_slot_is_default(type, to_memory)) {
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
...@@ -996,7 +991,7 @@ static void native_slot_merge_by_array(const upb_fielddef* field, const void* fr ...@@ -996,7 +991,7 @@ static void native_slot_merge_by_array(const upb_fielddef* field, const void* fr
} }
case UPB_TYPE_MESSAGE: { case UPB_TYPE_MESSAGE: {
const upb_msgdef* msg = upb_fielddef_msgsubdef(field); const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msg)); DescriptorInternal* desc = get_msgdef_desc(upb_fielddef_msgsubdef(field));
zend_class_entry* ce = desc->klass; zend_class_entry* ce = desc->klass;
#if PHP_MAJOR_VERSION < 7 #if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL(DEREF(to_memory, zval*)); MAKE_STD_ZVAL(DEREF(to_memory, zval*));
......
...@@ -4589,6 +4589,13 @@ const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) ...@@ -4589,6 +4589,13 @@ const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name)
: NULL; : NULL;
} }
const upb_filedef *upb_symtab_lookupfile2(
const upb_symtab *s, const char *name, size_t len) {
upb_value v;
return upb_strtable_lookup2(&s->files, name, len, &v) ?
upb_value_getconstptr(v) : NULL;
}
const upb_filedef *upb_symtab_addfile( const upb_filedef *upb_symtab_addfile(
upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
upb_status *status) { upb_status *status) {
......
...@@ -3760,6 +3760,8 @@ const upb_msgdef *upb_symtab_lookupmsg2( ...@@ -3760,6 +3760,8 @@ const upb_msgdef *upb_symtab_lookupmsg2(
const upb_symtab *s, const char *sym, size_t len); const upb_symtab *s, const char *sym, size_t len);
const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name); const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
const upb_filedef *upb_symtab_lookupfile2(
const upb_symtab *s, const char *name, size_t len);
int upb_symtab_filecount(const upb_symtab *s); int upb_symtab_filecount(const upb_symtab *s);
const upb_filedef *upb_symtab_addfile( const upb_filedef *upb_symtab_addfile(
upb_symtab *s, const google_protobuf_FileDescriptorProto *file, upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
......
...@@ -20,12 +20,22 @@ do ...@@ -20,12 +20,22 @@ do
echo "" echo ""
done done
for t in "${tests[@]}"
do
echo "****************************"
echo "* $t persistent"
echo "****************************"
php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php $t
echo ""
done
# # Make sure to run the memory test in debug mode. # # Make sure to run the memory test in debug mode.
# php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php # php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
export ZEND_DONT_UNLOAD_MODULES=1 export ZEND_DONT_UNLOAD_MODULES=1
export USE_ZEND_ALLOC=0 export USE_ZEND_ALLOC=0
valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
# TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by # TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by
# regresssion test.) # regresssion test.)
......
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