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
This commit is contained in:
Simon Feltman 2014-02-27 17:10:19 -08:00 committed by Colin Walters
parent 714414f0af
commit 220fbf35b8
6 changed files with 101 additions and 53 deletions

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -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))