Skip to content

Commit

Permalink
qom: Split out object and class caches
Browse files Browse the repository at this point in the history
The object-cast and class-cast caches cannot be shared because class
caching is conditional on the target type not being an interface and
object caching is unconditional. Leads to a bug when a class cast
to an interface follows an object cast to the same interface type:

FooObject = FOO(obj);
FooClass = FOO_GET_CLASS(obj);

Where TYPE_FOO is an interface. The first (object) cast will be
successful and cache the casting result (i.e. TYPE_FOO will be cached).
The second (class) cast will then check the shared cast cache
and register a hit. The issue is, when a class cast hits in the cache
it just returns a pointer cast of the input class (i.e. the concrete
class).

When casting to an interface, the cast itself must return the
interface class, not the concrete class. The implementation of class
cast caching already ensures that the returned cast result is only
a pointer cast before caching. The object cast logic however does
not have this check.

Resolve by just splitting the object and class caches.

Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Tested-by: Nathan Rossi <nathan.rossi@xilinx.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
(cherry picked from commit 0ab4c94)

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
  • Loading branch information
pete128 authored and mdroth committed Feb 21, 2014
1 parent 8fa58fe commit 2dc7975
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 7 deletions.
3 changes: 2 additions & 1 deletion include/qom/object.h
Expand Up @@ -358,7 +358,8 @@ struct ObjectClass
Type type;
GSList *interfaces;

const char *cast_cache[OBJECT_CLASS_CAST_CACHE];
const char *object_cast_cache[OBJECT_CLASS_CAST_CACHE];
const char *class_cast_cache[OBJECT_CLASS_CAST_CACHE];

ObjectUnparent *unparent;
};
Expand Down
13 changes: 7 additions & 6 deletions qom/object.c
Expand Up @@ -458,7 +458,7 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename,
Object *inst;

for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
if (obj->class->cast_cache[i] == typename) {
if (obj->class->object_cast_cache[i] == typename) {
goto out;
}
}
Expand All @@ -475,9 +475,10 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename,

if (obj && obj == inst) {
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
obj->class->cast_cache[i - 1] = obj->class->cast_cache[i];
obj->class->object_cast_cache[i - 1] =
obj->class->object_cast_cache[i];
}
obj->class->cast_cache[i - 1] = typename;
obj->class->object_cast_cache[i - 1] = typename;
}

out:
Expand Down Expand Up @@ -547,7 +548,7 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
int i;

for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
if (class->cast_cache[i] == typename) {
if (class->class_cast_cache[i] == typename) {
ret = class;
goto out;
}
Expand All @@ -568,9 +569,9 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
#ifdef CONFIG_QOM_CAST_DEBUG
if (class && ret == class) {
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
class->cast_cache[i - 1] = class->cast_cache[i];
class->class_cast_cache[i - 1] = class->class_cast_cache[i];
}
class->cast_cache[i - 1] = typename;
class->class_cast_cache[i - 1] = typename;
}
out:
#endif
Expand Down

0 comments on commit 2dc7975

Please sign in to comment.