summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Feltman <sfeltman@src.gnome.org>2014-02-27 17:10:19 -0800
committerColin Walters <walters@verbum.org>2015-10-10 17:41:24 -0400
commitdf21d1f362a810f48a23b7c121bf09ce398539c7 (patch)
treeb5fd8d369bacdb4a9cea40f4a5421321a38c5007
parent0aa60a43c4c9679668e15dbf3ef7a39016525150 (diff)
downloadgobject-introspection-df21d1f362a810f48a23b7c121bf09ce398539c7.tar.gz
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
-rw-r--r--girepository/giobjectinfo.c35
-rw-r--r--girepository/girmodule.c2
-rw-r--r--girepository/girnode.c92
-rw-r--r--girepository/girnode.h3
-rw-r--r--girepository/gitypelib-internal.h5
-rw-r--r--girepository/gitypelib.c17
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))