Do not use bound MethodHandle in DataObjectCodecContext 26/81826/2
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 30 Apr 2019 13:08:30 +0000 (15:08 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 30 Apr 2019 13:14:22 +0000 (15:14 +0200)
Binding the MethodHandle means we are actually creating two
methodhandles, which is wasteful. Add a dummy CodecDataObject
constructor argument, unifying constructor signatures and allowing
us to use a single methodhandle, passing 'this' at the single
call site.

JIRA: MDSAL-444
Change-Id: Idd94638eb42d219b7370463d91dad3d00409bd5e
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
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java

index 3cf75fbf70b01a84f8217c0423248809c978e382..d94c3f7c28604fff0cdc60b7aa2029cd5b606944 100644 (file)
@@ -44,7 +44,7 @@ public abstract class AugmentableCodecDataObject<T extends DataObject & Augmenta
 
     protected AugmentableCodecDataObject(final DataObjectCodecContext<T, ?> context,
             final NormalizedNodeContainer<?, ?, ?> data) {
-        super(data);
+        super(context, data);
         this.context = requireNonNull(context, "Context must not be null");
     }
 
index cec788f3fdc050209d3b5bde997a23a86347ec87..b48bde535a3943eaa37bfb3e92921ee72f902477 100644 (file)
@@ -36,7 +36,7 @@ public abstract class CodecDataObject<T extends DataObject> implements DataObjec
 
     private volatile Integer cachedHashcode = null;
 
-    protected CodecDataObject(final NormalizedNodeContainer<?, ?, ?> data) {
+    protected CodecDataObject(final DataObjectCodecContext<T, ?> context, final NormalizedNodeContainer<?, ?, ?> data) {
         this.data = requireNonNull(data, "Data must not be null");
     }
 
index 6505b3afdb0a3a47deb017f4707e0928165c85c3..92f76510c003af53c66a631720d809d1b2319f47 100644 (file)
@@ -78,12 +78,9 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
     }
 
     private static final Logger LOG = LoggerFactory.getLogger(DataObjectCodecContext.class);
-    private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class, NormalizedNodeContainer.class);
-    private static final MethodType AUGMENTABLE_CONSTRUCTOR_TYPE = MethodType.methodType(void.class,
+    private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class,
         DataObjectCodecContext.class, NormalizedNodeContainer.class);
     private static final MethodType DATAOBJECT_TYPE = MethodType.methodType(DataObject.class,
-        NormalizedNodeContainer.class);
-    private static final MethodType AUGMENTABLE_DATAOBJECT_TYPE = MethodType.methodType(DataObject.class,
         DataObjectCodecContext.class, NormalizedNodeContainer.class);
     private static final Comparator<Method> METHOD_BY_ALPHABET = Comparator.comparing(Method::getName);
     private static final Augmentations EMPTY_AUGMENTATIONS = new Augmentations(ImmutableMap.of(), ImmutableMap.of());
@@ -166,32 +163,25 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
         this.byBindingArgClass = ImmutableMap.copyOf(byBindingArgClassBuilder);
 
         final Class<? extends CodecDataObject<?>> generatedClass;
-        final MethodType ctorType;
         if (Augmentable.class.isAssignableFrom(bindingClass)) {
             this.possibleAugmentations = factory().getRuntimeContext().getAvailableAugmentationTypes(getSchema());
             generatedClass = CodecDataObjectGenerator.generateAugmentable(prototype.getFactory().getLoader(),
                 bindingClass, propBuilder.build(), keyMethod);
-            ctorType = AUGMENTABLE_CONSTRUCTOR_TYPE;
         } else {
             this.possibleAugmentations = ImmutableMap.of();
             generatedClass = CodecDataObjectGenerator.generate(prototype.getFactory().getLoader(), bindingClass,
                 propBuilder.build(), keyMethod);
-            ctorType = CONSTRUCTOR_TYPE;
         }
         reloadAllAugmentations();
 
         final MethodHandle ctor;
         try {
-            ctor = MethodHandles.publicLookup().findConstructor(generatedClass, ctorType);
+            ctor = MethodHandles.publicLookup().findConstructor(generatedClass, CONSTRUCTOR_TYPE);
         } catch (NoSuchMethodException | IllegalAccessException e) {
             throw new LinkageError("Failed to find contructor for class " + generatedClass, e);
         }
 
-        if (Augmentable.class.isAssignableFrom(bindingClass)) {
-            proxyConstructor = ctor.asType(AUGMENTABLE_DATAOBJECT_TYPE).bindTo(this);
-        } else {
-            proxyConstructor = ctor.asType(DATAOBJECT_TYPE);
-        }
+        proxyConstructor = ctor.asType(DATAOBJECT_TYPE);
     }
 
     // This method could be synchronized, but that would mean that concurrent attempts to load an invalid augmentation
@@ -519,7 +509,7 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
     @SuppressWarnings("checkstyle:illegalCatch")
     protected final D createBindingProxy(final NormalizedNodeContainer<?, ?, ?> node) {
         try {
-            return (D) proxyConstructor.invokeExact(node);
+            return (D) proxyConstructor.invokeExact(this, node);
         } catch (final Throwable e) {
             Throwables.throwIfUnchecked(e);
             throw new IllegalStateException(e);