/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.runtime;

import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGetter;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createSetter;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldCount;
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldName;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.lookup.MethodHandleFactory.stripName;
import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
import static jdk.nashorn.internal.runtime.JSType.getNumberOfAccessorTypes;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.SwitchPoint;
import java.util.function.Supplier;
import java.util.logging.Level;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.objects.Global;

/**
 * An AccessorProperty is the most generic property type. An AccessorProperty is
 * represented as fields in a ScriptObject class.
 */
public class AccessorProperty extends Property {
    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();

    private static final MethodHandle REPLACE_MAP   = findOwnMH_S("replaceMap", Object.class, Object.class, PropertyMap.class);
    private static final MethodHandle INVALIDATE_SP = findOwnMH_S("invalidateSwitchPoint", Object.class, AccessorProperty.class, Object.class);

    private static final int NOOF_TYPES = getNumberOfAccessorTypes();
    private static final long serialVersionUID = 3371720170182154920L;

    /**
     * Properties in different maps for the same structure class will share their field getters and setters. This could
     * be further extended to other method handles that are looked up in the AccessorProperty constructor, but right now
     * these are the most frequently retrieved ones, and lookup of method handle natives only registers in the profiler
     * for them.
     */
    private static ClassValue<Accessors> GETTERS_SETTERS = new ClassValue<Accessors>() {
        @Override
        protected Accessors computeValue(final Class<?> structure) {
            return new Accessors(structure);
        }
    };

    private static class Accessors {
        final MethodHandle[] objectGetters;
        final MethodHandle[] objectSetters;
        final MethodHandle[] primitiveGetters;
        final MethodHandle[] primitiveSetters;

        /**
         * Normal
         * @param structure
         */
        Accessors(final Class<?> structure) {
            final int fieldCount = getFieldCount(structure);
            objectGetters    = new MethodHandle[fieldCount];
            objectSetters    = new MethodHandle[fieldCount];
            primitiveGetters = new MethodHandle[fieldCount];
            primitiveSetters = new MethodHandle[fieldCount];

            for (int i = 0; i < fieldCount; i++) {
                final String fieldName = getFieldName(i, Type.OBJECT);
                final Class<?> typeClass = Type.OBJECT.getTypeClass();
                objectGetters[i] = MH.asType(MH.getter(LOOKUP, structure, fieldName, typeClass), Lookup.GET_OBJECT_TYPE);
                objectSetters[i] = MH.asType(MH.setter(LOOKUP, structure, fieldName, typeClass), Lookup.SET_OBJECT_TYPE);
            }

            if (!StructureLoader.isSingleFieldStructure(structure.getName())) {
                for (int i = 0; i < fieldCount; i++) {
                    final String fieldNamePrimitive = getFieldName(i, PRIMITIVE_FIELD_TYPE);
                    final Class<?> typeClass = PRIMITIVE_FIELD_TYPE.getTypeClass();
                    primitiveGetters[i] = MH.asType(MH.getter(LOOKUP, structure, fieldNamePrimitive, typeClass), Lookup.GET_PRIMITIVE_TYPE);
                    primitiveSetters[i] = MH.asType(MH.setter(LOOKUP, structure, fieldNamePrimitive, typeClass), Lookup.SET_PRIMITIVE_TYPE);
                }
            }
        }
    }

    /**
     * Property getter cache
     *   Note that we can't do the same simple caching for optimistic getters,
     *   due to the fact that they are bound to a program point, which will
     *   produce different boun method handles wrapping the same access mechanism
     *   depending on callsite
     */
    private transient MethodHandle[] GETTER_CACHE = new MethodHandle[NOOF_TYPES];

    /**
     * Create a new accessor property. Factory method used by nasgen generated code.
     *
     * @param key           {@link Property} key.
     * @param propertyFlags {@link Property} flags.
     * @param getter        {@link Property} get accessor method.
     * @param setter        {@link Property} set accessor method.
     *
     * @return  New {@link AccessorProperty} created.
     */
    public static AccessorProperty create(final String key, final int propertyFlags, final MethodHandle getter, final MethodHandle setter) {
        return new AccessorProperty(key, propertyFlags, -1, getter, setter);
    }

    /** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
    transient MethodHandle primitiveGetter;

    /** Seed setter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
    transient MethodHandle primitiveSetter;

    /** Seed getter for the Object version of this field */
    transient MethodHandle objectGetter;

    /** Seed setter for the Object version of this field */
    transient MethodHandle objectSetter;

    /**
     * Delegate constructor for bound properties. This is used for properties created by
     * {@link ScriptRuntime#mergeScope} and the Nashorn {@code Object.bindProperties} method.
     * The former is used to add a script's defined globals to the current global scope while
     * still storing them in a JO-prefixed ScriptObject class.
     *
     * <p>All properties created by this constructor have the {@link #IS_BOUND} flag set.</p>
     *
     * @param property  accessor property to rebind
     * @param delegate  delegate object to rebind receiver to
     */
    AccessorProperty(final AccessorProperty property, final Object delegate) {
        super(property, property.getFlags() | IS_BOUND);

        this.primitiveGetter = bindTo(property.primitiveGetter, delegate);
        this.primitiveSetter = bindTo(property.primitiveSetter, delegate);
        this.objectGetter    = bindTo(property.objectGetter, delegate);
        this.objectSetter    = bindTo(property.objectSetter, delegate);
        property.GETTER_CACHE = new MethodHandle[NOOF_TYPES];
        // Properties created this way are bound to a delegate
        setType(property.getType());
    }

    /**
     * SPILL PROPERTY or USER ACCESSOR PROPERTY abstract constructor
     *
     * Constructor for spill properties. Array getters and setters will be created on demand.
     *
     * @param key    the property key
     * @param flags  the property flags
     * @param slot   spill slot
     * @param primitiveGetter primitive getter
     * @param primitiveSetter primitive setter
     * @param objectGetter    object getter
     * @param objectSetter    object setter
     */
    protected AccessorProperty(
            final String key,
            final int flags,
            final int slot,
            final MethodHandle primitiveGetter,
            final MethodHandle primitiveSetter,
            final MethodHandle objectGetter,
            final MethodHandle objectSetter) {
        super(key, flags, slot);
        assert getClass() != AccessorProperty.class;
        this.primitiveGetter = primitiveGetter;
        this.primitiveSetter = primitiveSetter;
        this.objectGetter    = objectGetter;
        this.objectSetter    = objectSetter;
        initializeType();
    }

    /**
     * NASGEN constructor
     *
     * Constructor. Similar to the constructor with both primitive getters and setters, the difference
     * here being that only one getter and setter (setter is optional for non writable fields) is given
     * to the constructor, and the rest are created from those. Used e.g. by Nasgen classes
     *
     * @param key    the property key
     * @param flags  the property flags
     * @param slot   the property field number or spill slot
     * @param getter the property getter
     * @param setter the property setter or null if non writable, non configurable
     */
    private AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) {
        super(key, flags | IS_BUILTIN | DUAL_FIELDS | (getter.type().returnType().isPrimitive() ? IS_NASGEN_PRIMITIVE : 0), slot);
        assert !isSpill();

        // we don't need to prep the setters these will never be invalidated as this is a nasgen
        // or known type getter/setter. No invalidations will take place

        final Class<?> getterType = getter.type().returnType();
        final Class<?> setterType = setter == null ? null : setter.type().parameterType(1);

        assert setterType == null || setterType == getterType;

        if (getterType == int.class) {
            primitiveGetter = MH.asType(getter, Lookup.GET_PRIMITIVE_TYPE);
            primitiveSetter = setter == null ? null : MH.asType(setter, Lookup.SET_PRIMITIVE_TYPE);
        } else if (getterType == double.class) {
            primitiveGetter = MH.asType(MH.filterReturnValue(getter, ObjectClassGenerator.PACK_DOUBLE), Lookup.GET_PRIMITIVE_TYPE);
            primitiveSetter = setter == null ? null : MH.asType(MH.filterArguments(setter, 1, ObjectClassGenerator.UNPACK_DOUBLE), Lookup.SET_PRIMITIVE_TYPE);
        } else {
            primitiveGetter = primitiveSetter = null;
        }

        assert primitiveGetter == null || primitiveGetter.type() == Lookup.GET_PRIMITIVE_TYPE : primitiveGetter + "!=" + Lookup.GET_PRIMITIVE_TYPE;
        assert primitiveSetter == null || primitiveSetter.type() == Lookup.SET_PRIMITIVE_TYPE : primitiveSetter;

        objectGetter  = getter.type() != Lookup.GET_OBJECT_TYPE ? MH.asType(getter, Lookup.GET_OBJECT_TYPE) : getter;
        objectSetter  = setter != null && setter.type() != Lookup.SET_OBJECT_TYPE ? MH.asType(setter, Lookup.SET_OBJECT_TYPE) : setter;

        setType(getterType);
    }

    /**
     * Normal ACCESS PROPERTY constructor given a structure class.
     * Constructor for dual field AccessorPropertys.
     *
     * @param key              property key
     * @param flags            property flags
     * @param structure        structure for objects associated with this property
     * @param slot             property field number or spill slot
     */
    public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot) {
        super(key, flags, slot);

        initGetterSetter(structure);
        initializeType();
    }

    private void initGetterSetter(final Class<?> structure) {
        final int slot = getSlot();
        /*
         * primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also
         * works in dual field mode, it only means that the property never has a primitive
         * representation.
         */

        if (isParameter() && hasArguments()) {
            //parameters are always stored in an object array, which may or may not be a good idea
            final MethodHandle arguments = MH.getter(LOOKUP, structure, "arguments", ScriptObject.class);
            objectGetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.GET_OBJECT_TYPE);
            objectSetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.SET_OBJECT_TYPE);
            primitiveGetter = null;
            primitiveSetter = null;
        } else {
            final Accessors gs = GETTERS_SETTERS.get(structure);
            objectGetter    = gs.objectGetters[slot];
            primitiveGetter = gs.primitiveGetters[slot];
            objectSetter    = gs.objectSetters[slot];
            primitiveSetter = gs.primitiveSetters[slot];
        }

        // Always use dual fields except for single field structures
        assert hasDualFields() != StructureLoader.isSingleFieldStructure(structure.getName());
    }

    /**
     * Constructor
     *
     * @param key          key
     * @param flags        flags
     * @param slot         field slot index
     * @param owner        owner of property
     * @param initialValue initial value to which the property can be set
     */
    protected AccessorProperty(final String key, final int flags, final int slot, final ScriptObject owner, final Object initialValue) {
        this(key, flags, owner.getClass(), slot);
        setInitialValue(owner, initialValue);
    }

    /**
     * Normal access property constructor that overrides the type
     * Override the initial type. Used for Object Literals
     *
     * @param key          key
     * @param flags        flags
     * @param structure    structure to JO subclass
     * @param slot         field slot index
     * @param initialType  initial type of the property
     */
    public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot, final Class<?> initialType) {
        this(key, flags, structure, slot);
        setType(hasDualFields() ? initialType : Object.class);
    }

    /**
     * Copy constructor that may change type and in that case clear the cache. Important to do that before
     * type change or getters will be created already stale.
     *
     * @param property property
     * @param newType  new type
     */
    protected AccessorProperty(final AccessorProperty property, final Class<?> newType) {
        super(property, property.getFlags());

        this.GETTER_CACHE    = newType != property.getLocalType() ? new MethodHandle[NOOF_TYPES] : property.GETTER_CACHE;
        this.primitiveGetter = property.primitiveGetter;
        this.primitiveSetter = property.primitiveSetter;
        this.objectGetter    = property.objectGetter;
        this.objectSetter    = property.objectSetter;

        setType(newType);
    }

    /**
     * COPY constructor
     *
     * @param property  source property
     */
    protected AccessorProperty(final AccessorProperty property) {
        this(property, property.getLocalType());
    }

    /**
     * Set initial value of a script object's property
     * @param owner        owner
     * @param initialValue initial value
     */
    protected final void setInitialValue(final ScriptObject owner, final Object initialValue) {
        setType(hasDualFields() ? JSType.unboxedFieldType(initialValue) : Object.class);
        if (initialValue instanceof Integer) {
            invokeSetter(owner, ((Integer)initialValue).intValue());
        } else if (initialValue instanceof Long) {
            invokeSetter(owner, ((Long)initialValue).longValue());
        } else if (initialValue instanceof Double) {
            invokeSetter(owner, ((Double)initialValue).doubleValue());
        } else {
            invokeSetter(owner, initialValue);
        }
    }

    /**
     * Initialize the type of a property
     */
    protected final void initializeType() {
        setType(!hasDualFields() ? Object.class : null);
    }

    private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        // Restore getters array
        GETTER_CACHE = new MethodHandle[NOOF_TYPES];
    }

    private static MethodHandle bindTo(final MethodHandle mh, final Object receiver) {
        if (mh == null) {
            return null;
        }

        return MH.dropArguments(MH.bindTo(mh, receiver), 0, Object.class);
    }

    @Override
    public Property copy() {
        return new AccessorProperty(this);
    }

    @Override
    public Property copy(final Class<?> newType) {
        return new AccessorProperty(this, newType);
    }

    @Override
    public int getIntValue(final ScriptObject self, final ScriptObject owner) {
        try {
            return (int)getGetter(int.class).invokeExact((Object)self);
        } catch (final Error | RuntimeException e) {
            throw e;
        } catch (final Throwable e) {
            throw new RuntimeException(e);
        }
     }

     @Override
     public double getDoubleValue(final ScriptObject self, final ScriptObject owner) {
        try {
            return (double)getGetter(double.class).invokeExact((Object)self);
        } catch (final Error | RuntimeException e) {
            throw e;
        } catch (final Throwable e) {
            throw new RuntimeException(e);
        }
    }

     @Override
     public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
        try {
            return getGetter(Object.class).invokeExact((Object)self);
        } catch (final Error | RuntimeException e) {
            throw e;
        } catch (final Throwable e) {
            throw new RuntimeException(e);
        }
    }

     /**
      * Invoke setter for this property with a value
      * @param self  owner
      * @param value value
      */
    protected final void invokeSetter(final ScriptObject self, final int value) {
        try {
            getSetter(int.class, self.getMap()).invokeExact((Object)self, value);
        } catch (final Error | RuntimeException e) {
            throw e;
        } catch (final Throwable e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Invoke setter for this property with a value
     * @param self  owner
     * @param value value
     */
    protected final void invokeSetter(final ScriptObject self, final double value) {
        try {
            getSetter(double.class, self.getMap()).invokeExact((Object)self, value);
        } catch (final Error | RuntimeException e) {
            throw e;
        } catch (final Throwable e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Invoke setter for this property with a value
     * @param self  owner
     * @param value value
     */
    protected final void invokeSetter(final ScriptObject self, final Object value) {
        try {
            getSetter(Object.class, self.getMap()).invokeExact((Object)self, value);
        } catch (final Error | RuntimeException e) {
            throw e;
        } catch (final Throwable e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void setValue(final ScriptObject self, final ScriptObject owner, final int value, final boolean strict)  {
        assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
        invokeSetter(self, value);
    }

    @Override
    public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict)  {
        assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
        invokeSetter(self, value);
    }

    @Override
    public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict)  {
        //this is sometimes used for bootstrapping, hence no assert. ugly.
        invokeSetter(self, value);
    }

    @Override
    void initMethodHandles(final Class<?> structure) {
        // sanity check for structure class
        if (!ScriptObject.class.isAssignableFrom(structure) || !StructureLoader.isStructureClass(structure.getName())) {
            throw new IllegalArgumentException();
        }
        // this method is overridden in SpillProperty
        assert !isSpill();
        initGetterSetter(structure);
    }

    @Override
    public MethodHandle getGetter(final Class<?> type) {
        final int i = getAccessorTypeIndex(type);

        assert type == int.class ||
                type == double.class ||
                type == Object.class :
                "invalid getter type " + type + " for " + getKey();

        checkUndeclared();

        //all this does is add a return value filter for object fields only
        final MethodHandle[] getterCache = GETTER_CACHE;
        final MethodHandle cachedGetter = getterCache[i];
        final MethodHandle getter;
        if (cachedGetter != null) {
            getter = cachedGetter;
        } else {
            getter = debug(
                createGetter(
                    getLocalType(),
                    type,
                    primitiveGetter,
                    objectGetter,
                    INVALID_PROGRAM_POINT),
                getLocalType(),
                type,
                "get");
            getterCache[i] = getter;
       }
       assert getter.type().returnType() == type && getter.type().parameterType(0) == Object.class;
       return getter;
    }

    @Override
    public MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint) {
        // nasgen generated primitive fields like Math.PI have only one known unchangeable primitive type
        if (objectGetter == null) {
            return getOptimisticPrimitiveGetter(type, programPoint);
        }

        checkUndeclared();

        return debug(
            createGetter(
                getLocalType(),
                type,
                primitiveGetter,
                objectGetter,
                programPoint),
            getLocalType(),
            type,
            "get");
    }

    private MethodHandle getOptimisticPrimitiveGetter(final Class<?> type, final int programPoint) {
        final MethodHandle g = getGetter(getLocalType());
        return MH.asType(OptimisticReturnFilters.filterOptimisticReturnValue(g, type, programPoint), g.type().changeReturnType(type));
    }

    private Property getWiderProperty(final Class<?> type) {
        return copy(type); //invalidate cache of new property
    }

    private PropertyMap getWiderMap(final PropertyMap oldMap, final Property newProperty) {
        final PropertyMap newMap = oldMap.replaceProperty(this, newProperty);
        assert oldMap.size() > 0;
        assert newMap.size() == oldMap.size();
        return newMap;
    }

    private void checkUndeclared() {
        if ((getFlags() & NEEDS_DECLARATION) != 0) {
            // a lexically defined variable that hasn't seen its declaration - throw ReferenceError
            throw ECMAErrors.referenceError("not.defined", getKey());
        }
    }

    // the final three arguments are for debug printout purposes only
    @SuppressWarnings("unused")
    private static Object replaceMap(final Object sobj, final PropertyMap newMap) {
        ((ScriptObject)sobj).setMap(newMap);
        return sobj;
    }

    @SuppressWarnings("unused")
    private static Object invalidateSwitchPoint(final AccessorProperty property, final Object obj) {
         if (!property.builtinSwitchPoint.hasBeenInvalidated()) {
            SwitchPoint.invalidateAll(new SwitchPoint[] { property.builtinSwitchPoint });
        }
        return obj;
    }

    private MethodHandle generateSetter(final Class<?> forType, final Class<?> type) {
        return debug(createSetter(forType, type, primitiveSetter, objectSetter), getLocalType(), type, "set");
    }

    /**
     * Is this property of the undefined type?
     * @return true if undefined
     */
    protected final boolean isUndefined() {
        return getLocalType() == null;
    }

    @Override
    public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
        checkUndeclared();

        final int typeIndex        = getAccessorTypeIndex(type);
        final int currentTypeIndex = getAccessorTypeIndex(getLocalType());

        //if we are asking for an object setter, but are still a primitive type, we might try to box it
        MethodHandle mh;
        if (needsInvalidator(typeIndex, currentTypeIndex)) {
            final Property     newProperty = getWiderProperty(type);
            final PropertyMap  newMap      = getWiderMap(currentMap, newProperty);

            final MethodHandle widerSetter = newProperty.getSetter(type, newMap);
            final Class<?>     ct = getLocalType();
            mh = MH.filterArguments(widerSetter, 0, MH.insertArguments(debugReplace(ct, type, currentMap, newMap) , 1, newMap));
            if (ct != null && ct.isPrimitive() && !type.isPrimitive()) {
                 mh = ObjectClassGenerator.createGuardBoxedPrimitiveSetter(ct, generateSetter(ct, ct), mh);
            }
        } else {
            final Class<?> forType = isUndefined() ? type : getLocalType();
            mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type);
        }

        if (isBuiltin()) {
           mh = MH.filterArguments(mh, 0, debugInvalidate(MH.insertArguments(INVALIDATE_SP, 0, this), getKey()));
        }

        assert mh.type().returnType() == void.class : mh.type();

        return mh;
    }

    @Override
    public final boolean canChangeType() {
        if (!hasDualFields()) {
            return false;
        }
        // Return true for currently undefined even if non-writable/configurable to allow initialization of ES6 CONST.
        return getLocalType() == null || (getLocalType() != Object.class && (isConfigurable() || isWritable()));
    }

    private boolean needsInvalidator(final int typeIndex, final int currentTypeIndex) {
        return canChangeType() && typeIndex > currentTypeIndex;
    }

    private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) {
        if (!Context.DEBUG || !Global.hasInstance()) {
            return mh;
        }

        final Context context = Context.getContextTrusted();
        assert context != null;

        return context.addLoggingToHandle(
                ObjectClassGenerator.class,
                Level.INFO,
                mh,
                0,
                true,
                new Supplier<String>() {
                    @Override
                    public String get() {
                        return tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", slot=" + getSlot() + " " + getClass().getSimpleName() + " forType=" + stripName(forType) + ", type=" + stripName(type) + ')';
                    }
                });
    }

    private MethodHandle debugReplace(final Class<?> oldType, final Class<?> newType, final PropertyMap oldMap, final PropertyMap newMap) {
        if (!Context.DEBUG || !Global.hasInstance()) {
            return REPLACE_MAP;
        }

        final Context context = Context.getContextTrusted();
        assert context != null;

        MethodHandle mh = context.addLoggingToHandle(
                ObjectClassGenerator.class,
                REPLACE_MAP,
                new Supplier<String>() {
                    @Override
                    public String get() {
                        return "Type change for '" + getKey() + "' " + oldType + "=>" + newType;
                    }
                });

        mh = context.addLoggingToHandle(
                ObjectClassGenerator.class,
                Level.FINEST,
                mh,
                Integer.MAX_VALUE,
                false,
                new Supplier<String>() {
                    @Override
                    public String get() {
                        return "Setting map " + Debug.id(oldMap) + " => " + Debug.id(newMap) + " " + oldMap + " => " + newMap;
                    }
                });
        return mh;
    }

    private static MethodHandle debugInvalidate(final MethodHandle invalidator, final String key) {
        if (!Context.DEBUG || !Global.hasInstance()) {
            return invalidator;
        }

        final Context context = Context.getContextTrusted();
        assert context != null;

        return context.addLoggingToHandle(
                ObjectClassGenerator.class,
                invalidator,
                new Supplier<String>() {
                    @Override
                    public String get() {
                        return "Field change callback for " + key + " triggered ";
                    }
                });
    }

    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
        return MH.findStatic(LOOKUP, AccessorProperty.class, name, MH.type(rtype, types));
    }
}
