Unverified Commit 3cae8677 authored by Paul Yang's avatar Paul Yang Committed by GitHub

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 3cc55d61
This diff is collapsed.
This diff is collapsed.
...@@ -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;
......
This diff is collapsed.
...@@ -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