src/jdk/nashorn/internal/runtime/SpillProperty.java

Wed, 05 Nov 2014 12:34:06 +0100

author
lagergren
date
Wed, 05 Nov 2014 12:34:06 +0100
changeset 1086
d0b26e6f602c
parent 1074
29a4cd3d1f7a
child 1248
7d249c2d066a
permissions
-rw-r--r--

8057825: Bug in apply specialization - if an apply specialization that is available doesn't fit, a new one wouldn't be installed, if the new code generated as a specialization didn't manage to do the apply specialization. Basically changing a conditional to an unconditional.
Reviewed-by: attila, hannesw

attila@963 1 /*
attila@963 2 * Copyright (c) 2010-2014, Oracle and/or its affiliates. All rights reserved.
attila@963 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
attila@963 4 *
attila@963 5 * This code is free software; you can redistribute it and/or modify it
attila@963 6 * under the terms of the GNU General Public License version 2 only, as
attila@963 7 * published by the Free Software Foundation. Oracle designates this
attila@963 8 * particular file as subject to the "Classpath" exception as provided
attila@963 9 * by Oracle in the LICENSE file that accompanied this code.
attila@963 10 *
attila@963 11 * This code is distributed in the hope that it will be useful, but WITHOUT
attila@963 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
attila@963 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
attila@963 14 * version 2 for more details (a copy is included in the LICENSE file that
attila@963 15 * accompanied this code).
attila@963 16 *
attila@963 17 * You should have received a copy of the GNU General Public License version
attila@963 18 * 2 along with this work; if not, write to the Free Software Foundation,
attila@963 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
attila@963 20 *
attila@963 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
attila@963 22 * or visit www.oracle.com if you need additional information or have any
attila@963 23 * questions.
attila@963 24 */
attila@963 25
attila@963 26 package jdk.nashorn.internal.runtime;
attila@963 27
attila@963 28 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
attila@963 29 import static jdk.nashorn.internal.lookup.Lookup.MH;
attila@963 30
attila@963 31 import java.lang.invoke.MethodHandle;
attila@963 32 import java.lang.invoke.MethodHandles;
attila@963 33
attila@963 34 /**
attila@963 35 * Spill property
attila@963 36 */
attila@963 37 public class SpillProperty extends AccessorProperty {
attila@963 38 private static final long serialVersionUID = 3028496245198669460L;
attila@963 39
attila@963 40 private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
attila@963 41
attila@963 42 private static final MethodHandle PARRAY_GETTER = MH.asType(MH.getter(LOOKUP, ScriptObject.class, "primitiveSpill", long[].class), MH.type(long[].class, Object.class));
attila@963 43 private static final MethodHandle OARRAY_GETTER = MH.asType(MH.getter(LOOKUP, ScriptObject.class, "objectSpill", Object[].class), MH.type(Object[].class, Object.class));
attila@963 44
attila@963 45 private static final MethodHandle OBJECT_GETTER = MH.filterArguments(MH.arrayElementGetter(Object[].class), 0, OARRAY_GETTER);
attila@963 46 private static final MethodHandle PRIMITIVE_GETTER = MH.filterArguments(MH.arrayElementGetter(long[].class), 0, PARRAY_GETTER);
attila@963 47 private static final MethodHandle OBJECT_SETTER = MH.filterArguments(MH.arrayElementSetter(Object[].class), 0, OARRAY_GETTER);
attila@963 48 private static final MethodHandle PRIMITIVE_SETTER = MH.filterArguments(MH.arrayElementSetter(long[].class), 0, PARRAY_GETTER);
attila@963 49
attila@963 50 private static class Accessors {
attila@963 51 private MethodHandle objectGetter;
attila@963 52 private MethodHandle objectSetter;
attila@963 53 private MethodHandle primitiveGetter;
attila@963 54 private MethodHandle primitiveSetter;
attila@963 55
attila@963 56 private final int slot;
attila@963 57 private final MethodHandle ensureSpillSize;
attila@963 58
attila@963 59 private static Accessors ACCESSOR_CACHE[] = new Accessors[512];
attila@963 60
attila@963 61 //private static final Map<Integer, Reference<Accessors>> ACCESSOR_CACHE = Collections.synchronizedMap(new WeakHashMap<Integer, Reference<Accessors>>());
attila@963 62
attila@963 63 Accessors(final int slot) {
attila@963 64 assert slot >= 0;
attila@963 65 this.slot = slot;
attila@963 66 this.ensureSpillSize = MH.asType(MH.insertArguments(ScriptObject.ENSURE_SPILL_SIZE, 1, slot), MH.type(Object.class, Object.class));
attila@963 67 }
attila@963 68
attila@963 69 private static void ensure(final int slot) {
attila@963 70 int len = ACCESSOR_CACHE.length;
attila@963 71 if (slot >= len) {
attila@963 72 do {
attila@963 73 len *= 2;
attila@963 74 } while (slot >= len);
attila@963 75 final Accessors newCache[] = new Accessors[len];
attila@963 76 System.arraycopy(ACCESSOR_CACHE, 0, newCache, 0, ACCESSOR_CACHE.length);
attila@963 77 ACCESSOR_CACHE = newCache;
attila@963 78 }
attila@963 79 }
attila@963 80
attila@963 81 static MethodHandle getCached(final int slot, final boolean isPrimitive, final boolean isGetter) {
attila@963 82 //Reference<Accessors> ref = ACCESSOR_CACHE.get(slot);
attila@963 83 ensure(slot);
attila@963 84 Accessors acc = ACCESSOR_CACHE[slot];
attila@963 85 if (acc == null) {
attila@963 86 acc = new Accessors(slot);
attila@963 87 ACCESSOR_CACHE[slot] = acc;
attila@963 88 }
attila@963 89
attila@963 90 return acc.getOrCreate(isPrimitive, isGetter);
attila@963 91 }
attila@963 92
attila@963 93 private static MethodHandle primordial(final boolean isPrimitive, final boolean isGetter) {
attila@963 94 if (isPrimitive) {
attila@963 95 return isGetter ? PRIMITIVE_GETTER : PRIMITIVE_SETTER;
attila@963 96 }
attila@963 97 return isGetter ? OBJECT_GETTER : OBJECT_SETTER;
attila@963 98 }
attila@963 99
attila@963 100 MethodHandle getOrCreate(final boolean isPrimitive, final boolean isGetter) {
attila@963 101 MethodHandle accessor;
attila@963 102
attila@963 103 accessor = getInner(isPrimitive, isGetter);
attila@963 104 if (accessor != null) {
attila@963 105 return accessor;
attila@963 106 }
attila@963 107
attila@963 108 accessor = primordial(isPrimitive, isGetter);
attila@963 109 accessor = MH.insertArguments(accessor, 1, slot);
attila@963 110 if (!isGetter) {
attila@963 111 accessor = MH.filterArguments(accessor, 0, ensureSpillSize);
attila@963 112 }
attila@963 113 setInner(isPrimitive, isGetter, accessor);
attila@963 114
attila@963 115 return accessor;
attila@963 116 }
attila@963 117
attila@963 118 void setInner(final boolean isPrimitive, final boolean isGetter, final MethodHandle mh) {
attila@963 119 if (isPrimitive) {
attila@963 120 if (isGetter) {
attila@963 121 primitiveGetter = mh;
attila@963 122 } else {
attila@963 123 primitiveSetter = mh;
attila@963 124 }
attila@963 125 } else {
attila@963 126 if (isGetter) {
attila@963 127 objectGetter = mh;
attila@963 128 } else {
attila@963 129 objectSetter = mh;
attila@963 130 }
attila@963 131 }
attila@963 132 }
attila@963 133
attila@963 134 MethodHandle getInner(final boolean isPrimitive, final boolean isGetter) {
attila@963 135 if (isPrimitive) {
attila@963 136 return isGetter ? primitiveGetter : primitiveSetter;
attila@963 137 }
attila@963 138 return isGetter ? objectGetter : objectSetter;
attila@963 139 }
attila@963 140 }
attila@963 141
attila@963 142 private static MethodHandle primitiveGetter(final int slot) {
attila@963 143 return OBJECT_FIELDS_ONLY ? null : Accessors.getCached(slot, true, true);
attila@963 144 }
attila@963 145 private static MethodHandle primitiveSetter(final int slot) {
attila@963 146 return OBJECT_FIELDS_ONLY ? null : Accessors.getCached(slot, true, false);
attila@963 147 }
attila@963 148 private static MethodHandle objectGetter(final int slot) {
attila@963 149 return Accessors.getCached(slot, false, true);
attila@963 150 }
attila@963 151 private static MethodHandle objectSetter(final int slot) {
attila@963 152 return Accessors.getCached(slot, false, false);
attila@963 153 }
attila@963 154
attila@963 155 /**
attila@963 156 * Constructor for spill properties. Array getters and setters will be created on demand.
attila@963 157 *
attila@963 158 * @param key the property key
attila@963 159 * @param flags the property flags
attila@963 160 * @param slot spill slot
attila@963 161 */
attila@963 162 public SpillProperty(final String key, final int flags, final int slot) {
attila@963 163 super(key, flags, slot, primitiveGetter(slot), primitiveSetter(slot), objectGetter(slot), objectSetter(slot));
hannesw@1074 164 assert !OBJECT_FIELDS_ONLY || getLocalType() == Object.class;
attila@963 165 }
attila@963 166
attila@963 167 SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) {
attila@963 168 this(key, flags, slot);
hannesw@1074 169 setType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
attila@963 170 }
attila@963 171
attila@963 172 SpillProperty(final String key, final int flags, final int slot, final ScriptObject owner, final Object initialValue) {
attila@963 173 this(key, flags, slot);
attila@963 174 setInitialValue(owner, initialValue);
attila@963 175 }
attila@963 176
attila@963 177 /**
attila@963 178 * Copy constructor
attila@963 179 * @param property other property
attila@963 180 */
attila@963 181 protected SpillProperty(final SpillProperty property) {
attila@963 182 super(property);
attila@963 183 }
attila@963 184
attila@963 185 /**
attila@963 186 * Copy constructor
attila@963 187 * @param newType new type
attila@963 188 * @param property other property
attila@963 189 */
attila@963 190 protected SpillProperty(final SpillProperty property, final Class<?> newType) {
attila@963 191 super(property, newType);
attila@963 192 }
attila@963 193
attila@963 194 @Override
attila@963 195 public Property copy() {
attila@963 196 return new SpillProperty(this);
attila@963 197 }
attila@963 198
attila@963 199 @Override
attila@963 200 public Property copy(final Class<?> newType) {
attila@963 201 return new SpillProperty(this, newType);
attila@963 202 }
attila@963 203
attila@963 204 @Override
attila@963 205 public boolean isSpill() {
attila@963 206 return true;
attila@963 207 }
attila@963 208
attila@963 209 @Override
attila@963 210 void initMethodHandles(final Class<?> structure) {
attila@963 211 final int slot = getSlot();
attila@963 212 primitiveGetter = primitiveGetter(slot);
attila@963 213 primitiveSetter = primitiveSetter(slot);
attila@963 214 objectGetter = objectGetter(slot);
attila@963 215 objectSetter = objectSetter(slot);
attila@963 216 }
attila@963 217 }

mercurial