1. 18 3月, 2016 12 次提交
    • E
      qapi: Don't special-case simple union wrappers · 32bafa8f
      Eric Blake 提交于
      Simple unions were carrying a special case that hid their 'data'
      QMP member from the resulting C struct, via the hack method
      QAPISchemaObjectTypeVariant.simple_union_type().  But by using
      the work we started by unboxing flat union and alternate
      branches, coupled with the ability to visit the members of an
      implicit type, we can now expose the simple union's implicit
      type in qapi-types.h:
      
      | struct q_obj_ImageInfoSpecificQCow2_wrapper {
      |     ImageInfoSpecificQCow2 *data;
      | };
      |
      | struct q_obj_ImageInfoSpecificVmdk_wrapper {
      |     ImageInfoSpecificVmdk *data;
      | };
      ...
      | struct ImageInfoSpecific {
      |     ImageInfoSpecificKind type;
      |     union { /* union tag is @type */
      |         void *data;
      |-        ImageInfoSpecificQCow2 *qcow2;
      |-        ImageInfoSpecificVmdk *vmdk;
      |+        q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
      |+        q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
      |     } u;
      | };
      
      Doing this removes asymmetry between QAPI's QMP side and its
      C side (both sides now expose 'data'), and means that the
      treatment of a simple union as sugar for a flat union is now
      equivalent in both languages (previously the two approaches used
      a different layer of dereferencing, where the simple union could
      be converted to a flat union with equivalent C layout but
      different {} on the wire, or to an equivalent QMP wire form
      but with different C representation).  Using the implicit type
      also lets us get rid of the simple_union_type() hack.
      
      Of course, now all clients of simple unions have to adjust from
      using su->u.member to using su->u.member.data; while this touches
      a number of files in the tree, some earlier cleanup patches
      helped minimize the change to the initialization of a temporary
      variable rather than every single member access.  The generated
      qapi-visit.c code is also affected by the layout change:
      
      |@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
      |     }
      |     switch (obj->type) {
      |     case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
      |-        visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
      |+        visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
      |         break;
      |     case IMAGE_INFO_SPECIFIC_KIND_VMDK:
      |-        visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
      |+        visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
      |         break;
      |     default:
      |         abort();
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      32bafa8f
    • E
      qapi: Drop unused c_null() · 861877a0
      Eric Blake 提交于
      Now that we are always bulk-initializing a QAPI C struct to 0
      (whether by g_malloc0() or by 'Type arg = {0};'), we no longer
      have any clients of c_null() in the generator for per-element
      initialization.  This patch is easy enough to revert if we find
      a use in the future, but in the present, get rid of the dead code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-12-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      861877a0
    • E
      qapi: Inline gen_visit_members() into lone caller · 12f254fd
      Eric Blake 提交于
      Commit 82ca8e46 noticed that we had multiple implementations of
      visiting every member of a struct, and consolidated it into
      gen_visit_fields() (now gen_visit_members()) with enough
      parameters to cater to slight differences between the clients.
      But recent exposure of implicit types has meant that we are now
      down to a single use of that method, so we can clean up the
      unused conditionals and just inline it into the remaining
      caller: gen_visit_object_members().
      
      Likewise, gen_err_check() no longer needs optional parameters,
      as the lone use of non-defaults was via gen_visit_members().
      
      No change to generated code.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-11-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      12f254fd
    • E
      qapi-commands: Inline single-use helpers of gen_marshal() · c1ff0e6c
      Eric Blake 提交于
      Originally, gen_marshal_input_visit() (or gen_visitor_input_block()
      before commit f1538019) was factored out to make it easy to do two
      passes of a visit to each member of a (possibly-implicit) object,
      without duplicating lots of code.  But after recent changes, those
      visits now occupy a single line of emitted code, and the helper
      method has become a series of conditionals both before and after
      the one important line, making it rather awkward to see at a glance
      what gets emitted on the first (parsing) or second (deallocation)
      pass.  It's a lot easier to read the generator code if we just
      inline both uses directly into gen_marshal(), without all the
      conditionals.
      
      Once we've done that, it's easy to notice that gen_marshal_vars()
      is used only once, and inlining it too lets us consolidate some
      mcgen() calls that used to be split across helpers.
      
      gen_call() remains a single-use helper function, but it has
      enough indentation and complexity that inlining it would hamper
      legibility.
      
      No change to generated output.  The fact that the diffstat shows
      a net reduction in lines is an argument in favor of this cleanup.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-10-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      c1ff0e6c
    • E
      qapi-commands: Utilize implicit struct visits · 386230a2
      Eric Blake 提交于
      Rather than generate inline per-member visits, take advantage
      of the 'visit_type_FOO_members()' function for command
      marshalling.  This is possible now that implicit structs can be
      visited like any other.  Generate call arguments from a stack-
      allocated struct, rather than a list of local variables:
      
      |@@ -57,26 +57,15 @@ void qmp_marshal_add_fd(QDict *args, QOb
      |     QmpInputVisitor *qiv = qmp_input_visitor_new_strict(QOBJECT(args));
      |     QapiDeallocVisitor *qdv;
      |     Visitor *v;
      |-    bool has_fdset_id = false;
      |-    int64_t fdset_id = 0;
      |-    bool has_opaque = false;
      |-    char *opaque = NULL;
      |+    q_obj_add_fd_arg arg = {0};
      |
      |     v = qmp_input_get_visitor(qiv);
      |-    if (visit_optional(v, "fdset-id", &has_fdset_id)) {
      |-        visit_type_int(v, "fdset-id", &fdset_id, &err);
      |-        if (err) {
      |-            goto out;
      |-        }
      |-    }
      |-    if (visit_optional(v, "opaque", &has_opaque)) {
      |-        visit_type_str(v, "opaque", &opaque, &err);
      |-        if (err) {
      |-            goto out;
      |-        }
      |+    visit_type_q_obj_add_fd_arg_members(v, &arg, &err);
      |+    if (err) {
      |+        goto out;
      |     }
      |
      |-    retval = qmp_add_fd(has_fdset_id, fdset_id, has_opaque, opaque, &err);
      |+    retval = qmp_add_fd(arg.has_fdset_id, arg.fdset_id, arg.has_opaque, arg.opaque, &err);
      |     if (err) {
      |         goto out;
      |     }
      |@@ -88,12 +77,7 @@ out:
      |     qmp_input_visitor_cleanup(qiv);
      |     qdv = qapi_dealloc_visitor_new();
      |     v = qapi_dealloc_get_visitor(qdv);
      |-    if (visit_optional(v, "fdset-id", &has_fdset_id)) {
      |-        visit_type_int(v, "fdset-id", &fdset_id, NULL);
      |-    }
      |-    if (visit_optional(v, "opaque", &has_opaque)) {
      |-        visit_type_str(v, "opaque", &opaque, NULL);
      |-    }
      |+    visit_type_q_obj_add_fd_arg_members(v, &arg, NULL);
      |     qapi_dealloc_visitor_cleanup(qdv);
      | }
      
      This also has the nice side effect of eliminating a chance of
      collision between argument QMP names and local variables.
      
      This patch also paves the way for some followup simplifications
      in the generator, in subsequent patches.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-9-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      386230a2
    • E
      qapi-event: Utilize implicit struct visits · 0949e95b
      Eric Blake 提交于
      Rather than generate inline per-member visits, take advantage
      of the 'visit_type_FOO_members()' function for emitting events.
      This is possible now that implicit structs can be visited like
      any other.  Generated code shrinks accordingly; by initializing
      a struct based on parameters, through a new gen_param_var()
      helper, like:
      
      |@@ -338,6 +250,9 @@ void qapi_event_send_block_job_error(con
      |     QMPEventFuncEmit emit = qmp_event_get_func_emit();
      |     QmpOutputVisitor *qov;
      |     Visitor *v;
      |+    q_obj_BLOCK_JOB_ERROR_arg param = {
      |+        (char *)device, operation, action
      |+    };
      |
      |     if (!emit) {
      |         return;
      @@ -351,19 +266,7 @@ void qapi_event_send_block_job_error(con
      |     if (err) {
      |         goto out;
      |     }
      |-    visit_type_str(v, "device", (char **)&device, &err);
      |-    if (err) {
      |-        goto out_obj;
      |-    }
      |-    visit_type_IoOperationType(v, "operation", &operation, &err);
      |-    if (err) {
      |-        goto out_obj;
      |-    }
      |-    visit_type_BlockErrorAction(v, "action", &action, &err);
      |-    if (err) {
      |-        goto out_obj;
      |-    }
      |-out_obj:
      |+    visit_type_q_obj_BLOCK_JOB_ERROR_arg_members(v, &param, &err);
      |     visit_end_struct(v, err ? NULL : &err);
      
      Notice that the initialization of 'param' has to cast away const
      (just as the old gen_visit_members() had to do): we can't change
      the signature of the user function (which uses 'const char *'), but
      have to assign it to a non-const QAPI object (which requires
      'char *').
      
      While touching this, document with a FIXME comment that there is
      still a potential collision between QMP members and our choice of
      local variable names within qapi_event_send_FOO().
      
      This patch also paves the way for some followup simplifications
      in the generator, in subsequent patches.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-8-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      0949e95b
    • E
      qapi-event: Drop qmp_output_get_qobject() null check · 8df59565
      Eric Blake 提交于
      qmp_output_get_qobject() was changed never to return null some time
      ago (in commit 6c2f9a15), but the qapi_event_send_FOO() functions
      still check.  Clean that up:
      
      |@@ -28,7 +28,6 @@ void qapi_event_send_acpi_device_ost(ACP
      |     QMPEventFuncEmit emit;
      |     QmpOutputVisitor *qov;
      |     Visitor *v;
      |-    QObject *obj;
      |
      |     emit = qmp_event_get_func_emit();
      |     if (!emit) {
      |@@ -54,10 +53,7 @@ out_obj:
      |         goto out;
      |     }
      |
      |-    obj = qmp_output_get_qobject(qov);
      |-    g_assert(obj);
      |-
      |-    qdict_put_obj(qmp, "data", obj);
      |+    qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
      |     emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
      |
      | out:
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-7-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      8df59565
    • E
      qapi: Emit implicit structs in generated C · 7ce106a9
      Eric Blake 提交于
      We already have several places that want to visit all the members
      of an implicit object within a larger context (simple union variant,
      event with anonymous data, command with anonymous arguments struct);
      and will be adding another one soon (the ability to declare an
      anonymous base for a flat union).  Having a C struct declared for
      these implicit types, along with a visit_type_FOO_members() helper
      function, will make for fewer special cases in our generator.
      
      We do not, however, need qapi_free_FOO() or visit_type_FOO()
      functions for implicit types, because they should not be used
      directly outside of the generated code.  This is done by adding a
      conditional in visit_object_type() for both qapi-types.py and
      qapi-visit.py based on the object name.  The comparison of
      "name.startswith('q_')" is a bit hacky (it's basically duplicating
      what .is_implicit() already uses), but beats changing the signature
      of the visit_object_type() callback to pass a new 'implicit' flag.
      The hack should be temporary: we are considering adding a future
      patch that consolidates the narrow visit_object_type(..., base,
      local_members, variants) and visit_object_type_flat(...,
      all_members, variants) [where different sets of information are
      already broken out, and the QAPISchemaObjectType is no longer
      available] into a broader visit_object_type(obj_type) [where the
      visitor can query the needed fields from obj_type directly].
      
      Also, now that we WANT to output C code for implicits, we no longer
      need the visit_needed() filter, leaving 'q_empty' as the only object
      still needing a special case.  Remember, 'q_empty' is the only
      built-in generated object, which means that without a special case
      it would be emitted in multiple files (the main qapi-types.h and in
      qga-qapi-types.h) causing compilation failure due to redefinition.
      But since it has no members, it's easier to just avoid an attempt to
      visit that particular type; since gen_object() is called recursively,
      we also prime the objects_seen set to cover any recursion into the
      empty type.
      
      The patch relies on the changed naming of implicit types in the
      previous patch.  It is a bit unfortunate that the generated struct
      names and visit_type_FOO_members() don't match normal naming
      conventions, but it's not too bad, since they will only be used in
      generated code.
      
      The generated code grows substantially in size: the implicit
      '-wrapper' types must be emitted in qapi-types.h before any union
      can include an unboxed member of that type.  Arguably, the '-args'
      types could be emitted in a private header for just qapi-visit.c
      and qmp-marshal.c, rather than polluting qapi-types.h; but adding
      complexity to the generator to split the output location according
      to role doesn't seem worth the maintenance costs.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-6-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      7ce106a9
    • E
      qapi: Adjust names of implicit types · 7599697c
      Eric Blake 提交于
      The original choice of ':obj-' as the prefix for implicit types
      made it obvious that we weren't going to clash with any user-defined
      names, which cannot contain ':'.  But now we want to create structs
      for implicit types, to get rid of special cases in the generators,
      and our use of ':' in implicit names needs a tweak to produce valid
      C code.
      
      We could transliterate ':' to '_', except that C99 mandates that
      "identifiers that begin with an underscore are always reserved for
      use as identifiers with file scope in both the ordinary and tag name
      spaces".  So it's time to change our naming convention: we can
      instead use the 'q_' prefix that we reserved for ourselves back in
      commit 9fb081e0.  Technically, since we aren't planning on exposing
      the empty type in generated code, we could keep the name ':empty',
      but renaming it to 'q_empty' makes the check for startswith('q_')
      cover all implicit types, whether or not code is generated for them.
      
      As long as we don't declare 'empty' or 'obj' ticklish, it shouldn't
      clash with c_name() prepending 'q_' to the user's ticklish names.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-5-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      7599697c
    • E
      qapi: Make c_type() more OO-like · 4040d995
      Eric Blake 提交于
      QAPISchemaType.c_type() is a bit awkward: it takes two optional
      boolean flags is_param and is_unboxed, and they should never both
      be True.
      
      Add a new method for each of the flags, and drop the flags from
      c_type().
      
      Most callers pass no flags; they remain unchanged.
      
      One caller passes is_param=True; call the new .c_param_type()
      instead.
      
      One caller passes is_unboxed=True, except for simple union types.
      This is actually an ugly special case that will go away soon, so
      until then, we now have to call either .c_type() or the new
      .c_unboxed_type().  Tolerable in the interim.
      
      It requires slightly more Python, but is arguably easier to read.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-4-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      4040d995
    • E
      qapi: Fix command with named empty argument type · 972a1101
      Eric Blake 提交于
      The generator special-cased
      
       { 'command':'foo', 'data': {} }
      
      to avoid emitting a visitor variable, but failed to see that
      
       { 'struct':'NamedEmptyType, 'data': {} }
       { 'command':'foo', 'data':'NamedEmptyType' }
      
      needs the same treatment.  There, the generator happily generates a
      visitor to get no arguments, and a visitor to destroy no arguments;
      and the compiler isn't happy with that, as demonstrated by the updated
      qapi-schema-test.json:
      
        tests/test-qmp-marshal.c: In function ‘qmp_marshal_user_def_cmd0’:
        tests/test-qmp-marshal.c:264:14: error: variable ‘v’ set but not used [-Werror=unused-but-set-variable]
             Visitor *v;
                      ^
      
      No change to generated code except for the testsuite addition.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-3-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      972a1101
    • E
      qapi: Assert in places where variants are not handled · 29f6bd15
      Eric Blake 提交于
      We are getting closer to the point where we could use one union
      as the base or variant type within another union type (as long
      as there are no collisions between any possible combination of
      member names allowed across all discriminator choices).  But
      until we get to that point, it is worth asserting that variants
      are not present in places where we are not prepared to handle
      them: when exploding a type into a parameter list, we do not
      expect variants.  The qapi.py code is already checking this,
      via the older check_type() method; but someday we hope to get
      rid of that and move checking into QAPISchema*.check().  The
      two asserts added here make sure any refactoring still catches
      problems, and makes it locally obvious why we can iterate over
      only type.members without worrying about type.variants.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-2-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      29f6bd15
  2. 16 3月, 2016 3 次提交
  3. 07 3月, 2016 1 次提交
  4. 05 3月, 2016 5 次提交
    • E
      qapi: Drop useless 'data' member of unions · 48eb62a7
      Eric Blake 提交于
      We started moving away from the use of the 'void *data' member
      in the C union corresponding to a QAPI union back in commit
      544a3731; recent commits have gotten rid of other uses.  Now
      that it is completely unused, we can remove the member itself
      as well as the FIXME comment.  Update the testsuite to drop the
      negative test union-clash-data.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Reviewed-by: NDaniel P. Berrange <berrange@redhat.com>
      Message-Id: <1457021813-10704-11-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      48eb62a7
    • E
      qapi-visit: Expose visit_type_FOO_members() · 4d91e911
      Eric Blake 提交于
      Dan Berrange reported a case where he needs to work with a
      QCryptoBlockOptions union type using the OptsVisitor, but only
      visit one of the branches of that type (the discriminator is not
      visited directly, but learned externally).  When things were
      boxed, it was easy: just visit the variant directly, which took
      care of both allocating the variant and visiting its members, then
      store that pointer in the union type.  But now that things are
      unboxed, we need a way to visit the members without allocation,
      done by exposing visit_type_FOO_members() to the user.
      
      Before the patch, we had quite a bit of code associated with
      object_members_seen to make sure that a declaration of the helper
      was in scope before any use of the function.  But now that the
      helper is public and declared in the header, the .c file no
      longer needs to worry about topological sorting (the helper is
      always in scope), which leads to some nice cleanups.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1457021813-10704-4-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      4d91e911
    • E
      qapi: Rename 'fields' to 'members' in generated C code · c81200b0
      Eric Blake 提交于
      C types and JSON objects don't have fields, but members.  We
      shouldn't gratuitously invent terminology.  This patch is a
      strict renaming of static genarated functions, plus the naming
      of the dummy filler member for empty structs, before the next
      patch exposes some of that naming to the rest of the code base.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1457021813-10704-3-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      c81200b0
    • E
      qapi: Rename 'fields' to 'members' in generator · 14f00c6c
      Eric Blake 提交于
      C types and JSON objects don't have fields, but members.  We
      shouldn't gratuitously invent terminology.  This patch is a
      strict renaming of generator code internals (including testsuite
      comments), before later patches rename C interfaces.
      
      No change to generated code with this patch.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1457021813-10704-2-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      14f00c6c
    • D
      qmp-shell: fix pretty printing of JSON responses · e55250c6
      Daniel P. Berrange 提交于
      Pretty printing of JSON responses is important to be able to understand
      large responses from query commands in particular. Unfortunately this
      was broken during the addition of the verbose flag in
      
        commit 1ceca07e
        Author: John Snow <jsnow@redhat.com>
        Date:   Wed Apr 29 15:14:04 2015 -0400
      
          scripts: qmp-shell: Add verbose flag
      
      This is because that change turned the python data structure into a
      formatted JSON string before the pretty print was given it. So we're
      just pretty printing a string, which is a no-op.
      
      The original pretty printer would output python objects.
      
      (QEMU) query-chardev
      {   u'return': [   {   u'filename': u'vc',
                             u'frontend-open': False,
                             u'label': u'parallel0'},
                         {   u'filename': u'vc',
                             u'frontend-open': True,
                             u'label': u'serial0'},
                         {   u'filename': u'unix:/tmp/qemp,server',
                             u'frontend-open': True,
                             u'label': u'compat_monitor0'}]}
      
      This fixes the problem by switching to outputting pretty formatted JSON
      text instead. This has the added benefit that the pretty printed output
      is now valid JSON text. Due to the way the verbose flag was handled, the
      pretty printing now applies to the command sent, as well as its response:
      
      (QEMU) query-chardev
      {
          "execute": "query-chardev",
          "arguments": {}
      }
      {
          "return": [
              {
                  "frontend-open": false,
                  "label": "parallel0",
                  "filename": "vc"
              },
              {
                  "frontend-open": true,
                  "label": "serial0",
                  "filename": "vc"
              },
              {
                  "frontend-open": true,
                  "label": "compat_monitor0",
                  "filename": "unix:/tmp/qmp,server"
              }
          ]
      }
      Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
      Message-Id: <1456224706-1591-1-git-send-email-berrange@redhat.com>
      Tested-by: NKashyap Chamarthy <kchamart@redhat.com>
      Reviewed-by: NJohn Snow <jsnow@redhat.com>
      [Bonus fix: multiple -p now work]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      e55250c6
  5. 01 3月, 2016 7 次提交
  6. 24 2月, 2016 1 次提交
  7. 23 2月, 2016 4 次提交
  8. 19 2月, 2016 7 次提交
    • E
      qapi: Change visit_start_implicit_struct to visit_start_alternate · dbf11922
      Eric Blake 提交于
      After recent changes, the only remaining use of
      visit_start_implicit_struct() is for allocating the space needed
      when visiting an alternate.  Since the term 'implicit struct' is
      hard to explain, rename the function to its current usage.  While
      at it, we can merge the functionality of visit_get_next_type()
      into the same function, making it more like visit_start_struct().
      
      Generated code is now slightly smaller:
      
      | {
      |     Error *err = NULL;
      |
      |-    visit_start_implicit_struct(v, (void**) obj, sizeof(BlockdevRef), &err);
      |+    visit_start_alternate(v, name, (GenericAlternate **)obj, sizeof(**obj),
      |+                          true, &err);
      |     if (err) {
      |         goto out;
      |     }
      |-    visit_get_next_type(v, name, &(*obj)->type, true, &err);
      |-    if (err) {
      |-        goto out_obj;
      |-    }
      |     switch ((*obj)->type) {
      |     case QTYPE_QDICT:
      |         visit_start_struct(v, name, NULL, 0, &err);
      ...
      |     }
      |-out_obj:
      |-    visit_end_implicit_struct(v);
      |+    visit_end_alternate(v);
      | out:
      |     error_propagate(errp, err);
      | }
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-16-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      dbf11922
    • E
      qapi: Don't box branches of flat unions · 544a3731
      Eric Blake 提交于
      There's no reason to do two malloc's for a flat union; let's just
      inline the branch struct directly into the C union branch of the
      flat union.
      
      Surprisingly, fewer clients were actually using explicit references
      to the branch types in comparison to the number of flat unions
      thus modified.
      
      This lets us reduce the hack in qapi-types:gen_variants() added in
      the previous patch; we no longer need to distinguish between
      alternates and flat unions.
      
      The change to unboxed structs means that u.data (added in commit
      cee2dedb) is now coincident with random fields of each branch of
      the flat union, whereas beforehand it was only coincident with
      pointers (since all branches of a flat union have to be objects).
      Note that this was already the case for simple unions - but there
      we got lucky.  Remember, visit_start_union() blindly returns true
      for all visitors except for the dealloc visitor, where it returns
      the value !!obj->u.data, and that this result then controls
      whether to proceed with the visit to the variant.  Pre-patch,
      this meant that flat unions were testing whether the boxed pointer
      was still NULL, and thereby skipping visit_end_implicit_struct()
      and avoiding a NULL dereference if the pointer had not been
      allocated.  The same was true for simple unions where the current
      branch had pointer type, except there we bypassed visit_type_FOO().
      But for simple unions where the current branch had scalar type, the
      contents of that scalar meant that the decision to call
      visit_type_FOO() was data-dependent - the reason we got lucky there
      is that visit_type_FOO() for all scalar types in the dealloc visitor
      is a no-op (only the pointer variants had anything to free), so it
      did not matter whether the dealloc visit was skipped.  But with this
      patch, we would risk leaking memory if we could skip a call to
      visit_type_FOO_fields() based solely on a data-dependent decision.
      
      But notice: in the dealloc visitor, visit_type_FOO() already handles
      a NULL obj - it was only the visit_type_implicit_FOO() that was
      failing to check for NULL. And now that we have refactored things to
      have the branch be part of the parent struct, we no longer have a
      separate pointer that can be NULL in the first place.  So we can just
      delete the call to visit_start_union() altogether, and blindly visit
      the branch type; there is no change in behavior except to the dealloc
      visitor, where we now unconditionally visit the branch, but where that
      visit is now always safe (for a flat union, we can no longer
      dereference NULL, and for a simple union, visit_type_FOO() was already
      safely handling NULL on pointer types).
      
      Unfortunately, simple unions are not as easy to switch to unboxed
      layout; because we are special-casing the hidden implicit type with
      a single 'data' member, we really DO need to keep calling another
      layer of visit_start_struct(), with a second malloc; although there
      are some cleanups planned for simple unions in later patches.
      
      visit_start_union() and gen_visit_implicit_struct() are now unused.
      Drop them.
      
      Note that after this patch, the only remaining use of
      visit_start_implicit_struct() is for alternate types; the next patch
      will do further cleanup based on that fact.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-14-git-send-email-eblake@redhat.com>
      [Dead code deletion squashed in, commit message updated accordingly]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      544a3731
    • E
      qapi: Don't box struct branch of alternate · becceedc
      Eric Blake 提交于
      There's no reason to do two malloc's for an alternate type visiting
      a QAPI struct; let's just inline the struct directly as the C union
      branch of the struct.
      
      Surprisingly, no clients were actually using the struct member prior
      to this patch outside of the testsuite; an earlier patch in the series
      added some testsuite coverage to make the effect of this patch more
      obvious.
      
      In qapi.py, c_type() gains a new is_unboxed flag to control when we
      are emitting a C struct unboxed within the context of an outer
      struct (different from our other two modes of usage with no flags
      for normal local variable declarations, and with is_param for adding
      'const' in a parameter list).  I don't know if there is any more
      pythonic way of collapsing the two flags into a single parameter,
      as we never have a caller setting both flags at once.
      
      Ultimately, we want to also unbox branches for QAPI unions, but as
      that touches a lot more client code, it is better as separate
      patches.  But since unions and alternates share gen_variants(), I
      had to hack in a way to test if we are visiting an alternate type
      for setting the is_unboxed flag: look for a non-object branch.
      This works because alternates have at least two branches, with at
      most one object branch, while unions have only object branches.
      The hack will go away in a later patch.
      
      The generated code difference to qapi-types.h is relatively small:
      
      | struct BlockdevRef {
      |     QType type;
      |     union { /* union tag is @type */
      |         void *data;
      |-        BlockdevOptions *definition;
      |+        BlockdevOptions definition;
      |         char *reference;
      |     } u;
      | };
      
      The corresponding spot in qapi-visit.c calls visit_type_FOO(), which
      first calls visit_start_struct() to allocate or deallocate the member
      and handle a layer of {} from the JSON stream, then visits the
      members.  To peel off the indirection and the memory management that
      comes with it, we inline this call, then suppress allocation /
      deallocation by passing NULL to visit_start_struct(), and adjust the
      member visit:
      
      |     switch ((*obj)->type) {
      |     case QTYPE_QDICT:
      |-        visit_type_BlockdevOptions(v, name, &(*obj)->u.definition, &err);
      |+        visit_start_struct(v, name, NULL, 0, &err);
      |+        if (err) {
      |+            break;
      |+        }
      |+        visit_type_BlockdevOptions_fields(v, &(*obj)->u.definition, &err);
      |+        error_propagate(errp, err);
      |+        err = NULL;
      |+        visit_end_struct(v, &err);
      |         break;
      |     case QTYPE_QSTRING:
      |         visit_type_str(v, name, &(*obj)->u.reference, &err);
      
      The visit of non-object fields is unchanged.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-13-git-send-email-eblake@redhat.com>
      [Commit message tweaked]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      becceedc
    • E
      qapi-visit: Use common idiom in gen_visit_fields_decl() · 2208d649
      Eric Blake 提交于
      We have several instances of methods that do an early exit if
      output is not needed, then log that output is being generated,
      and finally produce the output; see qapi-types.py:gen_object()
      and qapi-visit.py:gen_visit_implicit_struct().  The odd man
      out was gen_visit_fields_decl(); rearrange it to be more like
      the others.  No semantic change or difference to generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-12-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      2208d649
    • E
      qapi: Emit structs used as variants in topological order · 1de5d4ca
      Eric Blake 提交于
      Right now, we emit the branches of union types as a boxed pointer,
      and it suffices to have a forward declaration of the type.  However,
      a future patch will swap things to directly use the branch type,
      instead of hiding it behind a pointer.  For this to work, the
      compiler needs the full definition of the type, not just a forward
      declaration, prior to the union that is including the branch type.
      This patch just adds topological sorting to hoist all types
      mentioned in a branch of a union to be fully declared before the
      union itself.  The sort is always possible, because we do not
      allow circular union types that include themselves as a direct
      branch (it is, however, still possible to include a branch type
      that itself has a pointer to the union, for a type that can
      indirectly recursively nest itself - that remains safe, because
      that the member of the branch type will remain a pointer, and the
      QMP representation of such a type adds another {} for each recurring
      layer of the union type).
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-11-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      1de5d4ca
    • E
      qapi: Adjust layout of FooList types · e65d89bf
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-10-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      e65d89bf
    • E
      qapi-visit: Less indirection in visit_type_Foo_fields() · 65551903
      Eric Blake 提交于
      We were passing 'Foo **obj' to the internal helper function, but
      all uses within the helper were via reads of '*obj'.  Refactor
      things to pass one less level of indirection, by having the
      callers dereference before calling.
      
      For an example of the generated code change:
      
      |-static void visit_type_BalloonInfo_fields(Visitor *v, BalloonInfo **obj, Error **errp)
      |+static void visit_type_BalloonInfo_fields(Visitor *v, BalloonInfo *obj, Error **errp)
      | {
      |     Error *err = NULL;
      |
      |-    visit_type_int(v, "actual", &(*obj)->actual, &err);
      |+    visit_type_int(v, "actual", &obj->actual, &err);
      |     error_propagate(errp, err);
      | }
      |
      |@@ -261,7 +261,7 @@ void visit_type_BalloonInfo(Visitor *v,
      |     if (!*obj) {
      |         goto out_obj;
      |     }
      |-    visit_type_BalloonInfo_fields(v, obj, &err);
      |+    visit_type_BalloonInfo_fields(v, *obj, &err);
      | out_obj:
      
      The refactoring will also make it easier to reuse the helpers in
      a future patch when implicit structs are stored directly in the
      parent struct rather than boxed through a pointer.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-9-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      65551903