Tue, 12 Mar 2013 15:30:53 +0100
8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
Reviewed-by: attila, jlaskey
jlaskey@3 | 1 | /* |
jlaskey@7 | 2 | * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
jlaskey@3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
jlaskey@3 | 4 | * |
jlaskey@3 | 5 | * This code is free software; you can redistribute it and/or modify it |
jlaskey@3 | 6 | * under the terms of the GNU General Public License version 2 only, as |
jlaskey@3 | 7 | * published by the Free Software Foundation. Oracle designates this |
jlaskey@3 | 8 | * particular file as subject to the "Classpath" exception as provided |
jlaskey@3 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
jlaskey@3 | 10 | * |
jlaskey@3 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
jlaskey@3 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
jlaskey@3 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
jlaskey@3 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
jlaskey@3 | 15 | * accompanied this code). |
jlaskey@3 | 16 | * |
jlaskey@3 | 17 | * You should have received a copy of the GNU General Public License version |
jlaskey@3 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
jlaskey@3 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
jlaskey@3 | 20 | * |
jlaskey@3 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
jlaskey@3 | 22 | * or visit www.oracle.com if you need additional information or have any |
jlaskey@3 | 23 | * questions. |
jlaskey@3 | 24 | */ |
jlaskey@3 | 25 | |
jlaskey@3 | 26 | package jdk.nashorn.internal.runtime; |
jlaskey@3 | 27 | |
lagergren@96 | 28 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.ACCESSOR_TYPES; |
lagergren@96 | 29 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS; |
lagergren@96 | 30 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.LOG; |
lagergren@96 | 31 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY; |
lagergren@96 | 32 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_TYPE; |
lagergren@96 | 33 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGetter; |
lagergren@96 | 34 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGuardBoxedPrimitiveSetter; |
lagergren@96 | 35 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createSetter; |
lagergren@96 | 36 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getAccessorType; |
lagergren@96 | 37 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getAccessorTypeIndex; |
lagergren@96 | 38 | import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getNumberOfAccessorTypes; |
sundar@133 | 39 | import static jdk.nashorn.internal.lookup.Lookup.MH; |
sundar@133 | 40 | import static jdk.nashorn.internal.lookup.MethodHandleFactory.stripName; |
jlaskey@3 | 41 | |
jlaskey@3 | 42 | import java.lang.invoke.MethodHandle; |
jlaskey@3 | 43 | import java.lang.invoke.MethodHandles; |
jlaskey@3 | 44 | import java.lang.invoke.MethodType; |
lagergren@96 | 45 | import jdk.nashorn.internal.codegen.ObjectClassGenerator; |
jlaskey@3 | 46 | import jdk.nashorn.internal.codegen.types.Type; |
sundar@133 | 47 | import jdk.nashorn.internal.lookup.Lookup; |
sundar@133 | 48 | import jdk.nashorn.internal.lookup.MethodHandleFactory; |
jlaskey@3 | 49 | |
jlaskey@3 | 50 | /** |
jlaskey@3 | 51 | * An AccessorProperty is the most generic property type. An AccessorProperty is |
jlaskey@3 | 52 | * represented as fields in a ScriptObject class. |
jlaskey@3 | 53 | * |
jlaskey@3 | 54 | * @see SpillProperty |
jlaskey@3 | 55 | */ |
jlaskey@3 | 56 | public class AccessorProperty extends Property { |
jlaskey@3 | 57 | private static final MethodHandle REPLACE_MAP = findOwnMH("replaceMap", Object.class, Object.class, PropertyMap.class, String.class, Class.class, Class.class); |
jlaskey@3 | 58 | |
jlaskey@3 | 59 | private static final int NOOF_TYPES = getNumberOfAccessorTypes(); |
jlaskey@3 | 60 | |
jlaskey@3 | 61 | /** Property getter cache */ |
jlaskey@3 | 62 | private MethodHandle[] getters = new MethodHandle[NOOF_TYPES]; |
jlaskey@3 | 63 | |
jlaskey@3 | 64 | private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES]; |
jlaskey@3 | 65 | private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES]; |
jlaskey@3 | 66 | |
jlaskey@3 | 67 | /** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */ |
jlaskey@3 | 68 | private MethodHandle primitiveGetter; |
jlaskey@3 | 69 | |
jlaskey@3 | 70 | /** Seed setter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */ |
jlaskey@3 | 71 | private MethodHandle primitiveSetter; |
jlaskey@3 | 72 | |
jlaskey@3 | 73 | /** Seed getter for the Object version of this field */ |
jlaskey@3 | 74 | private MethodHandle objectGetter; |
jlaskey@3 | 75 | |
jlaskey@3 | 76 | /** Seed setter for the Object version of this field */ |
jlaskey@3 | 77 | private MethodHandle objectSetter; |
jlaskey@3 | 78 | |
jlaskey@3 | 79 | /** |
jlaskey@3 | 80 | * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode |
jlaskey@3 | 81 | * null means undefined, and primitive types are allowed. The reason a special type is used for |
jlaskey@3 | 82 | * undefined, is that are no bits left to represent it in primitive types |
jlaskey@3 | 83 | */ |
jlaskey@3 | 84 | private Class<?> currentType; |
jlaskey@3 | 85 | |
jlaskey@3 | 86 | static { |
jlaskey@3 | 87 | for (int i = 0; i < NOOF_TYPES; i++) { |
jlaskey@3 | 88 | final Type type = ACCESSOR_TYPES.get(i); |
jlaskey@3 | 89 | ACCESSOR_GETTER_TYPES[i] = MH.type(type.getTypeClass(), Object.class); |
jlaskey@3 | 90 | ACCESSOR_SETTER_TYPES[i] = MH.type(void.class, Object.class, type.getTypeClass()); |
jlaskey@3 | 91 | } |
jlaskey@3 | 92 | } |
jlaskey@3 | 93 | |
jlaskey@3 | 94 | /** |
jlaskey@3 | 95 | * Delegate constructor. This is used when adding properties to the Global scope, which |
jlaskey@3 | 96 | * is necessary for outermost levels in a script (the ScriptObject is represented by |
jlaskey@131 | 97 | * a JO-prefixed ScriptObject class, but the properties need to be in the Global scope |
jlaskey@3 | 98 | * and are thus rebound with that as receiver |
jlaskey@3 | 99 | * |
jlaskey@3 | 100 | * @param property accessor property to rebind |
jlaskey@3 | 101 | * @param delegate delegate script object to rebind receiver to |
jlaskey@3 | 102 | */ |
jlaskey@3 | 103 | public AccessorProperty(final AccessorProperty property, final ScriptObject delegate) { |
jlaskey@3 | 104 | this(property); |
jlaskey@3 | 105 | |
jlaskey@3 | 106 | this.getters = new MethodHandle[NOOF_TYPES]; |
jlaskey@3 | 107 | |
jlaskey@3 | 108 | this.primitiveGetter = bindTo(primitiveGetter, delegate); |
jlaskey@3 | 109 | this.primitiveSetter = bindTo(primitiveSetter, delegate); |
jlaskey@3 | 110 | this.objectGetter = bindTo(objectGetter, delegate); |
jlaskey@3 | 111 | this.objectSetter = bindTo(objectSetter, delegate); |
jlaskey@3 | 112 | |
jlaskey@3 | 113 | setCurrentType(property.getCurrentType()); |
jlaskey@3 | 114 | } |
jlaskey@3 | 115 | |
jlaskey@3 | 116 | /** |
jlaskey@3 | 117 | * Constructor. Similar to the constructor with both primitive getters and setters, the difference |
jlaskey@3 | 118 | * here being that only one getter and setter (setter is optional for non writable fields) is given |
jlaskey@3 | 119 | * to the constructor, and the rest are created from those. Used e.g. by Nasgen classes |
jlaskey@3 | 120 | * |
jlaskey@3 | 121 | * @param key the property key |
jlaskey@3 | 122 | * @param flags the property flags |
jlaskey@80 | 123 | * @param slot the property field number or spill slot |
jlaskey@3 | 124 | * @param getter the property getter |
jlaskey@3 | 125 | * @param setter the property setter or null if non writable, non configurable |
jlaskey@3 | 126 | */ |
jlaskey@80 | 127 | public AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) { |
jlaskey@80 | 128 | super(key, flags, slot); |
jlaskey@3 | 129 | |
jlaskey@3 | 130 | // we don't need to prep the setters these will never be invalidated as this is a nasgen |
jlaskey@3 | 131 | // or known type getter/setter. No invalidations will take place |
jlaskey@3 | 132 | |
jlaskey@3 | 133 | final Class<?> getterType = getter.type().returnType(); |
jlaskey@3 | 134 | final Class<?> setterType = setter == null ? null : setter.type().parameterType(1); |
jlaskey@3 | 135 | |
jlaskey@3 | 136 | assert setterType == null || setterType == getterType; |
jlaskey@3 | 137 | |
jlaskey@3 | 138 | if (getterType.isPrimitive()) { |
jlaskey@3 | 139 | for (int i = 0; i < NOOF_TYPES; i++) { |
jlaskey@3 | 140 | getters[i] = MH.asType( |
jlaskey@3 | 141 | Lookup.filterReturnType( |
jlaskey@3 | 142 | getter, |
jlaskey@3 | 143 | getAccessorType(i).getTypeClass()), |
jlaskey@3 | 144 | ACCESSOR_GETTER_TYPES[i]); |
jlaskey@3 | 145 | } |
jlaskey@3 | 146 | } else { |
jlaskey@3 | 147 | //this will work as the object setter and getter will be converted appropriately |
jlaskey@3 | 148 | objectGetter = getter; |
jlaskey@3 | 149 | objectSetter = setter; |
jlaskey@3 | 150 | } |
jlaskey@3 | 151 | |
jlaskey@3 | 152 | setCurrentType(getterType); |
jlaskey@3 | 153 | } |
jlaskey@3 | 154 | |
jlaskey@3 | 155 | /** |
jlaskey@80 | 156 | * Constructor for dual field AccessorPropertys. |
jlaskey@80 | 157 | * |
jlaskey@80 | 158 | * @param key property key |
jlaskey@80 | 159 | * @param flags property flags |
jlaskey@80 | 160 | * @param structure structure for objects associated with this property |
jlaskey@80 | 161 | * @param slot property field number or spill slot |
jlaskey@80 | 162 | */ |
jlaskey@80 | 163 | public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot) { |
jlaskey@80 | 164 | super(key, flags, slot); |
jlaskey@80 | 165 | |
jlaskey@80 | 166 | /* |
jlaskey@80 | 167 | * primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also |
jlaskey@80 | 168 | * works in dual field mode, it only means that the property never has a primitive |
jlaskey@80 | 169 | * representation. |
jlaskey@80 | 170 | */ |
jlaskey@80 | 171 | primitiveGetter = null; |
jlaskey@80 | 172 | primitiveSetter = null; |
jlaskey@80 | 173 | |
jlaskey@80 | 174 | final MethodHandles.Lookup lookup = MethodHandles.lookup(); |
jlaskey@80 | 175 | |
jlaskey@80 | 176 | if (isParameter() && hasArguments()) { |
jlaskey@80 | 177 | final MethodHandle arguments = MH.getter(MethodHandles.lookup(), structure, "arguments", Object.class); |
jlaskey@80 | 178 | final MethodHandle argumentsSO = MH.asType(arguments, arguments.type().changeReturnType(ScriptObject.class)); |
jlaskey@80 | 179 | |
jlaskey@80 | 180 | objectGetter = MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot); |
jlaskey@80 | 181 | objectSetter = MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot); |
jlaskey@80 | 182 | } else { |
jlaskey@80 | 183 | final String fieldNameObject = ObjectClassGenerator.getFieldName(slot, Type.OBJECT); |
jlaskey@80 | 184 | final String fieldNamePrimitive = ObjectClassGenerator.getFieldName(slot, ObjectClassGenerator.PRIMITIVE_TYPE); |
jlaskey@80 | 185 | |
jlaskey@80 | 186 | objectGetter = MH.getter(lookup, structure, fieldNameObject, Type.OBJECT.getTypeClass()); |
jlaskey@80 | 187 | objectSetter = MH.setter(lookup, structure, fieldNameObject, Type.OBJECT.getTypeClass()); |
jlaskey@80 | 188 | |
jlaskey@80 | 189 | if (!OBJECT_FIELDS_ONLY) { |
jlaskey@80 | 190 | primitiveGetter = MH.getter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass()); |
jlaskey@80 | 191 | primitiveSetter = MH.setter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass()); |
jlaskey@80 | 192 | } |
jlaskey@80 | 193 | } |
jlaskey@80 | 194 | |
jlaskey@80 | 195 | Class<?> initialType = null; |
jlaskey@80 | 196 | |
jlaskey@80 | 197 | if (OBJECT_FIELDS_ONLY || isAlwaysObject()) { |
jlaskey@80 | 198 | initialType = Object.class; |
jlaskey@80 | 199 | } else if (!canBePrimitive()) { |
jlaskey@80 | 200 | info(key + " cannot be primitive"); |
jlaskey@80 | 201 | initialType = Object.class; |
jlaskey@80 | 202 | } else { |
jlaskey@80 | 203 | info(key + " CAN be primitive"); |
jlaskey@80 | 204 | if (!canBeUndefined()) { |
jlaskey@80 | 205 | info(key + " is always defined"); |
jlaskey@80 | 206 | initialType = int.class; //double works too for less type invalidation, but this requires experimentation, e.g. var x = 17; x += 2 will turn it into double now because of lack of range analysis |
jlaskey@80 | 207 | } |
jlaskey@80 | 208 | } |
jlaskey@80 | 209 | |
jlaskey@80 | 210 | // is always object means "is never initialized to undefined, and always of object type |
jlaskey@80 | 211 | setCurrentType(initialType); |
jlaskey@80 | 212 | } |
jlaskey@80 | 213 | |
jlaskey@80 | 214 | /** |
jlaskey@3 | 215 | * Copy constructor |
jlaskey@3 | 216 | * |
jlaskey@3 | 217 | * @param property source property |
jlaskey@3 | 218 | */ |
jlaskey@3 | 219 | protected AccessorProperty(final AccessorProperty property) { |
jlaskey@3 | 220 | super(property); |
jlaskey@3 | 221 | |
jlaskey@3 | 222 | this.getters = property.getters; |
jlaskey@3 | 223 | this.primitiveGetter = property.primitiveGetter; |
jlaskey@3 | 224 | this.primitiveSetter = property.primitiveSetter; |
jlaskey@3 | 225 | this.objectGetter = property.objectGetter; |
jlaskey@3 | 226 | this.objectSetter = property.objectSetter; |
jlaskey@3 | 227 | |
jlaskey@3 | 228 | setCurrentType(property.getCurrentType()); |
jlaskey@3 | 229 | } |
jlaskey@3 | 230 | |
jlaskey@3 | 231 | private static MethodHandle bindTo(final MethodHandle mh, final Object receiver) { |
jlaskey@3 | 232 | if (mh == null) { |
jlaskey@3 | 233 | return null; |
jlaskey@3 | 234 | } |
jlaskey@3 | 235 | |
jlaskey@3 | 236 | return MH.dropArguments(MH.bindTo(mh, receiver), 0, Object.class); |
jlaskey@3 | 237 | } |
jlaskey@3 | 238 | |
jlaskey@3 | 239 | @Override |
jlaskey@3 | 240 | protected Property copy() { |
jlaskey@3 | 241 | return new AccessorProperty(this); |
jlaskey@3 | 242 | } |
jlaskey@3 | 243 | |
jlaskey@3 | 244 | @Override |
jlaskey@3 | 245 | public MethodHandle getGetter(final Class<?> type) { |
jlaskey@3 | 246 | final int i = getAccessorTypeIndex(type); |
jlaskey@3 | 247 | if (getters[i] == null) { |
jlaskey@3 | 248 | getters[i] = debug( |
jlaskey@3 | 249 | MH.asType( |
jlaskey@3 | 250 | createGetter( |
jlaskey@3 | 251 | currentType, |
jlaskey@3 | 252 | type, |
jlaskey@3 | 253 | primitiveGetter, |
jlaskey@3 | 254 | objectGetter), |
jlaskey@3 | 255 | ACCESSOR_GETTER_TYPES[i]), |
jlaskey@3 | 256 | currentType, |
jlaskey@3 | 257 | type, |
jlaskey@3 | 258 | "get"); |
jlaskey@3 | 259 | } |
jlaskey@3 | 260 | |
jlaskey@3 | 261 | return getters[i]; |
jlaskey@3 | 262 | } |
jlaskey@3 | 263 | |
jlaskey@3 | 264 | private Property getWiderProperty(final Class<?> type) { |
jlaskey@3 | 265 | final AccessorProperty newProperty = new AccessorProperty(this); |
jlaskey@3 | 266 | newProperty.invalidate(type); |
jlaskey@3 | 267 | return newProperty; |
jlaskey@3 | 268 | } |
jlaskey@3 | 269 | |
jlaskey@3 | 270 | private PropertyMap getWiderMap(final PropertyMap oldMap, final Property newProperty) { |
jlaskey@3 | 271 | final PropertyMap newMap = oldMap.replaceProperty(this, newProperty); |
jlaskey@3 | 272 | assert oldMap.size() > 0; |
jlaskey@3 | 273 | assert newMap.size() == oldMap.size(); |
jlaskey@3 | 274 | return newMap; |
jlaskey@3 | 275 | } |
jlaskey@3 | 276 | |
jlaskey@3 | 277 | // the final three arguments are for debug printout purposes only |
jlaskey@3 | 278 | @SuppressWarnings("unused") |
jlaskey@3 | 279 | private static Object replaceMap(final Object sobj, final PropertyMap newMap, final String key, final Class<?> oldType, final Class<?> newType) { |
jlaskey@3 | 280 | if (DEBUG_FIELDS) { |
jlaskey@3 | 281 | final PropertyMap oldMap = ((ScriptObject)sobj).getMap(); |
jlaskey@3 | 282 | info("Type change for '" + key + "' " + oldType + "=>" + newType); |
jlaskey@3 | 283 | finest("setting map " + sobj + " from " + Debug.id(oldMap) + " to " + Debug.id(newMap) + " " + oldMap + " => " + newMap); |
jlaskey@3 | 284 | } |
jlaskey@3 | 285 | ((ScriptObject)sobj).setMap(newMap); |
jlaskey@3 | 286 | return sobj; |
jlaskey@3 | 287 | } |
jlaskey@3 | 288 | |
jlaskey@3 | 289 | private MethodHandle generateSetter(final Class<?> forType, final Class<?> type) { |
jlaskey@3 | 290 | MethodHandle mh = createSetter(forType, type, primitiveSetter, objectSetter); |
jlaskey@3 | 291 | mh = MH.asType(mh, ACCESSOR_SETTER_TYPES[getAccessorTypeIndex(type)]); //has to be the case for invokeexact to work in ScriptObject |
jlaskey@3 | 292 | mh = debug(mh, currentType, type, "set"); |
jlaskey@3 | 293 | return mh; |
jlaskey@3 | 294 | } |
jlaskey@3 | 295 | |
jlaskey@3 | 296 | @Override |
jlaskey@3 | 297 | public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) { |
jlaskey@3 | 298 | final int i = getAccessorTypeIndex(type); |
jlaskey@3 | 299 | final int ci = currentType == null ? -1 : getAccessorTypeIndex(currentType); |
jlaskey@3 | 300 | final Class<?> forType = currentType == null ? type : currentType; |
jlaskey@3 | 301 | |
jlaskey@3 | 302 | //if we are asking for an object setter, but are still a primitive type, we might try to box it |
jlaskey@3 | 303 | |
jlaskey@3 | 304 | if (needsInvalidator(i, ci)) { |
jlaskey@3 | 305 | final Property newProperty = getWiderProperty(type); |
jlaskey@3 | 306 | final PropertyMap newMap = getWiderMap(currentMap, newProperty); |
jlaskey@3 | 307 | final MethodHandle widerSetter = newProperty.getSetter(type, newMap); |
jlaskey@3 | 308 | final MethodHandle explodeTypeSetter = MH.filterArguments(widerSetter, 0, MH.insertArguments(REPLACE_MAP, 1, newMap, getKey(), currentType, type)); |
jlaskey@3 | 309 | if (currentType != null && currentType.isPrimitive() && type == Object.class) { |
jlaskey@3 | 310 | //might try a box check on this to avoid widening field to object storage |
jlaskey@3 | 311 | return createGuardBoxedPrimitiveSetter(currentType, generateSetter(currentType, currentType), explodeTypeSetter); |
jlaskey@3 | 312 | } |
jlaskey@3 | 313 | return explodeTypeSetter; |
jlaskey@3 | 314 | } |
jlaskey@3 | 315 | |
jlaskey@3 | 316 | return generateSetter(forType, type); |
jlaskey@3 | 317 | } |
jlaskey@3 | 318 | |
jlaskey@3 | 319 | @Override |
jlaskey@3 | 320 | public boolean canChangeType() { |
jlaskey@3 | 321 | if (OBJECT_FIELDS_ONLY) { |
jlaskey@3 | 322 | return false; |
jlaskey@3 | 323 | } |
jlaskey@3 | 324 | return currentType != Object.class && (isConfigurable() || isWritable()); |
jlaskey@3 | 325 | } |
jlaskey@3 | 326 | |
jlaskey@3 | 327 | private boolean needsInvalidator(final int ti, final int fti) { |
jlaskey@3 | 328 | return canChangeType() && ti > fti; |
jlaskey@3 | 329 | } |
jlaskey@3 | 330 | |
jlaskey@3 | 331 | private void invalidate(final Class<?> newType) { |
jlaskey@3 | 332 | getters = new MethodHandle[NOOF_TYPES]; |
jlaskey@3 | 333 | setCurrentType(newType); |
jlaskey@3 | 334 | } |
jlaskey@3 | 335 | |
jlaskey@3 | 336 | private static void finest(final String str) { |
jlaskey@3 | 337 | if (DEBUG_FIELDS) { |
jlaskey@3 | 338 | LOG.finest(str); |
jlaskey@3 | 339 | } |
jlaskey@3 | 340 | } |
jlaskey@3 | 341 | |
jlaskey@3 | 342 | private static void info(final String str) { |
jlaskey@3 | 343 | if (DEBUG_FIELDS) { |
jlaskey@3 | 344 | LOG.info(str); |
jlaskey@3 | 345 | } |
jlaskey@3 | 346 | } |
jlaskey@3 | 347 | |
jlaskey@3 | 348 | private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) { |
jlaskey@3 | 349 | if (DEBUG_FIELDS) { |
lagergren@137 | 350 | return MethodHandleFactory.addDebugPrintout( |
jlaskey@3 | 351 | LOG, |
jlaskey@3 | 352 | mh, |
jlaskey@3 | 353 | tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", forType=" + stripName(forType) + ", type=" + stripName(type) + ')'); |
jlaskey@3 | 354 | } |
jlaskey@3 | 355 | return mh; |
jlaskey@3 | 356 | } |
jlaskey@3 | 357 | |
jlaskey@3 | 358 | private void setCurrentType(final Class<?> currentType) { |
jlaskey@3 | 359 | this.currentType = currentType; |
jlaskey@3 | 360 | } |
jlaskey@3 | 361 | |
jlaskey@3 | 362 | @Override |
jlaskey@3 | 363 | public Class<?> getCurrentType() { |
jlaskey@3 | 364 | return currentType; |
jlaskey@3 | 365 | } |
jlaskey@3 | 366 | |
jlaskey@3 | 367 | private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { |
jlaskey@3 | 368 | return MH.findStatic(MethodHandles.lookup(), AccessorProperty.class, name, MH.type(rtype, types)); |
jlaskey@3 | 369 | } |
jlaskey@3 | 370 | |
jlaskey@3 | 371 | } |