author | hannesw |
Wed, 21 Mar 2018 16:55:34 +0100 | |
changeset 49275 | c639a6b33c5c |
parent 47216 | 71c04702a3d5 |
permissions | -rw-r--r-- |
16147 | 1 |
/* |
16151 | 2 |
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
16147 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package jdk.nashorn.internal.runtime; |
|
27 |
||
24719 | 28 |
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE; |
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16224
diff
changeset
|
29 |
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGetter; |
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16224
diff
changeset
|
30 |
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createSetter; |
24719 | 31 |
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldCount; |
32 |
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldName; |
|
16277 | 33 |
import static jdk.nashorn.internal.lookup.Lookup.MH; |
34 |
import static jdk.nashorn.internal.lookup.MethodHandleFactory.stripName; |
|
24719 | 35 |
import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex; |
36 |
import static jdk.nashorn.internal.runtime.JSType.getNumberOfAccessorTypes; |
|
37 |
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; |
|
23767 | 38 |
import java.io.IOException; |
39 |
import java.io.ObjectInputStream; |
|
16147 | 40 |
import java.lang.invoke.MethodHandle; |
41 |
import java.lang.invoke.MethodHandles; |
|
24738
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24734
diff
changeset
|
42 |
import java.lang.invoke.SwitchPoint; |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
43 |
import java.util.function.Supplier; |
24719 | 44 |
import java.util.logging.Level; |
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16224
diff
changeset
|
45 |
import jdk.nashorn.internal.codegen.ObjectClassGenerator; |
16147 | 46 |
import jdk.nashorn.internal.codegen.types.Type; |
16277 | 47 |
import jdk.nashorn.internal.lookup.Lookup; |
24738
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24734
diff
changeset
|
48 |
import jdk.nashorn.internal.objects.Global; |
16147 | 49 |
|
50 |
/** |
|
51 |
* An AccessorProperty is the most generic property type. An AccessorProperty is |
|
52 |
* represented as fields in a ScriptObject class. |
|
53 |
*/ |
|
24719 | 54 |
public class AccessorProperty extends Property { |
55 |
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); |
|
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
56 |
|
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
57 |
private static final MethodHandle REPLACE_MAP = findOwnMH_S("replaceMap", Object.class, Object.class, PropertyMap.class); |
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
58 |
private static final MethodHandle INVALIDATE_SP = findOwnMH_S("invalidateSwitchPoint", Object.class, AccessorProperty.class, Object.class); |
16147 | 59 |
|
60 |
private static final int NOOF_TYPES = getNumberOfAccessorTypes(); |
|
23767 | 61 |
private static final long serialVersionUID = 3371720170182154920L; |
16147 | 62 |
|
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
63 |
/** |
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
64 |
* Properties in different maps for the same structure class will share their field getters and setters. This could |
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
65 |
* be further extended to other method handles that are looked up in the AccessorProperty constructor, but right now |
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
66 |
* these are the most frequently retrieved ones, and lookup of method handle natives only registers in the profiler |
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
67 |
* for them. |
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
68 |
*/ |
24719 | 69 |
private static ClassValue<Accessors> GETTERS_SETTERS = new ClassValue<Accessors>() { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
70 |
@Override |
24719 | 71 |
protected Accessors computeValue(final Class<?> structure) { |
72 |
return new Accessors(structure); |
|
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
73 |
} |
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
74 |
}; |
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
75 |
|
24719 | 76 |
private static class Accessors { |
77 |
final MethodHandle[] objectGetters; |
|
78 |
final MethodHandle[] objectSetters; |
|
79 |
final MethodHandle[] primitiveGetters; |
|
80 |
final MethodHandle[] primitiveSetters; |
|
17770 | 81 |
|
24719 | 82 |
/** |
83 |
* Normal |
|
84 |
* @param structure |
|
85 |
*/ |
|
86 |
Accessors(final Class<?> structure) { |
|
87 |
final int fieldCount = getFieldCount(structure); |
|
88 |
objectGetters = new MethodHandle[fieldCount]; |
|
89 |
objectSetters = new MethodHandle[fieldCount]; |
|
90 |
primitiveGetters = new MethodHandle[fieldCount]; |
|
91 |
primitiveSetters = new MethodHandle[fieldCount]; |
|
18847 | 92 |
|
24719 | 93 |
for (int i = 0; i < fieldCount; i++) { |
94 |
final String fieldName = getFieldName(i, Type.OBJECT); |
|
95 |
final Class<?> typeClass = Type.OBJECT.getTypeClass(); |
|
96 |
objectGetters[i] = MH.asType(MH.getter(LOOKUP, structure, fieldName, typeClass), Lookup.GET_OBJECT_TYPE); |
|
97 |
objectSetters[i] = MH.asType(MH.setter(LOOKUP, structure, fieldName, typeClass), Lookup.SET_OBJECT_TYPE); |
|
98 |
} |
|
18847 | 99 |
|
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
100 |
if (!StructureLoader.isSingleFieldStructure(structure.getName())) { |
24719 | 101 |
for (int i = 0; i < fieldCount; i++) { |
102 |
final String fieldNamePrimitive = getFieldName(i, PRIMITIVE_FIELD_TYPE); |
|
103 |
final Class<?> typeClass = PRIMITIVE_FIELD_TYPE.getTypeClass(); |
|
104 |
primitiveGetters[i] = MH.asType(MH.getter(LOOKUP, structure, fieldNamePrimitive, typeClass), Lookup.GET_PRIMITIVE_TYPE); |
|
105 |
primitiveSetters[i] = MH.asType(MH.setter(LOOKUP, structure, fieldNamePrimitive, typeClass), Lookup.SET_PRIMITIVE_TYPE); |
|
106 |
} |
|
18847 | 107 |
} |
17770 | 108 |
} |
24719 | 109 |
} |
18847 | 110 |
|
24719 | 111 |
/** |
112 |
* Property getter cache |
|
113 |
* Note that we can't do the same simple caching for optimistic getters, |
|
114 |
* due to the fact that they are bound to a program point, which will |
|
115 |
* produce different boun method handles wrapping the same access mechanism |
|
116 |
* depending on callsite |
|
117 |
*/ |
|
26646
332e9901f0ed
8058304: Non-serializable fields in serializable classes
hannesw
parents:
26377
diff
changeset
|
118 |
private transient MethodHandle[] GETTER_CACHE = new MethodHandle[NOOF_TYPES]; |
16147 | 119 |
|
18855
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
120 |
/** |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
121 |
* Create a new accessor property. Factory method used by nasgen generated code. |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
122 |
* |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
123 |
* @param key {@link Property} key. |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
124 |
* @param propertyFlags {@link Property} flags. |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
125 |
* @param getter {@link Property} get accessor method. |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
126 |
* @param setter {@link Property} set accessor method. |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
127 |
* |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
128 |
* @return New {@link AccessorProperty} created. |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
129 |
*/ |
36023 | 130 |
public static AccessorProperty create(final Object key, final int propertyFlags, final MethodHandle getter, final MethodHandle setter) { |
18855
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
131 |
return new AccessorProperty(key, propertyFlags, -1, getter, setter); |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
132 |
} |
408663ef8f66
8020015: shared PropertyMaps should not be used without duplication
sundar
parents:
18852
diff
changeset
|
133 |
|
16147 | 134 |
/** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */ |
26055
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
135 |
transient MethodHandle primitiveGetter; |
16147 | 136 |
|
137 |
/** Seed setter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */ |
|
26055
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
138 |
transient MethodHandle primitiveSetter; |
16147 | 139 |
|
140 |
/** Seed getter for the Object version of this field */ |
|
26055
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
141 |
transient MethodHandle objectGetter; |
16147 | 142 |
|
143 |
/** Seed setter for the Object version of this field */ |
|
26055
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
144 |
transient MethodHandle objectSetter; |
16147 | 145 |
|
146 |
/** |
|
23372
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
19105
diff
changeset
|
147 |
* Delegate constructor for bound properties. This is used for properties created by |
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
19105
diff
changeset
|
148 |
* {@link ScriptRuntime#mergeScope} and the Nashorn {@code Object.bindProperties} method. |
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
19105
diff
changeset
|
149 |
* The former is used to add a script's defined globals to the current global scope while |
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
19105
diff
changeset
|
150 |
* still storing them in a JO-prefixed ScriptObject class. |
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
19105
diff
changeset
|
151 |
* |
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
19105
diff
changeset
|
152 |
* <p>All properties created by this constructor have the {@link #IS_BOUND} flag set.</p> |
16147 | 153 |
* |
154 |
* @param property accessor property to rebind |
|
18860
e387fde9322a
8014785: Ability to extend global instance by binding properties of another object
sundar
parents:
18859
diff
changeset
|
155 |
* @param delegate delegate object to rebind receiver to |
16147 | 156 |
*/ |
19105
a01ba9d17eab
8021571: @fork tests should use VM options passed from project.properties
sundar
parents:
18860
diff
changeset
|
157 |
AccessorProperty(final AccessorProperty property, final Object delegate) { |
24727 | 158 |
super(property, property.getFlags() | IS_BOUND); |
16147 | 159 |
|
17770 | 160 |
this.primitiveGetter = bindTo(property.primitiveGetter, delegate); |
161 |
this.primitiveSetter = bindTo(property.primitiveSetter, delegate); |
|
24719 | 162 |
this.objectGetter = bindTo(property.objectGetter, delegate); |
163 |
this.objectSetter = bindTo(property.objectSetter, delegate); |
|
24734
da070553a8e1
8038799: Guard and unbox boxed primitives types on setting them in Properties to avoid megamorphisism
lagergren
parents:
24733
diff
changeset
|
164 |
property.GETTER_CACHE = new MethodHandle[NOOF_TYPES]; |
23372
09707b3e5fb0
8021350: Share script classes between threads/globals within context
hannesw
parents:
19105
diff
changeset
|
165 |
// Properties created this way are bound to a delegate |
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
166 |
setType(property.getType()); |
16147 | 167 |
} |
168 |
||
169 |
/** |
|
24719 | 170 |
* SPILL PROPERTY or USER ACCESSOR PROPERTY abstract constructor |
171 |
* |
|
17770 | 172 |
* Constructor for spill properties. Array getters and setters will be created on demand. |
173 |
* |
|
174 |
* @param key the property key |
|
175 |
* @param flags the property flags |
|
176 |
* @param slot spill slot |
|
26055
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
177 |
* @param primitiveGetter primitive getter |
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
178 |
* @param primitiveSetter primitive setter |
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
179 |
* @param objectGetter object getter |
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
180 |
* @param objectSetter object setter |
17770 | 181 |
*/ |
24720 | 182 |
protected AccessorProperty( |
33690 | 183 |
final Object key, |
24720 | 184 |
final int flags, |
185 |
final int slot, |
|
186 |
final MethodHandle primitiveGetter, |
|
187 |
final MethodHandle primitiveSetter, |
|
188 |
final MethodHandle objectGetter, |
|
189 |
final MethodHandle objectSetter) { |
|
17770 | 190 |
super(key, flags, slot); |
24719 | 191 |
assert getClass() != AccessorProperty.class; |
192 |
this.primitiveGetter = primitiveGetter; |
|
193 |
this.primitiveSetter = primitiveSetter; |
|
194 |
this.objectGetter = objectGetter; |
|
195 |
this.objectSetter = objectSetter; |
|
196 |
initializeType(); |
|
17770 | 197 |
} |
198 |
||
199 |
/** |
|
24719 | 200 |
* NASGEN constructor |
201 |
* |
|
16147 | 202 |
* Constructor. Similar to the constructor with both primitive getters and setters, the difference |
203 |
* here being that only one getter and setter (setter is optional for non writable fields) is given |
|
204 |
* to the constructor, and the rest are created from those. Used e.g. by Nasgen classes |
|
205 |
* |
|
206 |
* @param key the property key |
|
207 |
* @param flags the property flags |
|
16224
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
208 |
* @param slot the property field number or spill slot |
16147 | 209 |
* @param getter the property getter |
210 |
* @param setter the property setter or null if non writable, non configurable |
|
211 |
*/ |
|
33690 | 212 |
private AccessorProperty(final Object key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) { |
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
213 |
super(key, flags | IS_BUILTIN | DUAL_FIELDS | (getter.type().returnType().isPrimitive() ? IS_NASGEN_PRIMITIVE : 0), slot); |
24719 | 214 |
assert !isSpill(); |
16147 | 215 |
|
216 |
// we don't need to prep the setters these will never be invalidated as this is a nasgen |
|
217 |
// or known type getter/setter. No invalidations will take place |
|
218 |
||
219 |
final Class<?> getterType = getter.type().returnType(); |
|
220 |
final Class<?> setterType = setter == null ? null : setter.type().parameterType(1); |
|
221 |
||
222 |
assert setterType == null || setterType == getterType; |
|
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
223 |
|
34732 | 224 |
if (getterType == int.class) { |
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
225 |
primitiveGetter = MH.asType(getter, Lookup.GET_PRIMITIVE_TYPE); |
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
226 |
primitiveSetter = setter == null ? null : MH.asType(setter, Lookup.SET_PRIMITIVE_TYPE); |
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
227 |
} else if (getterType == double.class) { |
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
228 |
primitiveGetter = MH.asType(MH.filterReturnValue(getter, ObjectClassGenerator.PACK_DOUBLE), Lookup.GET_PRIMITIVE_TYPE); |
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
229 |
primitiveSetter = setter == null ? null : MH.asType(MH.filterArguments(setter, 1, ObjectClassGenerator.UNPACK_DOUBLE), Lookup.SET_PRIMITIVE_TYPE); |
24719 | 230 |
} else { |
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
231 |
primitiveGetter = primitiveSetter = null; |
16147 | 232 |
} |
233 |
||
24719 | 234 |
assert primitiveGetter == null || primitiveGetter.type() == Lookup.GET_PRIMITIVE_TYPE : primitiveGetter + "!=" + Lookup.GET_PRIMITIVE_TYPE; |
235 |
assert primitiveSetter == null || primitiveSetter.type() == Lookup.SET_PRIMITIVE_TYPE : primitiveSetter; |
|
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
236 |
|
24719 | 237 |
objectGetter = getter.type() != Lookup.GET_OBJECT_TYPE ? MH.asType(getter, Lookup.GET_OBJECT_TYPE) : getter; |
238 |
objectSetter = setter != null && setter.type() != Lookup.SET_OBJECT_TYPE ? MH.asType(setter, Lookup.SET_OBJECT_TYPE) : setter; |
|
239 |
||
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
240 |
setType(getterType); |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
241 |
} |
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
16523
diff
changeset
|
242 |
|
16147 | 243 |
/** |
26055
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
244 |
* Normal ACCESS PROPERTY constructor given a structure class. |
16224
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
245 |
* Constructor for dual field AccessorPropertys. |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
246 |
* |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
247 |
* @param key property key |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
248 |
* @param flags property flags |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
249 |
* @param structure structure for objects associated with this property |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
250 |
* @param slot property field number or spill slot |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
251 |
*/ |
33690 | 252 |
public AccessorProperty(final Object key, final int flags, final Class<?> structure, final int slot) { |
16224
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
253 |
super(key, flags, slot); |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
254 |
|
23767 | 255 |
initGetterSetter(structure); |
26055
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
256 |
initializeType(); |
23767 | 257 |
} |
258 |
||
259 |
private void initGetterSetter(final Class<?> structure) { |
|
260 |
final int slot = getSlot(); |
|
16224
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
261 |
/* |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
262 |
* primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
263 |
* works in dual field mode, it only means that the property never has a primitive |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
264 |
* representation. |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
265 |
*/ |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
266 |
|
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
267 |
if (isParameter() && hasArguments()) { |
24719 | 268 |
//parameters are always stored in an object array, which may or may not be a good idea |
269 |
final MethodHandle arguments = MH.getter(LOOKUP, structure, "arguments", ScriptObject.class); |
|
18859 | 270 |
objectGetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.GET_OBJECT_TYPE); |
271 |
objectSetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.SET_OBJECT_TYPE); |
|
24719 | 272 |
primitiveGetter = null; |
273 |
primitiveSetter = null; |
|
16224
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
274 |
} else { |
24719 | 275 |
final Accessors gs = GETTERS_SETTERS.get(structure); |
276 |
objectGetter = gs.objectGetters[slot]; |
|
277 |
primitiveGetter = gs.primitiveGetters[slot]; |
|
278 |
objectSetter = gs.objectSetters[slot]; |
|
279 |
primitiveSetter = gs.primitiveSetters[slot]; |
|
16224
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
280 |
} |
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
281 |
|
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
282 |
// Always use dual fields except for single field structures |
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
283 |
assert hasDualFields() != StructureLoader.isSingleFieldStructure(structure.getName()); |
16224
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
284 |
} |
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
285 |
|
0c49ad4e3b55
8006222: Move slot from SpillProperty to Property
jlaskey
parents:
16151
diff
changeset
|
286 |
/** |
24719 | 287 |
* Constructor |
16147 | 288 |
* |
24719 | 289 |
* @param key key |
290 |
* @param flags flags |
|
291 |
* @param slot field slot index |
|
292 |
* @param owner owner of property |
|
293 |
* @param initialValue initial value to which the property can be set |
|
16147 | 294 |
*/ |
33690 | 295 |
protected AccessorProperty(final Object key, final int flags, final int slot, final ScriptObject owner, final Object initialValue) { |
24719 | 296 |
this(key, flags, owner.getClass(), slot); |
297 |
setInitialValue(owner, initialValue); |
|
298 |
} |
|
16147 | 299 |
|
24719 | 300 |
/** |
301 |
* Normal access property constructor that overrides the type |
|
302 |
* Override the initial type. Used for Object Literals |
|
16147 | 303 |
* |
24719 | 304 |
* @param key key |
305 |
* @param flags flags |
|
306 |
* @param structure structure to JO subclass |
|
307 |
* @param slot field slot index |
|
308 |
* @param initialType initial type of the property |
|
16147 | 309 |
*/ |
33690 | 310 |
public AccessorProperty(final Object key, final int flags, final Class<?> structure, final int slot, final Class<?> initialType) { |
24719 | 311 |
this(key, flags, structure, slot); |
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
312 |
setType(hasDualFields() ? initialType : Object.class); |
24719 | 313 |
} |
314 |
||
315 |
/** |
|
316 |
* Copy constructor that may change type and in that case clear the cache. Important to do that before |
|
317 |
* type change or getters will be created already stale. |
|
318 |
* |
|
319 |
* @param property property |
|
320 |
* @param newType new type |
|
321 |
*/ |
|
322 |
protected AccessorProperty(final AccessorProperty property, final Class<?> newType) { |
|
24727 | 323 |
super(property, property.getFlags()); |
16147 | 324 |
|
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
325 |
this.GETTER_CACHE = newType != property.getLocalType() ? new MethodHandle[NOOF_TYPES] : property.GETTER_CACHE; |
16147 | 326 |
this.primitiveGetter = property.primitiveGetter; |
327 |
this.primitiveSetter = property.primitiveSetter; |
|
328 |
this.objectGetter = property.objectGetter; |
|
329 |
this.objectSetter = property.objectSetter; |
|
330 |
||
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
331 |
setType(newType); |
24719 | 332 |
} |
333 |
||
334 |
/** |
|
335 |
* COPY constructor |
|
336 |
* |
|
337 |
* @param property source property |
|
338 |
*/ |
|
339 |
protected AccessorProperty(final AccessorProperty property) { |
|
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
340 |
this(property, property.getLocalType()); |
24719 | 341 |
} |
342 |
||
343 |
/** |
|
344 |
* Set initial value of a script object's property |
|
345 |
* @param owner owner |
|
346 |
* @param initialValue initial value |
|
347 |
*/ |
|
348 |
protected final void setInitialValue(final ScriptObject owner, final Object initialValue) { |
|
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
349 |
setType(hasDualFields() ? JSType.unboxedFieldType(initialValue) : Object.class); |
24719 | 350 |
if (initialValue instanceof Integer) { |
351 |
invokeSetter(owner, ((Integer)initialValue).intValue()); |
|
352 |
} else if (initialValue instanceof Double) { |
|
353 |
invokeSetter(owner, ((Double)initialValue).doubleValue()); |
|
354 |
} else { |
|
355 |
invokeSetter(owner, initialValue); |
|
356 |
} |
|
357 |
} |
|
358 |
||
359 |
/** |
|
360 |
* Initialize the type of a property |
|
361 |
*/ |
|
362 |
protected final void initializeType() { |
|
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
363 |
setType(!hasDualFields() ? Object.class : null); |
16147 | 364 |
} |
365 |
||
23767 | 366 |
private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException { |
367 |
s.defaultReadObject(); |
|
368 |
// Restore getters array |
|
24769 | 369 |
GETTER_CACHE = new MethodHandle[NOOF_TYPES]; |
23767 | 370 |
} |
371 |
||
16147 | 372 |
private static MethodHandle bindTo(final MethodHandle mh, final Object receiver) { |
373 |
if (mh == null) { |
|
374 |
return null; |
|
375 |
} |
|
376 |
||
377 |
return MH.dropArguments(MH.bindTo(mh, receiver), 0, Object.class); |
|
378 |
} |
|
379 |
||
380 |
@Override |
|
24719 | 381 |
public Property copy() { |
16147 | 382 |
return new AccessorProperty(this); |
383 |
} |
|
384 |
||
385 |
@Override |
|
24719 | 386 |
public Property copy(final Class<?> newType) { |
387 |
return new AccessorProperty(this, newType); |
|
388 |
} |
|
389 |
||
390 |
@Override |
|
391 |
public int getIntValue(final ScriptObject self, final ScriptObject owner) { |
|
392 |
try { |
|
393 |
return (int)getGetter(int.class).invokeExact((Object)self); |
|
394 |
} catch (final Error | RuntimeException e) { |
|
395 |
throw e; |
|
396 |
} catch (final Throwable e) { |
|
397 |
throw new RuntimeException(e); |
|
398 |
} |
|
399 |
} |
|
400 |
||
401 |
@Override |
|
402 |
public double getDoubleValue(final ScriptObject self, final ScriptObject owner) { |
|
403 |
try { |
|
404 |
return (double)getGetter(double.class).invokeExact((Object)self); |
|
405 |
} catch (final Error | RuntimeException e) { |
|
406 |
throw e; |
|
407 |
} catch (final Throwable e) { |
|
408 |
throw new RuntimeException(e); |
|
17774
0407501fa563
8014219: Make the run-octane harness more deterministic by not measuring elapsed time every iteration. Also got rid of most of the run logic in base.js and call benchmarks directly for the same purpose
lagergren
parents:
17770
diff
changeset
|
409 |
} |
24719 | 410 |
} |
17774
0407501fa563
8014219: Make the run-octane harness more deterministic by not measuring elapsed time every iteration. Also got rid of most of the run logic in base.js and call benchmarks directly for the same purpose
lagergren
parents:
17770
diff
changeset
|
411 |
|
24719 | 412 |
@Override |
413 |
public Object getObjectValue(final ScriptObject self, final ScriptObject owner) { |
|
17774
0407501fa563
8014219: Make the run-octane harness more deterministic by not measuring elapsed time every iteration. Also got rid of most of the run logic in base.js and call benchmarks directly for the same purpose
lagergren
parents:
17770
diff
changeset
|
414 |
try { |
0407501fa563
8014219: Make the run-octane harness more deterministic by not measuring elapsed time every iteration. Also got rid of most of the run logic in base.js and call benchmarks directly for the same purpose
lagergren
parents:
17770
diff
changeset
|
415 |
return getGetter(Object.class).invokeExact((Object)self); |
24719 | 416 |
} catch (final Error | RuntimeException e) { |
417 |
throw e; |
|
418 |
} catch (final Throwable e) { |
|
419 |
throw new RuntimeException(e); |
|
420 |
} |
|
421 |
} |
|
422 |
||
423 |
/** |
|
424 |
* Invoke setter for this property with a value |
|
425 |
* @param self owner |
|
426 |
* @param value value |
|
427 |
*/ |
|
428 |
protected final void invokeSetter(final ScriptObject self, final int value) { |
|
429 |
try { |
|
430 |
getSetter(int.class, self.getMap()).invokeExact((Object)self, value); |
|
431 |
} catch (final Error | RuntimeException e) { |
|
17774
0407501fa563
8014219: Make the run-octane harness more deterministic by not measuring elapsed time every iteration. Also got rid of most of the run logic in base.js and call benchmarks directly for the same purpose
lagergren
parents:
17770
diff
changeset
|
432 |
throw e; |
0407501fa563
8014219: Make the run-octane harness more deterministic by not measuring elapsed time every iteration. Also got rid of most of the run logic in base.js and call benchmarks directly for the same purpose
lagergren
parents:
17770
diff
changeset
|
433 |
} catch (final Throwable e) { |
0407501fa563
8014219: Make the run-octane harness more deterministic by not measuring elapsed time every iteration. Also got rid of most of the run logic in base.js and call benchmarks directly for the same purpose
lagergren
parents:
17770
diff
changeset
|
434 |
throw new RuntimeException(e); |
17770 | 435 |
} |
436 |
} |
|
437 |
||
24719 | 438 |
/** |
439 |
* Invoke setter for this property with a value |
|
440 |
* @param self owner |
|
441 |
* @param value value |
|
442 |
*/ |
|
443 |
protected final void invokeSetter(final ScriptObject self, final double value) { |
|
444 |
try { |
|
445 |
getSetter(double.class, self.getMap()).invokeExact((Object)self, value); |
|
446 |
} catch (final Error | RuntimeException e) { |
|
447 |
throw e; |
|
448 |
} catch (final Throwable e) { |
|
449 |
throw new RuntimeException(e); |
|
17770 | 450 |
} |
18852
604c1d681b6f
8017084: Use spill properties for large object literals
hannesw
parents:
18847
diff
changeset
|
451 |
} |
604c1d681b6f
8017084: Use spill properties for large object literals
hannesw
parents:
18847
diff
changeset
|
452 |
|
24719 | 453 |
/** |
454 |
* Invoke setter for this property with a value |
|
455 |
* @param self owner |
|
456 |
* @param value value |
|
457 |
*/ |
|
458 |
protected final void invokeSetter(final ScriptObject self, final Object value) { |
|
459 |
try { |
|
460 |
getSetter(Object.class, self.getMap()).invokeExact((Object)self, value); |
|
461 |
} catch (final Error | RuntimeException e) { |
|
462 |
throw e; |
|
463 |
} catch (final Throwable e) { |
|
464 |
throw new RuntimeException(e); |
|
18852
604c1d681b6f
8017084: Use spill properties for large object literals
hannesw
parents:
18847
diff
changeset
|
465 |
} |
24719 | 466 |
} |
467 |
||
468 |
@Override |
|
469 |
public void setValue(final ScriptObject self, final ScriptObject owner, final int value, final boolean strict) { |
|
470 |
assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable"; |
|
471 |
invokeSetter(self, value); |
|
472 |
} |
|
473 |
||
474 |
@Override |
|
475 |
public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict) { |
|
476 |
assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable"; |
|
477 |
invokeSetter(self, value); |
|
478 |
} |
|
479 |
||
480 |
@Override |
|
481 |
public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) { |
|
482 |
//this is sometimes used for bootstrapping, hence no assert. ugly. |
|
483 |
invokeSetter(self, value); |
|
18852
604c1d681b6f
8017084: Use spill properties for large object literals
hannesw
parents:
18847
diff
changeset
|
484 |
} |
604c1d681b6f
8017084: Use spill properties for large object literals
hannesw
parents:
18847
diff
changeset
|
485 |
|
604c1d681b6f
8017084: Use spill properties for large object literals
hannesw
parents:
18847
diff
changeset
|
486 |
@Override |
23767 | 487 |
void initMethodHandles(final Class<?> structure) { |
26055
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
488 |
// sanity check for structure class |
23767 | 489 |
if (!ScriptObject.class.isAssignableFrom(structure) || !StructureLoader.isStructureClass(structure.getName())) { |
490 |
throw new IllegalArgumentException(); |
|
491 |
} |
|
26055
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
492 |
// this method is overridden in SpillProperty |
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
493 |
assert !isSpill(); |
fe8be844ba50
8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents:
24880
diff
changeset
|
494 |
initGetterSetter(structure); |
23767 | 495 |
} |
496 |
||
497 |
@Override |
|
18852
604c1d681b6f
8017084: Use spill properties for large object literals
hannesw
parents:
18847
diff
changeset
|
498 |
public MethodHandle getGetter(final Class<?> type) { |
16147 | 499 |
final int i = getAccessorTypeIndex(type); |
24719 | 500 |
|
501 |
assert type == int.class || |
|
502 |
type == double.class || |
|
503 |
type == Object.class : |
|
504 |
"invalid getter type " + type + " for " + getKey(); |
|
18852
604c1d681b6f
8017084: Use spill properties for large object literals
hannesw
parents:
18847
diff
changeset
|
505 |
|
26377
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
506 |
checkUndeclared(); |
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
507 |
|
24719 | 508 |
//all this does is add a return value filter for object fields only |
24880
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
509 |
final MethodHandle[] getterCache = GETTER_CACHE; |
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
510 |
final MethodHandle cachedGetter = getterCache[i]; |
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
511 |
final MethodHandle getter; |
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
512 |
if (cachedGetter != null) { |
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
513 |
getter = cachedGetter; |
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
514 |
} else { |
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
515 |
getter = debug( |
24719 | 516 |
createGetter( |
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
517 |
getLocalType(), |
24719 | 518 |
type, |
519 |
primitiveGetter, |
|
520 |
objectGetter, |
|
521 |
INVALID_PROGRAM_POINT), |
|
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
522 |
getLocalType(), |
24719 | 523 |
type, |
524 |
"get"); |
|
24880
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
525 |
getterCache[i] = getter; |
24719 | 526 |
} |
24880
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
527 |
assert getter.type().returnType() == type && getter.type().parameterType(0) == Object.class; |
cac5f6a0a40c
8046025: AccessorProperty.getGetter is not threadsafe
attila
parents:
24769
diff
changeset
|
528 |
return getter; |
24719 | 529 |
} |
530 |
||
531 |
@Override |
|
532 |
public MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint) { |
|
533 |
// nasgen generated primitive fields like Math.PI have only one known unchangeable primitive type |
|
534 |
if (objectGetter == null) { |
|
535 |
return getOptimisticPrimitiveGetter(type, programPoint); |
|
16147 | 536 |
} |
537 |
||
26377
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
538 |
checkUndeclared(); |
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
539 |
|
24719 | 540 |
return debug( |
541 |
createGetter( |
|
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
542 |
getLocalType(), |
24719 | 543 |
type, |
544 |
primitiveGetter, |
|
545 |
objectGetter, |
|
546 |
programPoint), |
|
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
547 |
getLocalType(), |
24719 | 548 |
type, |
549 |
"get"); |
|
550 |
} |
|
551 |
||
552 |
private MethodHandle getOptimisticPrimitiveGetter(final Class<?> type, final int programPoint) { |
|
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
553 |
final MethodHandle g = getGetter(getLocalType()); |
24719 | 554 |
return MH.asType(OptimisticReturnFilters.filterOptimisticReturnValue(g, type, programPoint), g.type().changeReturnType(type)); |
16147 | 555 |
} |
556 |
||
557 |
private Property getWiderProperty(final Class<?> type) { |
|
24719 | 558 |
return copy(type); //invalidate cache of new property |
16147 | 559 |
} |
560 |
||
561 |
private PropertyMap getWiderMap(final PropertyMap oldMap, final Property newProperty) { |
|
562 |
final PropertyMap newMap = oldMap.replaceProperty(this, newProperty); |
|
563 |
assert oldMap.size() > 0; |
|
564 |
assert newMap.size() == oldMap.size(); |
|
565 |
return newMap; |
|
566 |
} |
|
567 |
||
26377
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
568 |
private void checkUndeclared() { |
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
569 |
if ((getFlags() & NEEDS_DECLARATION) != 0) { |
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
570 |
// a lexically defined variable that hasn't seen its declaration - throw ReferenceError |
33690 | 571 |
throw ECMAErrors.referenceError("not.defined", getKey().toString()); |
26377
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
572 |
} |
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
573 |
} |
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
574 |
|
16147 | 575 |
// the final three arguments are for debug printout purposes only |
576 |
@SuppressWarnings("unused") |
|
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
577 |
private static Object replaceMap(final Object sobj, final PropertyMap newMap) { |
16147 | 578 |
((ScriptObject)sobj).setMap(newMap); |
579 |
return sobj; |
|
580 |
} |
|
581 |
||
24738
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24734
diff
changeset
|
582 |
@SuppressWarnings("unused") |
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
583 |
private static Object invalidateSwitchPoint(final AccessorProperty property, final Object obj) { |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
584 |
if (!property.builtinSwitchPoint.hasBeenInvalidated()) { |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
585 |
SwitchPoint.invalidateAll(new SwitchPoint[] { property.builtinSwitchPoint }); |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
586 |
} |
24738
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24734
diff
changeset
|
587 |
return obj; |
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24734
diff
changeset
|
588 |
} |
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24734
diff
changeset
|
589 |
|
16147 | 590 |
private MethodHandle generateSetter(final Class<?> forType, final Class<?> type) { |
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
591 |
return debug(createSetter(forType, type, primitiveSetter, objectSetter), getLocalType(), type, "set"); |
16147 | 592 |
} |
593 |
||
24719 | 594 |
/** |
595 |
* Is this property of the undefined type? |
|
596 |
* @return true if undefined |
|
597 |
*/ |
|
598 |
protected final boolean isUndefined() { |
|
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
599 |
return getLocalType() == null; |
16147 | 600 |
} |
601 |
||
602 |
@Override |
|
36023 | 603 |
public boolean hasNativeSetter() { |
604 |
return objectSetter != null; |
|
605 |
} |
|
606 |
||
607 |
@Override |
|
16147 | 608 |
public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) { |
26377
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
609 |
checkUndeclared(); |
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
610 |
|
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
611 |
final int typeIndex = getAccessorTypeIndex(type); |
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
612 |
final int currentTypeIndex = getAccessorTypeIndex(getLocalType()); |
16147 | 613 |
|
614 |
//if we are asking for an object setter, but are still a primitive type, we might try to box it |
|
17513 | 615 |
MethodHandle mh; |
26377
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
616 |
if (needsInvalidator(typeIndex, currentTypeIndex)) { |
16147 | 617 |
final Property newProperty = getWiderProperty(type); |
618 |
final PropertyMap newMap = getWiderMap(currentMap, newProperty); |
|
24734
da070553a8e1
8038799: Guard and unbox boxed primitives types on setting them in Properties to avoid megamorphisism
lagergren
parents:
24733
diff
changeset
|
619 |
|
16147 | 620 |
final MethodHandle widerSetter = newProperty.getSetter(type, newMap); |
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
621 |
final Class<?> ct = getLocalType(); |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
622 |
mh = MH.filterArguments(widerSetter, 0, MH.insertArguments(debugReplace(ct, type, currentMap, newMap) , 1, newMap)); |
24734
da070553a8e1
8038799: Guard and unbox boxed primitives types on setting them in Properties to avoid megamorphisism
lagergren
parents:
24733
diff
changeset
|
623 |
if (ct != null && ct.isPrimitive() && !type.isPrimitive()) { |
da070553a8e1
8038799: Guard and unbox boxed primitives types on setting them in Properties to avoid megamorphisism
lagergren
parents:
24733
diff
changeset
|
624 |
mh = ObjectClassGenerator.createGuardBoxedPrimitiveSetter(ct, generateSetter(ct, ct), mh); |
16147 | 625 |
} |
17513 | 626 |
} else { |
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
627 |
final Class<?> forType = isUndefined() ? type : getLocalType(); |
24749
1549c85f8200
8041625: AccessorProperty currentType must only by Object.class when non-primitive, and scoping followup problem for lazily generated with bodies
lagergren
parents:
24745
diff
changeset
|
628 |
mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type); |
16147 | 629 |
} |
630 |
||
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
631 |
if (isBuiltin()) { |
33690 | 632 |
mh = MH.filterArguments(mh, 0, debugInvalidate(MH.insertArguments(INVALIDATE_SP, 0, this), getKey().toString())); |
24738
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24734
diff
changeset
|
633 |
} |
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24734
diff
changeset
|
634 |
|
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
635 |
assert mh.type().returnType() == void.class : mh.type(); |
24719 | 636 |
|
17770 | 637 |
return mh; |
16147 | 638 |
} |
639 |
||
640 |
@Override |
|
24719 | 641 |
public final boolean canChangeType() { |
29834
f678f348c947
8067215: Disable dual fields when not using optimistic types
hannesw
parents:
27307
diff
changeset
|
642 |
if (!hasDualFields()) { |
16147 | 643 |
return false; |
644 |
} |
|
26377
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
645 |
// Return true for currently undefined even if non-writable/configurable to allow initialization of ES6 CONST. |
27307
62ed492cbe63
8062401: User accessors require boxing and do not support optimistic types
hannesw
parents:
26768
diff
changeset
|
646 |
return getLocalType() == null || (getLocalType() != Object.class && (isConfigurable() || isWritable())); |
16147 | 647 |
} |
648 |
||
26377
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
649 |
private boolean needsInvalidator(final int typeIndex, final int currentTypeIndex) { |
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
26068
diff
changeset
|
650 |
return canChangeType() && typeIndex > currentTypeIndex; |
16147 | 651 |
} |
652 |
||
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
653 |
private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) { |
26060 | 654 |
if (!Context.DEBUG || !Global.hasInstance()) { |
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
655 |
return mh; |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
656 |
} |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
657 |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
658 |
final Context context = Context.getContextTrusted(); |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
659 |
assert context != null; |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
660 |
|
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
661 |
return context.addLoggingToHandle( |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
662 |
ObjectClassGenerator.class, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
663 |
Level.INFO, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
664 |
mh, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
665 |
0, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
666 |
true, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
667 |
new Supplier<String>() { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
668 |
@Override |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
669 |
public String get() { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
670 |
return tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", slot=" + getSlot() + " " + getClass().getSimpleName() + " forType=" + stripName(forType) + ", type=" + stripName(type) + ')'; |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
671 |
} |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
672 |
}); |
16147 | 673 |
} |
674 |
||
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
675 |
private MethodHandle debugReplace(final Class<?> oldType, final Class<?> newType, final PropertyMap oldMap, final PropertyMap newMap) { |
26060 | 676 |
if (!Context.DEBUG || !Global.hasInstance()) { |
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
677 |
return REPLACE_MAP; |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
678 |
} |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
679 |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
680 |
final Context context = Context.getContextTrusted(); |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
681 |
assert context != null; |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
682 |
|
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
683 |
MethodHandle mh = context.addLoggingToHandle( |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
684 |
ObjectClassGenerator.class, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
685 |
REPLACE_MAP, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
686 |
new Supplier<String>() { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
687 |
@Override |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
688 |
public String get() { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
689 |
return "Type change for '" + getKey() + "' " + oldType + "=>" + newType; |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
690 |
} |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
691 |
}); |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
692 |
|
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
693 |
mh = context.addLoggingToHandle( |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
694 |
ObjectClassGenerator.class, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
695 |
Level.FINEST, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
696 |
mh, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
697 |
Integer.MAX_VALUE, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
698 |
false, |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
699 |
new Supplier<String>() { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
700 |
@Override |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
701 |
public String get() { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
702 |
return "Setting map " + Debug.id(oldMap) + " => " + Debug.id(newMap) + " " + oldMap + " => " + newMap; |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
703 |
} |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
704 |
}); |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
705 |
return mh; |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
706 |
} |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
707 |
|
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
708 |
private static MethodHandle debugInvalidate(final MethodHandle invalidator, final String key) { |
26060 | 709 |
if (!Context.DEBUG || !Global.hasInstance()) { |
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
710 |
return invalidator; |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
711 |
} |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
712 |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
713 |
final Context context = Context.getContextTrusted(); |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
714 |
assert context != null; |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
715 |
|
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
716 |
return context.addLoggingToHandle( |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
717 |
ObjectClassGenerator.class, |
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
718 |
invalidator, |
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
719 |
new Supplier<String>() { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
720 |
@Override |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
721 |
public String get() { |
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26646
diff
changeset
|
722 |
return "Field change callback for " + key + " triggered "; |
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
723 |
} |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
724 |
}); |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
725 |
} |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
726 |
|
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
727 |
private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) { |
24719 | 728 |
return MH.findStatic(LOOKUP, AccessorProperty.class, name, MH.type(rtype, types)); |
16147 | 729 |
} |
730 |
} |