/*
 * 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 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));
    }
}
