From df21d1f362a810f48a23b7c121bf09ce398539c7 Mon Sep 17 00:00:00 2001 From: Simon Feltman Date: Thu, 27 Feb 2014 17:10:19 -0800 Subject: girepository: Use constant time calculation for sections after Object fields Add "n_field_callbacks" to ObjectBlob which represents the number of object fields which are also callbacks. This a allows a constant time computation for accessing sections after fields. Track writing of this field by passing an extra argument through the girnode writers recursive call structure. This essentally reverts a portion of commit 7027bb256d0d1ab which added a linear time computation for accessing sections after fields. Update typelib validator to also ensure n_field_callbacks is properly set. https://bugzilla.gnome.org/show_bug.cgi?id=700338 --- girepository/giobjectinfo.c | 35 ++++++++++++--- girepository/girmodule.c | 2 +- girepository/girnode.c | 92 ++++++++++++++++++++++----------------- girepository/girnode.h | 3 +- girepository/gitypelib-internal.h | 5 ++- girepository/gitypelib.c | 17 +++++++- 6 files changed, 101 insertions(+), 53 deletions(-) diff --git a/girepository/giobjectinfo.c b/girepository/giobjectinfo.c index 381f4651..0991b80e 100644 --- a/girepository/giobjectinfo.c +++ b/girepository/giobjectinfo.c @@ -342,7 +342,10 @@ g_object_info_get_property (GIObjectInfo *info, header = (Header *)rinfo->typelib->data; blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset]; - offset = g_object_info_get_field_offset(info, blob->n_fields) + offset = rinfo->offset + header->object_blob_size + + (blob->n_interfaces + blob->n_interfaces % 2) * 2 + + blob->n_fields * header->field_blob_size + + blob->n_field_callbacks * header->callback_blob_size + n * header->property_blob_size; return (GIPropertyInfo *) g_info_new (GI_INFO_TYPE_PROPERTY, (GIBaseInfo*)info, @@ -397,7 +400,10 @@ g_object_info_get_method (GIObjectInfo *info, blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset]; - offset = g_object_info_get_field_offset(info, blob->n_fields) + offset = rinfo->offset + header->object_blob_size + + (blob->n_interfaces + blob->n_interfaces % 2) * 2 + + blob->n_fields * header->field_blob_size + + blob->n_field_callbacks * header->callback_blob_size + blob->n_properties * header->property_blob_size + n * header->function_blob_size; @@ -431,7 +437,10 @@ g_object_info_find_method (GIObjectInfo *info, header = (Header *)rinfo->typelib->data; blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset]; - offset = g_object_info_get_field_offset(info, blob->n_fields) + offset = rinfo->offset + header->object_blob_size + + (blob->n_interfaces + blob->n_interfaces % 2) * 2 + + blob->n_fields * header->field_blob_size + + + blob->n_field_callbacks * header->callback_blob_size + blob->n_properties * header->property_blob_size; return _g_base_info_find_method ((GIBaseInfo*)info, offset, blob->n_methods, name); @@ -541,7 +550,10 @@ g_object_info_get_signal (GIObjectInfo *info, header = (Header *)rinfo->typelib->data; blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset]; - offset = g_object_info_get_field_offset(info, blob->n_fields) + offset = rinfo->offset + header->object_blob_size + + (blob->n_interfaces + blob->n_interfaces % 2) * 2 + + blob->n_fields * header->field_blob_size + + blob->n_field_callbacks * header->callback_blob_size + blob->n_properties * header->property_blob_size + blob->n_methods * header->function_blob_size + n * header->signal_blob_size; @@ -630,7 +642,10 @@ g_object_info_get_vfunc (GIObjectInfo *info, header = (Header *)rinfo->typelib->data; blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset]; - offset = g_object_info_get_field_offset(info, blob->n_fields) + offset = rinfo->offset + header->object_blob_size + + (blob->n_interfaces + blob->n_interfaces % 2) * 2 + + blob->n_fields * header->field_blob_size + + blob->n_field_callbacks * header->callback_blob_size + blob->n_properties * header->property_blob_size + blob->n_methods * header->function_blob_size + blob->n_signals * header->signal_blob_size @@ -671,7 +686,10 @@ g_object_info_find_vfunc (GIObjectInfo *info, header = (Header *)rinfo->typelib->data; blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset]; - offset = g_object_info_get_field_offset(info, blob->n_fields) + offset = rinfo->offset + header->object_blob_size + + (blob->n_interfaces + blob->n_interfaces % 2) * 2 + + blob->n_fields * header->field_blob_size + + blob->n_field_callbacks * header->callback_blob_size + blob->n_properties * header->property_blob_size + blob->n_methods * header->function_blob_size + blob->n_signals * header->signal_blob_size; @@ -786,7 +804,10 @@ g_object_info_get_constant (GIObjectInfo *info, header = (Header *)rinfo->typelib->data; blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset]; - offset = g_object_info_get_field_offset(info, blob->n_fields) + offset = rinfo->offset + header->object_blob_size + + (blob->n_interfaces + blob->n_interfaces % 2) * 2 + + blob->n_fields * header->field_blob_size + + blob->n_field_callbacks * header->callback_blob_size + blob->n_properties * header->property_blob_size + blob->n_methods * header->function_blob_size + blob->n_signals * header->signal_blob_size diff --git a/girepository/girmodule.c b/girepository/girmodule.c index e3897c34..66b33fa1 100644 --- a/girepository/girmodule.c +++ b/girepository/girmodule.c @@ -508,7 +508,7 @@ _g_ir_module_build_typelib (GIrModule *module) build.nodes_with_attributes = nodes_with_attributes; build.n_attributes = header->n_attributes; build.data = data; - _g_ir_node_build_typelib (node, NULL, &build, &offset, &offset2); + _g_ir_node_build_typelib (node, NULL, &build, &offset, &offset2, NULL); nodes_with_attributes = build.nodes_with_attributes; header->n_attributes = build.n_attributes; diff --git a/girepository/girnode.c b/girepository/girnode.c index d0a18a31..455e9d6c 100644 --- a/girepository/girnode.c +++ b/girepository/girnode.c @@ -1326,7 +1326,8 @@ _g_ir_node_build_members (GList **members, GIrNode *parent, GIrTypelibBuild *build, guint32 *offset, - guint32 *offset2) + guint32 *offset2, + guint16 *count2) { GList *l = *members; @@ -1338,7 +1339,7 @@ _g_ir_node_build_members (GList **members, if (member->type == type) { (*count)++; - _g_ir_node_build_typelib (member, parent, build, offset, offset2); + _g_ir_node_build_typelib (member, parent, build, offset, offset2, count2); *members = g_list_delete_link (*members, l); } l = next; @@ -1379,7 +1380,8 @@ _g_ir_node_build_typelib (GIrNode *node, GIrNode *parent, GIrTypelibBuild *build, guint32 *offset, - guint32 *offset2) + guint32 *offset2, + guint16 *count2) { gboolean appended_stack; GHashTable *strings = build->strings; @@ -1480,7 +1482,7 @@ _g_ir_node_build_typelib (GIrNode *node, *offset2 += sizeof (ArrayTypeBlob); _g_ir_node_build_typelib ((GIrNode *)type->parameter_type1, - node, build, &pos, offset2); + node, build, &pos, offset2, NULL); } break; @@ -1514,7 +1516,7 @@ _g_ir_node_build_typelib (GIrNode *node, *offset2 += sizeof (ParamTypeBlob) + sizeof (SimpleTypeBlob); _g_ir_node_build_typelib ((GIrNode *)type->parameter_type1, - node, build, &pos, offset2); + node, build, &pos, offset2, NULL); } break; @@ -1533,9 +1535,9 @@ _g_ir_node_build_typelib (GIrNode *node, *offset2 += sizeof (ParamTypeBlob) + sizeof (SimpleTypeBlob)*2; _g_ir_node_build_typelib ((GIrNode *)type->parameter_type1, - node, build, &pos, offset2); + node, build, &pos, offset2, NULL); _g_ir_node_build_typelib ((GIrNode *)type->parameter_type2, - node, build, &pos, offset2); + node, build, &pos, offset2, NULL); } break; @@ -1585,7 +1587,14 @@ _g_ir_node_build_typelib (GIrNode *node, blob->type.offset = GI_INFO_TYPE_CALLBACK; *offset += sizeof (FieldBlob); _g_ir_node_build_typelib ((GIrNode *)field->callback, - node, build, offset, offset2); + node, build, offset, offset2, NULL); + /* Fields with callbacks are bigger than normal, update count2 + * as an extra hint which represents the number of fields which are + * callbacks. This allows us to gain constant time performance in the + * repository for skipping over the fields section. + */ + if (count2) + (*count2)++; } else { @@ -1593,7 +1602,7 @@ _g_ir_node_build_typelib (GIrNode *node, /* We handle the size member specially below, so subtract it */ *offset += sizeof (FieldBlob) - sizeof (SimpleTypeBlob); _g_ir_node_build_typelib ((GIrNode *)field->type, - node, build, offset, offset2); + node, build, offset, offset2, NULL); } } break; @@ -1616,7 +1625,7 @@ _g_ir_node_build_typelib (GIrNode *node, blob->reserved = 0; _g_ir_node_build_typelib ((GIrNode *)prop->type, - node, build, offset, offset2); + node, build, offset, offset2, NULL); } break; @@ -1658,7 +1667,7 @@ _g_ir_node_build_typelib (GIrNode *node, g_debug ("building function '%s'", function->symbol); _g_ir_node_build_typelib ((GIrNode *)function->result->type, - node, build, &signature, offset2); + node, build, &signature, offset2, NULL); blob2->may_return_null = function->result->nullable; blob2->caller_owns_return_value = function->result->transfer; @@ -1675,7 +1684,7 @@ _g_ir_node_build_typelib (GIrNode *node, { GIrNode *param = (GIrNode *)l->data; - _g_ir_node_build_typelib (param, node, build, &signature, offset2); + _g_ir_node_build_typelib (param, node, build, &signature, offset2, NULL); } } @@ -1702,7 +1711,7 @@ _g_ir_node_build_typelib (GIrNode *node, blob->signature = signature; _g_ir_node_build_typelib ((GIrNode *)function->result->type, - node, build, &signature, offset2); + node, build, &signature, offset2, NULL); blob2->may_return_null = function->result->nullable; blob2->caller_owns_return_value = function->result->transfer; @@ -1717,7 +1726,7 @@ _g_ir_node_build_typelib (GIrNode *node, { GIrNode *param = (GIrNode *)l->data; - _g_ir_node_build_typelib (param, node, build, &signature, offset2); + _g_ir_node_build_typelib (param, node, build, &signature, offset2, NULL); } } break; @@ -1760,7 +1769,7 @@ _g_ir_node_build_typelib (GIrNode *node, ((GIrNode *) signal->result)->offset = signature; _g_ir_node_build_typelib ((GIrNode *)signal->result->type, - node, build, &signature, offset2); + node, build, &signature, offset2, NULL); blob2->may_return_null = signal->result->nullable; blob2->caller_owns_return_value = signal->result->transfer; @@ -1775,7 +1784,7 @@ _g_ir_node_build_typelib (GIrNode *node, { GIrNode *param = (GIrNode *)l->data; - _g_ir_node_build_typelib (param, node, build, &signature, offset2); + _g_ir_node_build_typelib (param, node, build, &signature, offset2, NULL); } } break; @@ -1819,7 +1828,7 @@ _g_ir_node_build_typelib (GIrNode *node, blob->signature = signature; _g_ir_node_build_typelib ((GIrNode *)vfunc->result->type, - node, build, &signature, offset2); + node, build, &signature, offset2, NULL); blob2->may_return_null = vfunc->result->nullable; blob2->caller_owns_return_value = vfunc->result->transfer; @@ -1835,7 +1844,7 @@ _g_ir_node_build_typelib (GIrNode *node, { GIrNode *param = (GIrNode *)l->data; - _g_ir_node_build_typelib (param, node, build, &signature, offset2); + _g_ir_node_build_typelib (param, node, build, &signature, offset2, NULL); } } break; @@ -1865,7 +1874,7 @@ _g_ir_node_build_typelib (GIrNode *node, blob->closure = param->closure; blob->destroy = param->destroy; - _g_ir_node_build_typelib ((GIrNode *)param->type, node, build, offset, offset2); + _g_ir_node_build_typelib ((GIrNode *)param->type, node, build, offset, offset2, NULL); } break; @@ -1905,10 +1914,10 @@ _g_ir_node_build_typelib (GIrNode *node, members = g_list_copy (struct_->members); _g_ir_node_build_members (&members, G_IR_NODE_FIELD, &blob->n_fields, - node, build, offset, offset2); + node, build, offset, offset2, NULL); _g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_methods, - node, build, offset, offset2); + node, build, offset, offset2, NULL); _g_ir_node_check_unhandled_members (&members, node->type); @@ -1940,10 +1949,10 @@ _g_ir_node_build_typelib (GIrNode *node, members = g_list_copy (boxed->members); _g_ir_node_build_members (&members, G_IR_NODE_FIELD, &blob->n_fields, - node, build, offset, offset2); + node, build, offset, offset2, NULL); _g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_methods, - node, build, offset, offset2); + node, build, offset, offset2, NULL); _g_ir_node_check_unhandled_members (&members, node->type); @@ -1988,7 +1997,7 @@ _g_ir_node_build_typelib (GIrNode *node, *offset += 28; blob->discriminated = TRUE; _g_ir_node_build_typelib ((GIrNode *)union_->discriminator_type, - build, offset, offset2); + build, offset, offset2, NULL); } else { @@ -2000,10 +2009,10 @@ _g_ir_node_build_typelib (GIrNode *node, members = g_list_copy (union_->members); _g_ir_node_build_members (&members, G_IR_NODE_FIELD, &blob->n_fields, - node, build, offset, offset2); + node, build, offset, offset2, NULL); _g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_functions, - node, build, offset, offset2); + node, build, offset, offset2, NULL); _g_ir_node_check_unhandled_members (&members, node->type); @@ -2015,7 +2024,7 @@ _g_ir_node_build_typelib (GIrNode *node, { GIrNode *member = (GIrNode *)l->data; - _g_ir_node_build_typelib (member, node, build, offset, offset2); + _g_ir_node_build_typelib (member, node, build, offset, offset2, NULL); } } } @@ -2063,7 +2072,7 @@ _g_ir_node_build_typelib (GIrNode *node, GIrNode *value = (GIrNode *)l->data; blob->n_values++; - _g_ir_node_build_typelib (value, node, build, offset, offset2); + _g_ir_node_build_typelib (value, node, build, offset, offset2, NULL); } for (l = enum_->methods; l; l = l->next) @@ -2071,7 +2080,7 @@ _g_ir_node_build_typelib (GIrNode *node, GIrNode *method = (GIrNode *)l->data; blob->n_methods++; - _g_ir_node_build_typelib (method, node, build, offset, offset2); + _g_ir_node_build_typelib (method, node, build, offset, offset2, NULL); } } break; @@ -2114,6 +2123,7 @@ _g_ir_node_build_typelib (GIrNode *node, blob->n_signals = 0; blob->n_vfuncs = 0; blob->n_constants = 0; + blob->n_field_callbacks = 0; *offset += sizeof(ObjectBlob); for (l = object->interfaces; l; l = l->next) @@ -2127,27 +2137,27 @@ _g_ir_node_build_typelib (GIrNode *node, *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_FIELD, &blob->n_fields, - node, build, offset, offset2); + node, build, offset, offset2, &blob->n_field_callbacks); *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_PROPERTY, &blob->n_properties, - node, build, offset, offset2); + node, build, offset, offset2, NULL); *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_methods, - node, build, offset, offset2); + node, build, offset, offset2, NULL); *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_SIGNAL, &blob->n_signals, - node, build, offset, offset2); + node, build, offset, offset2, NULL); *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_VFUNC, &blob->n_vfuncs, - node, build, offset, offset2); + node, build, offset, offset2, NULL); *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_CONSTANT, &blob->n_constants, - node, build, offset, offset2); + node, build, offset, offset2, NULL); _g_ir_node_check_unhandled_members (&members, node->type); @@ -2190,23 +2200,23 @@ _g_ir_node_build_typelib (GIrNode *node, *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_PROPERTY, &blob->n_properties, - node, build, offset, offset2); + node, build, offset, offset2, NULL); *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_methods, - node, build, offset, offset2); + node, build, offset, offset2, NULL); *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_SIGNAL, &blob->n_signals, - node, build, offset, offset2); + node, build, offset, offset2, NULL); *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_VFUNC, &blob->n_vfuncs, - node, build, offset, offset2); + node, build, offset, offset2, NULL); *offset = ALIGN_VALUE (*offset, 4); _g_ir_node_build_members (&members, G_IR_NODE_CONSTANT, &blob->n_constants, - node, build, offset, offset2); + node, build, offset, offset2, NULL); _g_ir_node_check_unhandled_members (&members, node->type); @@ -2298,7 +2308,7 @@ _g_ir_node_build_typelib (GIrNode *node, } *offset2 += ALIGN_VALUE (blob->size, 4); - _g_ir_node_build_typelib ((GIrNode *)constant->type, node, build, &pos, offset2); + _g_ir_node_build_typelib ((GIrNode *)constant->type, node, build, &pos, offset2, NULL); } break; default: diff --git a/girepository/girnode.h b/girepository/girnode.h index 02196e7f..e4ce85a4 100644 --- a/girepository/girnode.h +++ b/girepository/girnode.h @@ -358,7 +358,8 @@ void _g_ir_node_build_typelib (GIrNode *node, GIrNode *parent, GIrTypelibBuild *build, guint32 *offset, - guint32 *offset2); + guint32 *offset2, + guint16 *count2); int _g_ir_node_cmp (GIrNode *node, GIrNode *other); gboolean _g_ir_node_can_have_member (GIrNode *node); diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h index 5ccff719..0f105127 100644 --- a/girepository/gitypelib-internal.h +++ b/girepository/gitypelib-internal.h @@ -1051,7 +1051,8 @@ typedef struct { * @n_constants: The lengths of the arrays.Up to 16bits of padding may be * inserted between the arrays to ensure that they start on a 32bit * boundary. - * @reserved2: Reserved for future use. + * @n_field_callbacks: The number of n_fields which are also callbacks. + * This is used to calculate the fields section size in constant time. * @ref_func: String pointing to a function which can be called to increase * the reference count for an instance of this object type. * @unref_func: String pointing to a function which can be called to decrease @@ -1088,7 +1089,7 @@ typedef struct { guint16 n_signals; guint16 n_vfuncs; guint16 n_constants; - guint16 reserved2; + guint16 n_field_callbacks; guint32 ref_func; guint32 unref_func; diff --git a/girepository/gitypelib.c b/girepository/gitypelib.c index 09e74f13..8ae4b44d 100644 --- a/girepository/gitypelib.c +++ b/girepository/gitypelib.c @@ -1645,6 +1645,7 @@ validate_object_blob (ValidateContext *ctx, ObjectBlob *blob; gint i; guint32 offset2; + guint16 n_field_callbacks; header = (Header *)typelib->data; @@ -1774,6 +1775,7 @@ validate_object_blob (ValidateContext *ctx, push_context (ctx, get_string_nofail (typelib, blob->name)); + n_field_callbacks = 0; for (i = 0; i < blob->n_fields; i++) { FieldBlob *blob = (FieldBlob*) &typelib->data[offset2]; @@ -1783,8 +1785,21 @@ validate_object_blob (ValidateContext *ctx, offset2 += sizeof (FieldBlob); /* Special case fields which are callbacks. */ - if (blob->has_embedded_type) + if (blob->has_embedded_type) { offset2 += sizeof (CallbackBlob); + n_field_callbacks++; + } + } + + if (blob->n_field_callbacks != n_field_callbacks) + { + g_set_error (error, + G_TYPELIB_ERROR, + G_TYPELIB_ERROR_INVALID_BLOB, + "Incorrect number of field callbacks; expected " + G_GUINT16_FORMAT ", got " G_GUINT16_FORMAT, + blob->n_field_callbacks, n_field_callbacks); + return FALSE; } for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob)) -- cgit v1.2.1