Generate DataObject codec implementation 54/81654/30
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 15 Apr 2019 11:50:58 +0000 (13:50 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 24 Apr 2019 08:59:27 +0000 (10:59 +0200)
commit0de2fd0fa7ad26db607e9703bcc8296bed9073a5
tree2a9044a66670c9aa5dc390949ac84adc6ffce220
parent3106784dac024576f56095b2aff7ef715538da08
Generate DataObject codec implementation

With the advent of CodecClassLoader we can safely instantiate
codec-specific implementations of binding interfaces instead
of relying on dynamic proxies.

This has several advantages:
- we do not generate a proxy class in public space, hence our mess
  will undergo normal GC rules
- generated code is a normal final class, hence we can inherit
  method implementations from interfaces and subclasses
- for each instance, we do not require a proxy and an invocation
  handler, so we instantiate only one object
- there is no reflection in the invocation path, hence JIT has
  full (and direct) visibility and can perform all of its magic

This patch DataObject support to use this approach, with
(Augmentable)CodecDataObject forming the base class.

The result is a bit more complex than the OpaqueObject case, but
also offers several advantages over the LazyDataObject approach
it replaces:
- nonnullFoo() methods are inherited from the binding interface,
  hence the presence of binding-dom-codec does not prevent CHA
  analysis from concluding there is only a single implementation
  -- thus allowing rapid devirtualization. This also means that
  DataContainerCodecContext no longer needs to track those methods
  or do anything.
- Augmentable interfaces are supported by a separate superclass,
  which implements AugmentationHolder, resulting in augmentations
  field being held only if the binding interface is augmentable
- getters and Identifiable.key() values are held in dedicated
  fields of the generated object. This leads to them being properly
  cached in all cases, hence invoking a getter after an
  equals/hashCode() operation will reuse the cached value if it
  was populated
- since we are using plain fields, data access does not involve
  walking a ConcurrentHashMap, further improving performance

The amount of generated code is kept at a minimum -- methods
just invoke CodecDataObject's method, passing it the ARFU
corresponding to the field as a constant -- and rely on the
compiler to inline the call, so that constants are propagated.

JIRA: MDSAL-442
Change-Id: I6acc34ab6b2cc62fd26dc34275259494ac4541fb
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentableCodecDataObject.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectCustomizer.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/KeyedListNodeCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyDataObject.java [deleted file]
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListNodeCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NodeCodecContext.java