[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 10/15] qapi: Adjust layout of FooList types
From: |
Markus Armbruster |
Subject: |
[Qemu-devel] [PULL 10/15] qapi: Adjust layout of FooList types |
Date: |
Fri, 19 Feb 2016 13:18:01 +0100 |
From: Eric Blake <address@hidden>
By sticking the next pointer first, we don't need a union with
64-bit padding for smaller types. On 32-bit platforms, this
can reduce the size of uint8List from 16 bytes (or 12, depending
on whether 64-bit ints can tolerate 4-byte alignment) down to 8.
It has no effect on 64-bit platforms (where alignment still
dictates a 16-byte struct); but fewer anonymous unions is still
a win in my book.
It requires visit_next_list() to gain a size parameter, to know
what size element to allocate; comparable to the size parameter
of visit_start_struct().
I debated about going one step further, to allow for fewer casts,
by doing:
typedef GenericList GenericList;
struct GenericList {
GenericList *next;
};
struct FooList {
GenericList base;
Foo *value;
};
so that you convert to 'GenericList *' by '&foolist->base', and
back by 'container_of(generic, GenericList, base)' (as opposed to
the existing '(GenericList *)foolist' and '(FooList *)generic').
But doing that would require hoisting the declaration of
GenericList prior to inclusion of qapi-types.h, rather than its
current spot in visitor.h; it also makes iteration a bit more
verbose through 'foolist->base.next' instead of 'foolist->next'.
Note that for lists of objects, the 'value' payload is still
hidden behind a boxed pointer. Someday, it would be nice to do:
struct FooList {
FooList *next;
Foo value;
};
for one less level of malloc for each list element. This patch
is a step in that direction (now that 'next' is no longer at a
fixed non-zero offset within the struct, we can store more than
just a pointer's-worth of data as the value payload), but the
actual conversion would be a task for another series, as it will
touch a lot of code.
Signed-off-by: Eric Blake <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Markus Armbruster <address@hidden>
---
include/qapi/visitor-impl.h | 2 +-
include/qapi/visitor.h | 13 ++++++-------
qapi/opts-visitor.c | 4 ++--
qapi/qapi-dealloc-visitor.c | 3 ++-
qapi/qapi-visit-core.c | 5 +++--
qapi/qmp-input-visitor.c | 5 +++--
qapi/qmp-output-visitor.c | 3 ++-
qapi/string-input-visitor.c | 4 ++--
qapi/string-output-visitor.c | 2 +-
scripts/qapi-types.py | 5 +----
scripts/qapi-visit.py | 2 +-
11 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index ea252f8..7905a28 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -29,7 +29,7 @@ struct Visitor
void (*start_list)(Visitor *v, const char *name, Error **errp);
/* Must be set */
- GenericList *(*next_list)(Visitor *v, GenericList **list);
+ GenericList *(*next_list)(Visitor *v, GenericList **list, size_t size);
/* Must be set */
void (*end_list)(Visitor *v);
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 5e581dc..8a2d5cc 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -19,13 +19,12 @@
#include "qapi/error.h"
#include <stdlib.h>
-typedef struct GenericList
-{
- union {
- void *value;
- uint64_t padding;
- };
+/* This struct is layout-compatible with all other *List structs
+ * created by the qapi generator. It is used as a typical
+ * singly-linked list. */
+typedef struct GenericList {
struct GenericList *next;
+ char padding[];
} GenericList;
void visit_start_struct(Visitor *v, const char *name, void **obj,
@@ -36,7 +35,7 @@ void visit_start_implicit_struct(Visitor *v, void **obj,
size_t size,
void visit_end_implicit_struct(Visitor *v);
void visit_start_list(Visitor *v, const char *name, Error **errp);
-GenericList *visit_next_list(Visitor *v, GenericList **list);
+GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size);
void visit_end_list(Visitor *v);
/**
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index ae5b955..73e4ace 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -215,7 +215,7 @@ opts_start_list(Visitor *v, const char *name, Error **errp)
static GenericList *
-opts_next_list(Visitor *v, GenericList **list)
+opts_next_list(Visitor *v, GenericList **list, size_t size)
{
OptsVisitor *ov = to_ov(v);
GenericList **link;
@@ -258,7 +258,7 @@ opts_next_list(Visitor *v, GenericList **list)
abort();
}
- *link = g_malloc0(sizeof **link);
+ *link = g_malloc0(size);
return *link;
}
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index 2659d3f..6667e8c 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -100,7 +100,8 @@ static void qapi_dealloc_start_list(Visitor *v, const char
*name, Error **errp)
qapi_dealloc_push(qov, NULL);
}
-static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp)
+static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
+ size_t size)
{
GenericList *list = *listp;
QapiDeallocVisitor *qov = to_qov(v);
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index f856286..b4a0f21 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -50,9 +50,10 @@ void visit_start_list(Visitor *v, const char *name, Error
**errp)
v->start_list(v, name, errp);
}
-GenericList *visit_next_list(Visitor *v, GenericList **list)
+GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size)
{
- return v->next_list(v, list);
+ assert(list && size >= sizeof(GenericList));
+ return v->next_list(v, list, size);
}
void visit_end_list(Visitor *v)
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 2f48b95..2621660 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -165,7 +165,8 @@ static void qmp_input_start_list(Visitor *v, const char
*name, Error **errp)
qmp_input_push(qiv, qobj, errp);
}
-static GenericList *qmp_input_next_list(Visitor *v, GenericList **list)
+static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
+ size_t size)
{
QmpInputVisitor *qiv = to_qiv(v);
GenericList *entry;
@@ -184,7 +185,7 @@ static GenericList *qmp_input_next_list(Visitor *v,
GenericList **list)
return NULL;
}
- entry = g_malloc0(sizeof(*entry));
+ entry = g_malloc0(size);
if (first) {
*list = entry;
} else {
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
index f47eefa..d44c676 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -126,7 +126,8 @@ static void qmp_output_start_list(Visitor *v, const char
*name, Error **errp)
qmp_output_push(qov, list);
}
-static GenericList *qmp_output_next_list(Visitor *v, GenericList **listp)
+static GenericList *qmp_output_next_list(Visitor *v, GenericList **listp,
+ size_t size)
{
GenericList *list = *listp;
QmpOutputVisitor *qov = to_qov(v);
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index 18b9339..59eb5dc 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -139,7 +139,7 @@ start_list(Visitor *v, const char *name, Error **errp)
}
}
-static GenericList *next_list(Visitor *v, GenericList **list)
+static GenericList *next_list(Visitor *v, GenericList **list, size_t size)
{
StringInputVisitor *siv = to_siv(v);
GenericList **link;
@@ -173,7 +173,7 @@ static GenericList *next_list(Visitor *v, GenericList
**list)
link = &(*list)->next;
}
- *link = g_malloc0(sizeof **link);
+ *link = g_malloc0(size);
return *link;
}
diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
index b980bd3..c2e5c5b 100644
--- a/qapi/string-output-visitor.c
+++ b/qapi/string-output-visitor.c
@@ -276,7 +276,7 @@ start_list(Visitor *v, const char *name, Error **errp)
sov->head = true;
}
-static GenericList *next_list(Visitor *v, GenericList **list)
+static GenericList *next_list(Visitor *v, GenericList **list, size_t size)
{
StringOutputVisitor *sov = to_sov(v);
GenericList *ret = NULL;
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 7b0dca8..83f230a 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -26,11 +26,8 @@ def gen_array(name, element_type):
return mcgen('''
struct %(c_name)s {
- union {
- %(c_type)s value;
- uint64_t padding;
- };
%(c_name)s *next;
+ %(c_type)s value;
};
''',
c_name=c_name(name), c_type=element_type.c_type())
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index a8b1057..dfeef71 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -173,7 +173,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name,
%(c_name)s **obj, Error
}
for (prev = (GenericList **)obj;
- !err && (i = visit_next_list(v, prev)) != NULL;
+ !err && (i = visit_next_list(v, prev, sizeof(**obj))) != NULL;
prev = &i) {
%(c_name)s *native_i = (%(c_name)s *)i;
visit_type_%(c_elt_type)s(v, NULL, &native_i->value, &err);
--
2.4.3
- [Qemu-devel] [PULL 00/15] QAPI patches for 2016-02-19, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 12/15] qapi-visit: Use common idiom in gen_visit_fields_decl(), Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 02/15] qapi: Simplify excess input reporting in input visitors, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 01/15] qapi-visit: Honor prefix of discriminator enum, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 04/15] qapi: Forbid 'any' inside an alternate, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 09/15] qapi-visit: Less indirection in visit_type_Foo_fields(), Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 08/15] qapi-visit: Unify struct and union visit, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 06/15] qapi-visit: Simplify how we visit common union members, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 10/15] qapi: Adjust layout of FooList types,
Markus Armbruster <=
- [Qemu-devel] [PULL 13/15] qapi: Don't box struct branch of alternate, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 03/15] qapi: Forbid empty unions and useless alternates, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 11/15] qapi: Emit structs used as variants in topological order, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 07/15] qapi: Visit variants in visit_type_FOO_fields(), Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 05/15] qapi: Add tests of complex objects within alternate, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 15/15] qapi: Change visit_start_implicit_struct to visit_start_alternate, Markus Armbruster, 2016/02/19
- [Qemu-devel] [PULL 14/15] qapi: Don't box branches of flat unions, Markus Armbruster, 2016/02/19