X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=inline;f=binding%2Fmdsal-binding-dom-codec%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fdom%2Fcodec%2Fimpl%2FCodecDataObjectGenerator.java;h=19f31386fa760760d15b3d1af6b8f6dcf7ab37c7;hb=refs%2Fchanges%2F46%2F109746%2F2;hp=03a9bacfc56fa6e29336889f95b7f41465686182;hpb=d793698267d9f4cb8f766a51bc77206c582aa785;p=mdsal.git diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java index 03a9bacfc5..19f31386fa 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java @@ -10,56 +10,43 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static com.google.common.base.Verify.verify; import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; -import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.THIS; +import static net.bytebuddy.implementation.bytecode.member.MethodVariableAccess.loadThis; import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.getField; import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.invokeMethod; import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.putField; -import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.VarHandle; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.Optional; import net.bytebuddy.ByteBuddy; import net.bytebuddy.description.field.FieldDescription; -import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDefinition; import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.description.type.TypeDescription.ForLoadedType; import net.bytebuddy.description.type.TypeDescription.Generic; import net.bytebuddy.dynamic.DynamicType.Builder; import net.bytebuddy.dynamic.scaffold.InstrumentedType; import net.bytebuddy.implementation.Implementation; -import net.bytebuddy.implementation.Implementation.Context; -import net.bytebuddy.implementation.bytecode.Addition; import net.bytebuddy.implementation.bytecode.ByteCodeAppender; -import net.bytebuddy.implementation.bytecode.Multiplication; import net.bytebuddy.implementation.bytecode.StackManipulation; import net.bytebuddy.implementation.bytecode.assign.TypeCasting; import net.bytebuddy.implementation.bytecode.constant.ClassConstant; -import net.bytebuddy.implementation.bytecode.constant.IntegerConstant; import net.bytebuddy.implementation.bytecode.constant.TextConstant; import net.bytebuddy.implementation.bytecode.member.MethodReturn; import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess; -import net.bytebuddy.jar.asm.Label; -import net.bytebuddy.jar.asm.MethodVisitor; import net.bytebuddy.jar.asm.Opcodes; import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.mdsal.binding.dom.codec.impl.ClassGeneratorBridge.CodecContextSupplierProvider; import org.opendaylight.mdsal.binding.dom.codec.impl.ClassGeneratorBridge.LocalNameProvider; -import org.opendaylight.mdsal.binding.dom.codec.impl.ClassGeneratorBridge.NodeContextSupplierProvider; -import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader; -import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.ClassGenerator; -import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.GeneratorResult; -import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.mdsal.binding.loader.BindingClassLoader; +import org.opendaylight.mdsal.binding.loader.BindingClassLoader.ClassGenerator; +import org.opendaylight.mdsal.binding.loader.BindingClassLoader.GeneratorResult; +import org.opendaylight.yangtools.yang.binding.contract.Naming; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,9 +55,11 @@ import org.slf4j.LoggerFactory; * *

* Code generation here is probably more involved than usual mainly due to the fact we *really* want to express the - * strong connection between a generated class and BindingCodecContext in terms of a true constant, which boils down to - * {@code private static final NodeContextSupplier NCS}. Having such constants provides significant boost to JITs - * ability to optimize code -- especially with inlining and constant propagation. + * strong connection between a generated class to the extent possible. In most cases (grouping-generated types) this + * involves one level of indirection, which is a safe approach. If we are dealing with a type generated outside of a + * grouping statement, though, we are guaranteed instantiation-invariance and hence can hard-wire to a runtime-constant + * {@link CodecContextSupplier} -- which provides significant boost to JITs ability to optimize code -- especially with + * inlining and constant propagation. * *

* The accessor mapping performance is critical due to users typically not taking care of storing the results acquired @@ -92,7 +81,7 @@ import org.slf4j.LoggerFactory; * private static final VarHandle getBar$$$V; * private volatile Object getBar; * - * public Foo$$$codecImpl(NormalizedNodeContainer data) { + * public Foo$$$codecImpl(DistinctNodeContainer data) { * super(data); * } * @@ -106,8 +95,10 @@ import org.slf4j.LoggerFactory; * This strategy minimizes the bytecode footprint and follows the generally good idea of keeping common logic in a * single place in a maintainable form. The glue code is extremely light (~6 instructions), which is beneficial on both * sides of invocation: - * - generated method can readily be inlined into the caller - * - it forms a call site into which codeMember() can be inlined with VarHandle being constant + *

* *

* The second point is important here, as it allows the invocation logic around VarHandle to completely disappear, @@ -128,27 +119,27 @@ import org.slf4j.LoggerFactory; *

* The sticky point here is the NodeContextSupplier, as it is a heap object which cannot normally be looked up from the * static context in which the static class initializer operates -- so we need perform some sort of a trick here. - * Eventhough ByteBuddy provides facilities for bridging references to type fields, those facilities operate on volatile - * fields -- hence they do not quite work for us. + * Even though ByteBuddy provides facilities for bridging references to type fields, those facilities operate on + * volatile fields -- hence they do not quite work for us. * *

* Another alternative, which we used in Javassist-generated DataObjectSerializers, is to muck with the static field - * using reflection -- which works, but requires redefinition of Field.modifiers, which is something Java 9 complains + * using reflection -- which works, but requires redefinition of Field.modifiers, which is something Java 9+ complains * about quite noisily. * *

* We take a different approach here, which takes advantage of the fact we are in control of both code generation (here) - * and class loading (in {@link CodecClassLoader}). The process is performed in four steps: + * and class loading (in {@link BindingClassLoader}). The process is performed in four steps: *