mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-16 10:53:31 +00:00
8020015: shared PropertyMaps should not be used without duplication
Reviewed-by: hannesw, attila
This commit is contained in:
parent
fa6c5ef45f
commit
0a7fda8dbe
@ -42,7 +42,8 @@
|
||||
destdir="${build.classes.dir}"
|
||||
classpath="${javac.classpath}"
|
||||
debug="${javac.debug}"
|
||||
includeantruntime="false">
|
||||
includeantruntime="false" fork="true">
|
||||
<compilerarg value="-J-Djava.ext.dirs="/>
|
||||
<compilerarg value="-Xlint:unchecked"/>
|
||||
<compilerarg value="-Xlint:deprecation"/>
|
||||
<compilerarg value="-XDignore.symbol.file"/>
|
||||
|
||||
@ -37,14 +37,24 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.GETTER_PREFIX;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.LOOKUP_NEWPROPERTY;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.LOOKUP_NEWPROPERTY_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.LOOKUP_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_FIELD_NAME;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_NEWMAP;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_NEWMAP_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.LIST_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_INIT_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC;
|
||||
@ -161,17 +171,30 @@ public class ClassGenerator {
|
||||
return new MethodGenerator(mv, access, name, desc);
|
||||
}
|
||||
|
||||
static void emitStaticInitPrefix(final MethodGenerator mi, final String className) {
|
||||
static void emitStaticInitPrefix(final MethodGenerator mi, final String className, final int memberCount) {
|
||||
mi.visitCode();
|
||||
mi.pushNull();
|
||||
mi.putStatic(className, MAP_FIELD_NAME, MAP_DESC);
|
||||
mi.invokeStatic(MAP_TYPE, MAP_NEWMAP, MAP_NEWMAP_DESC);
|
||||
// stack: PropertyMap
|
||||
if (memberCount > 0) {
|
||||
// new ArrayList(int)
|
||||
mi.newObject(ARRAYLIST_TYPE);
|
||||
mi.dup();
|
||||
mi.push(memberCount);
|
||||
mi.invokeSpecial(ARRAYLIST_TYPE, INIT, ARRAYLIST_INIT_DESC);
|
||||
// stack: ArrayList
|
||||
} else {
|
||||
// java.util.Collections.EMPTY_LIST
|
||||
mi.getStatic(COLLECTIONS_TYPE, COLLECTIONS_EMPTY_LIST, LIST_DESC);
|
||||
// stack List
|
||||
}
|
||||
}
|
||||
|
||||
static void emitStaticInitSuffix(final MethodGenerator mi, final String className) {
|
||||
// stack: PropertyMap
|
||||
mi.putStatic(className, MAP_FIELD_NAME, MAP_DESC);
|
||||
// stack: Collection
|
||||
// pmap = PropertyMap.newMap(Collection<Property>);
|
||||
mi.invokeStatic(PROPERTYMAP_TYPE, PROPERTYMAP_NEWMAP, PROPERTYMAP_NEWMAP_DESC);
|
||||
// pmap.setIsShared();
|
||||
mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_SETISSHARED, PROPERTYMAP_SETISSHARED_DESC);
|
||||
// $nasgenmap$ = pmap;
|
||||
mi.putStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
|
||||
mi.returnVoid();
|
||||
mi.computeMaxs();
|
||||
mi.visitEnd();
|
||||
@ -235,9 +258,9 @@ public class ClassGenerator {
|
||||
}
|
||||
|
||||
static void addMapField(final ClassVisitor cv) {
|
||||
// add a MAP static field
|
||||
// add a PropertyMap static field
|
||||
final FieldVisitor fv = cv.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL,
|
||||
MAP_FIELD_NAME, MAP_DESC, null, null);
|
||||
PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC, null, null);
|
||||
if (fv != null) {
|
||||
fv.visitEnd();
|
||||
}
|
||||
@ -278,7 +301,11 @@ public class ClassGenerator {
|
||||
|
||||
static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo memInfo) {
|
||||
final String propertyName = memInfo.getName();
|
||||
// stack: PropertyMap
|
||||
// stack: Collection
|
||||
// dup of Collection instance
|
||||
mi.dup();
|
||||
|
||||
// property = AccessorProperty.create(key, flags, getter, setter);
|
||||
mi.loadLiteral(propertyName);
|
||||
// setup flags
|
||||
mi.push(memInfo.getAttributes());
|
||||
@ -292,13 +319,21 @@ public class ClassGenerator {
|
||||
javaName = SETTER_PREFIX + memInfo.getJavaName();
|
||||
mi.visitLdcInsn(new Handle(H_INVOKEVIRTUAL, className, javaName, setterDesc(memInfo)));
|
||||
}
|
||||
mi.invokeStatic(LOOKUP_TYPE, LOOKUP_NEWPROPERTY, LOOKUP_NEWPROPERTY_DESC);
|
||||
// stack: PropertyMap
|
||||
mi.invokeStatic(ACCESSORPROPERTY_TYPE, ACCESSORPROPERTY_CREATE, ACCESSORPROPERTY_CREATE_DESC);
|
||||
// boolean Collection.add(property)
|
||||
mi.invokeInterface(COLLECTION_TYPE, COLLECTION_ADD, COLLECTION_ADD_DESC);
|
||||
// pop return value of Collection.add
|
||||
mi.pop();
|
||||
// stack: Collection
|
||||
}
|
||||
|
||||
static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo getter, final MemberInfo setter) {
|
||||
final String propertyName = getter.getName();
|
||||
// stack: PropertyMap
|
||||
// stack: Collection
|
||||
// dup of Collection instance
|
||||
mi.dup();
|
||||
|
||||
// property = AccessorProperty.create(key, flags, getter, setter);
|
||||
mi.loadLiteral(propertyName);
|
||||
// setup flags
|
||||
mi.push(getter.getAttributes());
|
||||
@ -312,8 +347,12 @@ public class ClassGenerator {
|
||||
mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className,
|
||||
setter.getJavaName(), setter.getJavaDesc()));
|
||||
}
|
||||
mi.invokeStatic(LOOKUP_TYPE, LOOKUP_NEWPROPERTY, LOOKUP_NEWPROPERTY_DESC);
|
||||
// stack: PropertyMap
|
||||
mi.invokeStatic(ACCESSORPROPERTY_TYPE, ACCESSORPROPERTY_CREATE, ACCESSORPROPERTY_CREATE_DESC);
|
||||
// boolean Collection.add(property)
|
||||
mi.invokeInterface(COLLECTION_TYPE, COLLECTION_ADD, COLLECTION_ADD_DESC);
|
||||
// pop return value of Collection.add
|
||||
mi.pop();
|
||||
// stack: Collection
|
||||
}
|
||||
|
||||
static ScriptClassInfo getScriptClassInfo(final String fileName) throws IOException {
|
||||
|
||||
@ -32,11 +32,11 @@ import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.CONSTRUCTOR_SUFFIX;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DUPLICATE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DUPLICATE_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_FIELD_NAME;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC;
|
||||
@ -129,7 +129,7 @@ public class ConstructorGenerator extends ClassGenerator {
|
||||
|
||||
private void emitStaticInitializer() {
|
||||
final MethodGenerator mi = makeStaticInitializer();
|
||||
emitStaticInitPrefix(mi, className);
|
||||
emitStaticInitPrefix(mi, className, memberCount);
|
||||
|
||||
for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
|
||||
if (memInfo.isConstructorFunction() || memInfo.isConstructorProperty()) {
|
||||
@ -170,10 +170,10 @@ public class ConstructorGenerator extends ClassGenerator {
|
||||
|
||||
private void loadMap(final MethodGenerator mi) {
|
||||
if (memberCount > 0) {
|
||||
mi.getStatic(className, MAP_FIELD_NAME, MAP_DESC);
|
||||
mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
|
||||
// make sure we use duplicated PropertyMap so that original map
|
||||
// stays intact and so can be used for many globals in same context
|
||||
mi.invokeVirtual(MAP_TYPE, MAP_DUPLICATE, MAP_DUPLICATE_DESC);
|
||||
// stays intact and so can be used for many globals.
|
||||
mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -57,6 +57,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.IALOAD;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.IASTORE;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
|
||||
@ -347,6 +348,10 @@ public class MethodGenerator extends MethodVisitor {
|
||||
}
|
||||
|
||||
// invokes, field get/sets
|
||||
void invokeInterface(final String owner, final String method, final String desc) {
|
||||
super.visitMethodInsn(INVOKEINTERFACE, owner, method, desc);
|
||||
}
|
||||
|
||||
void invokeVirtual(final String owner, final String method, final String desc) {
|
||||
super.visitMethodInsn(INVOKEVIRTUAL, owner, method, desc);
|
||||
}
|
||||
|
||||
@ -30,11 +30,11 @@ import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DUPLICATE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DUPLICATE_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_FIELD_NAME;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE_SUFFIX;
|
||||
@ -67,6 +67,7 @@ public class PrototypeGenerator extends ClassGenerator {
|
||||
// add <clinit>
|
||||
emitStaticInitializer();
|
||||
}
|
||||
|
||||
// add <init>
|
||||
emitConstructor();
|
||||
|
||||
@ -106,7 +107,7 @@ public class PrototypeGenerator extends ClassGenerator {
|
||||
|
||||
private void emitStaticInitializer() {
|
||||
final MethodGenerator mi = makeStaticInitializer();
|
||||
emitStaticInitPrefix(mi, className);
|
||||
emitStaticInitPrefix(mi, className, memberCount);
|
||||
for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
|
||||
if (memInfo.isPrototypeFunction() || memInfo.isPrototypeProperty()) {
|
||||
linkerAddGetterSetter(mi, className, memInfo);
|
||||
@ -124,10 +125,10 @@ public class PrototypeGenerator extends ClassGenerator {
|
||||
mi.loadThis();
|
||||
if (memberCount > 0) {
|
||||
// call "super(map$)"
|
||||
mi.getStatic(className, MAP_FIELD_NAME, MAP_DESC);
|
||||
mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
|
||||
// make sure we use duplicated PropertyMap so that original map
|
||||
// stays intact and so can be used for many globals in same context
|
||||
mi.invokeVirtual(MAP_TYPE, MAP_DUPLICATE, MAP_DUPLICATE_DESC);
|
||||
// stays intact and so can be used for many global.
|
||||
mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC);
|
||||
mi.invokeSpecial(PROTOTYPEOBJECT_TYPE, INIT, SCRIPTOBJECT_INIT_DESC);
|
||||
// initialize Function type fields
|
||||
initFunctionFields(mi);
|
||||
|
||||
@ -37,10 +37,7 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.$CLINIT$;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.CLINIT;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_FIELD_NAME;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_INIT_DESC;
|
||||
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_TYPE;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
@ -159,14 +156,7 @@ public class ScriptClassInstrumentor extends ClassVisitor {
|
||||
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
|
||||
if (isConstructor && opcode == INVOKESPECIAL &&
|
||||
INIT.equals(name) && SCRIPTOBJECT_TYPE.equals(owner)) {
|
||||
|
||||
// replace call to empty super-constructor with one passing PropertyMap argument
|
||||
if (DEFAULT_INIT_DESC.equals(desc)) {
|
||||
super.visitFieldInsn(GETSTATIC, scriptClassInfo.getJavaName(), MAP_FIELD_NAME, MAP_DESC);
|
||||
super.visitMethodInsn(INVOKESPECIAL, SCRIPTOBJECT_TYPE, INIT, SCRIPTOBJECT_INIT_DESC);
|
||||
} else {
|
||||
super.visitMethodInsn(opcode, owner, name, desc);
|
||||
}
|
||||
super.visitMethodInsn(opcode, owner, name, desc);
|
||||
|
||||
if (memberCount > 0) {
|
||||
// initialize @Property fields if needed
|
||||
@ -256,7 +246,7 @@ public class ScriptClassInstrumentor extends ClassVisitor {
|
||||
}
|
||||
// Now generate $clinit$
|
||||
final MethodGenerator mi = ClassGenerator.makeStaticInitializer(this, $CLINIT$);
|
||||
ClassGenerator.emitStaticInitPrefix(mi, className);
|
||||
ClassGenerator.emitStaticInitPrefix(mi, className, memberCount);
|
||||
if (memberCount > 0) {
|
||||
for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
|
||||
if (memInfo.isInstanceProperty() || memInfo.isInstanceFunction()) {
|
||||
|
||||
@ -27,10 +27,14 @@ package jdk.nashorn.internal.tools.nasgen;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import jdk.internal.org.objectweb.asm.Type;
|
||||
import jdk.nashorn.internal.lookup.Lookup;
|
||||
import jdk.nashorn.internal.objects.PrototypeObject;
|
||||
import jdk.nashorn.internal.objects.ScriptFunctionImpl;
|
||||
import jdk.nashorn.internal.runtime.AccessorProperty;
|
||||
import jdk.nashorn.internal.runtime.PropertyMap;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
@ -40,15 +44,41 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
public interface StringConstants {
|
||||
// standard jdk types, methods
|
||||
static final Type TYPE_METHOD = Type.getType(Method.class);
|
||||
static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class);
|
||||
static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class);
|
||||
static final Type TYPE_OBJECT = Type.getType(Object.class);
|
||||
static final Type TYPE_CLASS = Type.getType(Class.class);
|
||||
static final Type TYPE_STRING = Type.getType(String.class);
|
||||
static final Type TYPE_COLLECTION = Type.getType(Collection.class);
|
||||
static final Type TYPE_COLLECTIONS = Type.getType(Collections.class);
|
||||
static final Type TYPE_ARRAYLIST = Type.getType(ArrayList.class);
|
||||
static final Type TYPE_LIST = Type.getType(List.class);
|
||||
|
||||
// Nashorn types
|
||||
static final Type TYPE_LOOKUP = Type.getType(Lookup.class);
|
||||
static final String CLINIT = "<clinit>";
|
||||
static final String INIT = "<init>";
|
||||
static final String DEFAULT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE);
|
||||
|
||||
static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName();
|
||||
static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName();
|
||||
static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor();
|
||||
static final String OBJECT_ARRAY_DESC = Type.getDescriptor(Object[].class);
|
||||
static final String ARRAYLIST_TYPE = TYPE_ARRAYLIST.getInternalName();
|
||||
static final String COLLECTION_TYPE = TYPE_COLLECTION.getInternalName();
|
||||
static final String COLLECTIONS_TYPE = TYPE_COLLECTIONS.getInternalName();
|
||||
|
||||
// java.util.Collection.add(Object)
|
||||
static final String COLLECTION_ADD = "add";
|
||||
static final String COLLECTION_ADD_DESC = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, TYPE_OBJECT);
|
||||
// java.util.ArrayList.<init>(int)
|
||||
static final String ARRAYLIST_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE);
|
||||
// java.util.Collections.EMPTY_LIST
|
||||
static final String COLLECTIONS_EMPTY_LIST = "EMPTY_LIST";
|
||||
static final String LIST_DESC = TYPE_LIST.getDescriptor();
|
||||
|
||||
// Nashorn types, methods
|
||||
static final Type TYPE_ACCESSORPROPERTY = Type.getType(AccessorProperty.class);
|
||||
static final Type TYPE_PROPERTYMAP = Type.getType(PropertyMap.class);
|
||||
static final Type TYPE_PROTOTYPEOBJECT = Type.getType(PrototypeObject.class);
|
||||
static final Type TYPE_SCRIPTFUNCTION = Type.getType(ScriptFunction.class);
|
||||
@ -57,52 +87,56 @@ public interface StringConstants {
|
||||
|
||||
static final String PROTOTYPE_SUFFIX = "$Prototype";
|
||||
static final String CONSTRUCTOR_SUFFIX = "$Constructor";
|
||||
|
||||
// This field name is known to Nashorn runtime (Context).
|
||||
// Synchronize the name change, if needed at all.
|
||||
static final String MAP_FIELD_NAME = "$nasgenmap$";
|
||||
static final String PROPERTYMAP_FIELD_NAME = "$nasgenmap$";
|
||||
static final String $CLINIT$ = "$clinit$";
|
||||
static final String CLINIT = "<clinit>";
|
||||
static final String INIT = "<init>";
|
||||
static final String DEFAULT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE);
|
||||
|
||||
static final String SCRIPTOBJECT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_PROPERTYMAP);
|
||||
// AccessorProperty
|
||||
static final String ACCESSORPROPERTY_TYPE = TYPE_ACCESSORPROPERTY.getInternalName();
|
||||
static final String ACCESSORPROPERTY_CREATE = "create";
|
||||
static final String ACCESSORPROPERTY_CREATE_DESC =
|
||||
Type.getMethodDescriptor(TYPE_ACCESSORPROPERTY, TYPE_STRING, Type.INT_TYPE, TYPE_METHODHANDLE, TYPE_METHODHANDLE);
|
||||
|
||||
static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName();
|
||||
// PropertyMap
|
||||
static final String PROPERTYMAP_TYPE = TYPE_PROPERTYMAP.getInternalName();
|
||||
static final String PROPERTYMAP_DESC = TYPE_PROPERTYMAP.getDescriptor();
|
||||
static final String PROPERTYMAP_NEWMAP = "newMap";
|
||||
static final String PROPERTYMAP_NEWMAP_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP, TYPE_COLLECTION);
|
||||
static final String PROPERTYMAP_DUPLICATE = "duplicate";
|
||||
static final String PROPERTYMAP_DUPLICATE_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
|
||||
static final String PROPERTYMAP_SETISSHARED = "setIsShared";
|
||||
static final String PROPERTYMAP_SETISSHARED_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
|
||||
|
||||
static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName();
|
||||
static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor();
|
||||
static final String OBJECT_ARRAY_DESC = Type.getDescriptor(Object[].class);
|
||||
// PrototypeObject
|
||||
static final String PROTOTYPEOBJECT_TYPE = TYPE_PROTOTYPEOBJECT.getInternalName();
|
||||
static final String PROTOTYPEOBJECT_SETCONSTRUCTOR = "setConstructor";
|
||||
static final String PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT, TYPE_OBJECT);
|
||||
|
||||
// ScriptFunction
|
||||
static final String SCRIPTFUNCTION_TYPE = TYPE_SCRIPTFUNCTION.getInternalName();
|
||||
static final String SCRIPTFUNCTION_SETARITY = "setArity";
|
||||
static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE);
|
||||
static final String SCRIPTFUNCTION_SETPROTOTYPE = "setPrototype";
|
||||
static final String SCRIPTFUNCTION_SETPROTOTYPE_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT);
|
||||
|
||||
// ScriptFunctionImpl
|
||||
static final String SCRIPTFUNCTIONIMPL_TYPE = TYPE_SCRIPTFUNCTIONIMPL.getInternalName();
|
||||
static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION = "makeFunction";
|
||||
static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC =
|
||||
Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE);
|
||||
static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC =
|
||||
Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY);
|
||||
|
||||
static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 =
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY);
|
||||
static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 =
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_METHODHANDLE_ARRAY);
|
||||
static final String SCRIPTFUNCTION_SETARITY = "setArity";
|
||||
static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE);
|
||||
static final String SCRIPTFUNCTION_SETPROTOTYPE = "setPrototype";
|
||||
static final String SCRIPTFUNCTION_SETPROTOTYPE_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT);
|
||||
static final String PROTOTYPEOBJECT_TYPE = TYPE_PROTOTYPEOBJECT.getInternalName();
|
||||
static final String PROTOTYPEOBJECT_SETCONSTRUCTOR = "setConstructor";
|
||||
static final String PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT, TYPE_OBJECT);
|
||||
|
||||
// ScriptObject
|
||||
static final String SCRIPTOBJECT_TYPE = TYPE_SCRIPTOBJECT.getInternalName();
|
||||
static final String MAP_TYPE = TYPE_PROPERTYMAP.getInternalName();
|
||||
static final String MAP_DESC = TYPE_PROPERTYMAP.getDescriptor();
|
||||
static final String MAP_NEWMAP = "newMap";
|
||||
static final String MAP_NEWMAP_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
|
||||
static final String MAP_DUPLICATE = "duplicate";
|
||||
static final String MAP_DUPLICATE_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
|
||||
static final String LOOKUP_TYPE = TYPE_LOOKUP.getInternalName();
|
||||
static final String LOOKUP_NEWPROPERTY = "newProperty";
|
||||
static final String LOOKUP_NEWPROPERTY_DESC =
|
||||
Type.getMethodDescriptor(TYPE_PROPERTYMAP, TYPE_PROPERTYMAP, TYPE_STRING, Type.INT_TYPE, TYPE_METHODHANDLE, TYPE_METHODHANDLE);
|
||||
static final String SCRIPTOBJECT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_PROPERTYMAP);
|
||||
|
||||
static final String GETTER_PREFIX = "G$";
|
||||
static final String SETTER_PREFIX = "S$";
|
||||
|
||||
|
||||
@ -60,16 +60,8 @@
|
||||
<copy todir="${build.dir}/to_be_instrumented">
|
||||
<fileset dir="${build.classes.dir}">
|
||||
<include name="**/*.class"/>
|
||||
<include name="**/*.clazz"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<move todir="${build.dir}/to_be_instrumented/jdk/nashorn/internal/objects">
|
||||
<fileset dir="${build.dir}/to_be_instrumented/jdk/nashorn/internal/objects">
|
||||
<include name="**/*.clazz"/>
|
||||
</fileset>
|
||||
<mapper type="glob" from="*.clazz" to="*.class"/>
|
||||
</move>
|
||||
</target>
|
||||
|
||||
<target name="generate-cc-template" depends="prepare-to-be-instrumented" description="Generates code coverage template for dynamic CC" if="cc.generate.template">
|
||||
|
||||
@ -200,6 +200,9 @@ test262-test-sys-prop.test.failed.list.file=${build.dir}/test/failedTests
|
||||
|
||||
# test262 test frameworks
|
||||
test262-test-sys-prop.test.js.framework=\
|
||||
--class-cache-size=0 \
|
||||
--no-java \
|
||||
--no-typed-arrays \
|
||||
-timezone=PST \
|
||||
${test.script.dir}/test262.js \
|
||||
${test262.dir}/test/harness/framework.js \
|
||||
|
||||
@ -124,44 +124,6 @@ public final class Lookup {
|
||||
throw typeError("strict.getter.setter.poison", ScriptRuntime.safeToString(self));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Property}
|
||||
*
|
||||
* @param map property map
|
||||
* @param key property key
|
||||
* @param flags property flags
|
||||
* @param propertyGetter getter for property if available, null otherwise
|
||||
* @param propertySetter setter for property if available, null otherwise
|
||||
*
|
||||
* @return new property map, representing {@code PropertyMap} with the new property added to it
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
public static PropertyMap newProperty(final PropertyMap map, final String key, final int flags, final MethodHandle propertyGetter, final MethodHandle propertySetter) {
|
||||
MethodHandle getter = propertyGetter;
|
||||
MethodHandle setter = propertySetter;
|
||||
|
||||
// TODO: this is temporary code. This code exists to support reflective
|
||||
// field reader/writer handles generated by "unreflect" lookup.
|
||||
|
||||
switch (getter.type().parameterCount()) {
|
||||
case 0:
|
||||
// A static field reader, so drop the 'self' argument.
|
||||
getter = MH.dropArguments(getter, 0, Object.class);
|
||||
if (setter != null) {
|
||||
setter = MH.dropArguments(setter, 0, Object.class);
|
||||
}
|
||||
// fall through
|
||||
case 1:
|
||||
// standard getter that accepts 'self'.
|
||||
break;
|
||||
default:
|
||||
// Huh!! something wrong..
|
||||
throw new IllegalArgumentException("getter/setter has wrong arguments");
|
||||
}
|
||||
|
||||
return map.newProperty(key, flags, -1, getter, setter);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method filters primitive return types using JavaScript semantics. For example,
|
||||
* an (int) cast of a double in Java land is not the same thing as invoking toInt32 on it.
|
||||
|
||||
@ -46,14 +46,17 @@ abstract class ArrayBufferView extends ScriptObject {
|
||||
return $nasgenmap$;
|
||||
}
|
||||
|
||||
ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
|
||||
private ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength, final Global global) {
|
||||
super(global.getArrayBufferViewMap());
|
||||
checkConstructorArgs(buffer, byteOffset, elementLength);
|
||||
final Global global = Global.instance();
|
||||
this.setMap(global.getArrayBufferViewMap());
|
||||
this.setProto(getPrototype(global));
|
||||
this.setArray(factory().createArrayData(buffer, byteOffset, elementLength));
|
||||
}
|
||||
|
||||
ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
|
||||
this(buffer, byteOffset, elementLength, Global.instance());
|
||||
}
|
||||
|
||||
private void checkConstructorArgs(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
|
||||
if (byteOffset < 0 || elementLength < 0) {
|
||||
throw new RuntimeException("byteOffset or length must not be negative");
|
||||
|
||||
@ -43,7 +43,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
import jdk.nashorn.internal.objects.annotations.Property;
|
||||
import jdk.nashorn.internal.objects.annotations.ScriptClass;
|
||||
@ -389,6 +388,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
private PropertyMap prototypeObjectMap;
|
||||
private PropertyMap objectMap;
|
||||
private PropertyMap functionMap;
|
||||
private PropertyMap anonymousFunctionMap;
|
||||
private PropertyMap strictFunctionMap;
|
||||
private PropertyMap boundFunctionMap;
|
||||
|
||||
@ -409,7 +409,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
/**
|
||||
@ -418,14 +417,14 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
* @param context the context
|
||||
*/
|
||||
public Global(final Context context) {
|
||||
this.setContext(context);
|
||||
this.setIsScope();
|
||||
/*
|
||||
* Duplicate global's map and use it. This way the initial Map filled
|
||||
* by nasgen (referenced from static field in this class) is retained
|
||||
* 'as is'. This allows multiple globals to be used within a context.
|
||||
* 'as is' (as that one is process wide singleton.
|
||||
*/
|
||||
this.setMap(getMap().duplicate());
|
||||
super($nasgenmap$.duplicate());
|
||||
this.setContext(context);
|
||||
this.setIsScope();
|
||||
|
||||
final int cacheSize = context.getEnv()._class_cache_size;
|
||||
if (cacheSize > 0) {
|
||||
@ -1018,6 +1017,10 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
return functionMap;
|
||||
}
|
||||
|
||||
PropertyMap getAnonymousFunctionMap() {
|
||||
return anonymousFunctionMap;
|
||||
}
|
||||
|
||||
PropertyMap getStrictFunctionMap() {
|
||||
return strictFunctionMap;
|
||||
}
|
||||
@ -1538,7 +1541,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
final ScriptEnvironment env = getContext().getEnv();
|
||||
|
||||
// duplicate PropertyMaps of Native* classes
|
||||
copyInitialMaps();
|
||||
copyInitialMaps(env);
|
||||
|
||||
// initialize Function and Object constructor
|
||||
initFunctionAndObject();
|
||||
@ -1599,12 +1602,16 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
initErrorObjects();
|
||||
|
||||
// java access
|
||||
initJavaAccess();
|
||||
if (! env._no_java) {
|
||||
initJavaAccess();
|
||||
}
|
||||
|
||||
initTypedArray();
|
||||
if (! env._no_typed_arrays) {
|
||||
initTypedArray();
|
||||
}
|
||||
|
||||
if (env._scripting) {
|
||||
initScripting();
|
||||
initScripting(env);
|
||||
}
|
||||
|
||||
if (Context.DEBUG && System.getSecurityManager() == null) {
|
||||
@ -1685,7 +1692,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
this.builtinJavaApi = initConstructor("Java");
|
||||
}
|
||||
|
||||
private void initScripting() {
|
||||
private void initScripting(final ScriptEnvironment scriptEnv) {
|
||||
Object value;
|
||||
value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
|
||||
addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
|
||||
@ -1704,7 +1711,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
|
||||
// Nashorn extension: global.$OPTIONS (scripting-mode-only)
|
||||
final ScriptObject options = newObject();
|
||||
final ScriptEnvironment scriptEnv = getContext().getEnv();
|
||||
copyOptions(options, scriptEnv);
|
||||
addOwnProperty("$OPTIONS", Attribute.NOT_ENUMERABLE, options);
|
||||
|
||||
@ -1857,20 +1863,17 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
}
|
||||
}
|
||||
|
||||
private void copyInitialMaps() {
|
||||
private void copyInitialMaps(final ScriptEnvironment env) {
|
||||
this.accessorPropertyDescriptorMap = AccessorPropertyDescriptor.getInitialMap().duplicate();
|
||||
this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate();
|
||||
this.dataPropertyDescriptorMap = DataPropertyDescriptor.getInitialMap().duplicate();
|
||||
this.genericPropertyDescriptorMap = GenericPropertyDescriptor.getInitialMap().duplicate();
|
||||
this.nativeArgumentsMap = NativeArguments.getInitialMap().duplicate();
|
||||
this.nativeArrayMap = NativeArray.getInitialMap().duplicate();
|
||||
this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate();
|
||||
this.nativeBooleanMap = NativeBoolean.getInitialMap().duplicate();
|
||||
this.nativeDateMap = NativeDate.getInitialMap().duplicate();
|
||||
this.nativeErrorMap = NativeError.getInitialMap().duplicate();
|
||||
this.nativeEvalErrorMap = NativeEvalError.getInitialMap().duplicate();
|
||||
this.nativeJSAdapterMap = NativeJSAdapter.getInitialMap().duplicate();
|
||||
this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate();
|
||||
this.nativeNumberMap = NativeNumber.getInitialMap().duplicate();
|
||||
this.nativeRangeErrorMap = NativeRangeError.getInitialMap().duplicate();
|
||||
this.nativeReferenceErrorMap = NativeReferenceError.getInitialMap().duplicate();
|
||||
@ -1883,9 +1886,21 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
this.nativeURIErrorMap = NativeURIError.getInitialMap().duplicate();
|
||||
this.prototypeObjectMap = PrototypeObject.getInitialMap().duplicate();
|
||||
this.objectMap = JO.getInitialMap().duplicate();
|
||||
this.functionMap = ScriptFunctionImpl.getInitialMap();
|
||||
this.functionMap = ScriptFunctionImpl.getInitialMap().duplicate();
|
||||
this.anonymousFunctionMap = ScriptFunctionImpl.getInitialAnonymousMap().duplicate();
|
||||
this.strictFunctionMap = ScriptFunctionImpl.getInitialStrictMap().duplicate();
|
||||
this.boundFunctionMap = ScriptFunctionImpl.getInitialBoundMap().duplicate();
|
||||
|
||||
// java
|
||||
if (! env._no_java) {
|
||||
this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate();
|
||||
}
|
||||
|
||||
// typed arrays
|
||||
if (! env._no_typed_arrays) {
|
||||
this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate();
|
||||
this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate();
|
||||
}
|
||||
}
|
||||
|
||||
// Function and Object constructors are inter-dependent. Also,
|
||||
@ -1899,7 +1914,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
this.builtinFunction = (ScriptFunction)initConstructor("Function");
|
||||
|
||||
// create global anonymous function
|
||||
final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
|
||||
final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
|
||||
// need to copy over members of Function.prototype to anon function
|
||||
anon.addBoundProperties(getFunctionPrototype());
|
||||
|
||||
|
||||
@ -31,8 +31,10 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import jdk.nashorn.internal.runtime.AccessorProperty;
|
||||
import jdk.nashorn.internal.runtime.Property;
|
||||
import jdk.nashorn.internal.runtime.PropertyDescriptor;
|
||||
import jdk.nashorn.internal.runtime.PropertyMap;
|
||||
@ -41,8 +43,6 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.arrays.ArrayData;
|
||||
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
|
||||
import jdk.nashorn.internal.lookup.Lookup;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
|
||||
/**
|
||||
* ECMA 10.6 Arguments Object.
|
||||
@ -64,10 +64,10 @@ public final class NativeArguments extends ScriptObject {
|
||||
private static final PropertyMap map$;
|
||||
|
||||
static {
|
||||
PropertyMap map = PropertyMap.newMap();
|
||||
map = Lookup.newProperty(map, "length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH);
|
||||
map = Lookup.newProperty(map, "callee", Property.NOT_ENUMERABLE, G$CALLEE, S$CALLEE);
|
||||
map$ = map;
|
||||
final ArrayList<Property> properties = new ArrayList<>(2);
|
||||
properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH));
|
||||
properties.add(AccessorProperty.create("callee", Property.NOT_ENUMERABLE, G$CALLEE, S$CALLEE));
|
||||
map$ = PropertyMap.newMap(properties).setIsShared();
|
||||
}
|
||||
|
||||
static PropertyMap getInitialMap() {
|
||||
|
||||
@ -40,7 +40,6 @@ import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.PropertyMap;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
|
||||
|
||||
/**
|
||||
|
||||
@ -49,6 +49,7 @@ import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
|
||||
public final class NativeDebug extends ScriptObject {
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
private NativeDebug() {
|
||||
@ -144,7 +145,7 @@ public final class NativeDebug extends ScriptObject {
|
||||
*/
|
||||
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
|
||||
public static Object equals(final Object self, final Object obj1, final Object obj2) {
|
||||
return (obj1 != null) ? obj1.equals(obj2) : false;
|
||||
return Objects.equals(obj1, obj2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,6 +177,15 @@ public final class NativeDebug extends ScriptObject {
|
||||
return obj.getClass() + "@" + Integer.toHexString(hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property listener count for a script object
|
||||
* @return listener count
|
||||
*/
|
||||
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
|
||||
public static Object getListenerCount(final Object self, final Object obj) {
|
||||
return (obj instanceof ScriptObject)? ((ScriptObject)obj).getListenerCount() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump all Nashorn debug mode counters. Calling this may be better if
|
||||
* you want to print all counters. This way you can avoid too many callsites
|
||||
@ -197,6 +207,8 @@ public final class NativeDebug extends ScriptObject {
|
||||
out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
|
||||
out.println("PropertyMap count " + PropertyMap.getCount());
|
||||
out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
|
||||
out.println("PropertyMap shared " + PropertyMap.getSharedCount());
|
||||
out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
|
||||
out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
|
||||
out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
|
||||
out.println("PropertyMap proto history hit " + PropertyMap.getProtoHistoryHit());
|
||||
|
||||
@ -31,7 +31,6 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import jdk.nashorn.api.scripting.NashornException;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
import jdk.nashorn.internal.objects.annotations.Constructor;
|
||||
import jdk.nashorn.internal.objects.annotations.Function;
|
||||
|
||||
@ -48,7 +48,6 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
|
||||
import jdk.nashorn.internal.lookup.Lookup;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.scripts.JO;
|
||||
|
||||
/**
|
||||
|
||||
@ -60,6 +60,7 @@ public final class NativeJSON extends ScriptObject {
|
||||
ScriptFunction.class, ScriptObject.class, Object.class, Object.class);
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
private NativeJSON() {
|
||||
|
||||
@ -43,6 +43,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
public final class NativeMath extends ScriptObject {
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
private NativeMath() {
|
||||
|
||||
@ -30,14 +30,14 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import jdk.nashorn.internal.runtime.AccessorProperty;
|
||||
import jdk.nashorn.internal.runtime.Property;
|
||||
import jdk.nashorn.internal.runtime.PropertyMap;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.arrays.ArrayData;
|
||||
import jdk.nashorn.internal.lookup.Lookup;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
|
||||
/**
|
||||
* ECMA 10.6 Arguments Object.
|
||||
@ -54,14 +54,15 @@ public final class NativeStrictArguments extends ScriptObject {
|
||||
private static final PropertyMap map$;
|
||||
|
||||
static {
|
||||
PropertyMap map = PropertyMap.newMap();
|
||||
map = Lookup.newProperty(map, "length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH);
|
||||
final ArrayList<Property> properties = new ArrayList<>(1);
|
||||
properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH));
|
||||
PropertyMap map = PropertyMap.newMap(properties);
|
||||
// In strict mode, the caller and callee properties should throw TypeError
|
||||
// Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
|
||||
final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
|
||||
map = map.addProperty(map.newUserAccessors("caller", flags));
|
||||
map = map.addProperty(map.newUserAccessors("callee", flags));
|
||||
map$ = map;
|
||||
map$ = map.setIsShared();
|
||||
}
|
||||
|
||||
static PropertyMap getInitialMap() {
|
||||
|
||||
@ -30,12 +30,12 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import jdk.nashorn.internal.runtime.AccessorProperty;
|
||||
import jdk.nashorn.internal.runtime.Property;
|
||||
import jdk.nashorn.internal.runtime.PropertyMap;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.lookup.Lookup;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
|
||||
/**
|
||||
* Instances of this class serve as "prototype" object for script functions.
|
||||
@ -52,9 +52,9 @@ public class PrototypeObject extends ScriptObject {
|
||||
private static final MethodHandle SET_CONSTRUCTOR = findOwnMH("setConstructor", void.class, Object.class, Object.class);
|
||||
|
||||
static {
|
||||
PropertyMap map = PropertyMap.newMap();
|
||||
map = Lookup.newProperty(map, "constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR);
|
||||
map$ = map;
|
||||
final ArrayList<Property> properties = new ArrayList<>(1);
|
||||
properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR));
|
||||
map$ = PropertyMap.newMap(properties).setIsShared();
|
||||
}
|
||||
|
||||
static PropertyMap getInitialMap() {
|
||||
|
||||
@ -28,6 +28,7 @@ package jdk.nashorn.internal.objects;
|
||||
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.util.ArrayList;
|
||||
import jdk.nashorn.internal.runtime.GlobalFunctions;
|
||||
import jdk.nashorn.internal.runtime.Property;
|
||||
import jdk.nashorn.internal.runtime.PropertyMap;
|
||||
@ -36,6 +37,7 @@ import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunctionData;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.lookup.Lookup;
|
||||
import jdk.nashorn.internal.runtime.AccessorProperty;
|
||||
|
||||
/**
|
||||
* Concrete implementation of ScriptFunction. This sets correct map for the
|
||||
@ -57,6 +59,10 @@ public class ScriptFunctionImpl extends ScriptFunction {
|
||||
return map$;
|
||||
}
|
||||
|
||||
static PropertyMap getInitialAnonymousMap() {
|
||||
return AnonymousFunction.getInitialMap();
|
||||
}
|
||||
|
||||
static PropertyMap getInitialStrictMap() {
|
||||
return strictmodemap$;
|
||||
}
|
||||
@ -149,13 +155,18 @@ public class ScriptFunctionImpl extends ScriptFunction {
|
||||
}
|
||||
|
||||
static {
|
||||
PropertyMap map = PropertyMap.newMap();
|
||||
map = Lookup.newProperty(map, "prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE);
|
||||
map = Lookup.newProperty(map, "length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null);
|
||||
map = Lookup.newProperty(map, "name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null);
|
||||
map$ = map;
|
||||
final ArrayList<Property> properties = new ArrayList<>(3);
|
||||
properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE));
|
||||
properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null));
|
||||
properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null));
|
||||
map$ = PropertyMap.newMap(properties);
|
||||
strictmodemap$ = createStrictModeMap(map$);
|
||||
boundfunctionmap$ = createBoundFunctionMap(strictmodemap$);
|
||||
// There are order dependencies between normal map, struct map and bound map
|
||||
// We can make these 'shared' only after initialization of all three.
|
||||
map$.setIsShared();
|
||||
strictmodemap$.setIsShared();
|
||||
boundfunctionmap$.setIsShared();
|
||||
}
|
||||
|
||||
// function object representing TypeErrorThrower
|
||||
@ -201,15 +212,19 @@ public class ScriptFunctionImpl extends ScriptFunction {
|
||||
// Instance of this class is used as global anonymous function which
|
||||
// serves as Function.prototype object.
|
||||
private static class AnonymousFunction extends ScriptFunctionImpl {
|
||||
private static final PropertyMap nasgenmap$$ = PropertyMap.newMap();
|
||||
private static final PropertyMap map$ = PropertyMap.newMap().setIsShared();
|
||||
|
||||
AnonymousFunction() {
|
||||
super("", GlobalFunctions.ANONYMOUS, nasgenmap$$, null);
|
||||
static PropertyMap getInitialMap() {
|
||||
return map$;
|
||||
}
|
||||
|
||||
AnonymousFunction(final Global global) {
|
||||
super("", GlobalFunctions.ANONYMOUS, global.getAnonymousFunctionMap(), null);
|
||||
}
|
||||
}
|
||||
|
||||
static ScriptFunctionImpl newAnonymousFunction() {
|
||||
return new AnonymousFunction();
|
||||
static ScriptFunctionImpl newAnonymousFunction(final Global global) {
|
||||
return new AnonymousFunction(global);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -107,6 +107,20 @@ public class AccessorProperty extends Property {
|
||||
SPILL_ELEMENT_SETTER = MH.filterArguments(MH.arrayElementSetter(Object[].class), 0, spillGetter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new accessor property. Factory method used by nasgen generated code.
|
||||
*
|
||||
* @param key {@link Property} key.
|
||||
* @param propertyFlags {@link Property} flags.
|
||||
* @param getter {@link Property} get accessor method.
|
||||
* @param setter {@link Property} set accessor method.
|
||||
*
|
||||
* @return New {@link AccessorProperty} created.
|
||||
*/
|
||||
public static AccessorProperty create(final String key, final int propertyFlags, final MethodHandle getter, final MethodHandle setter) {
|
||||
return new AccessorProperty(key, propertyFlags, -1, getter, setter);
|
||||
}
|
||||
|
||||
/** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
|
||||
private MethodHandle primitiveGetter;
|
||||
|
||||
|
||||
@ -253,13 +253,7 @@ public final class Context {
|
||||
this.env = new ScriptEnvironment(options, out, err);
|
||||
this._strict = env._strict;
|
||||
this.appLoader = appLoader;
|
||||
this.scriptLoader = (ScriptLoader)AccessController.doPrivileged(
|
||||
new PrivilegedAction<ClassLoader>() {
|
||||
@Override
|
||||
public ClassLoader run() {
|
||||
return new ScriptLoader(sharedLoader, Context.this);
|
||||
}
|
||||
});
|
||||
this.scriptLoader = env._loader_per_compile? null : createNewLoader();
|
||||
this.errors = errors;
|
||||
|
||||
// if user passed -classpath option, make a class loader with that and set it as
|
||||
|
||||
@ -41,6 +41,7 @@ public class PropertyListenerManager implements PropertyListener {
|
||||
private static int listenersRemoved;
|
||||
|
||||
/**
|
||||
* Return aggregate listeners added to all PropertyListenerManagers
|
||||
* @return the listenersAdded
|
||||
*/
|
||||
public static int getListenersAdded() {
|
||||
@ -48,12 +49,21 @@ public class PropertyListenerManager implements PropertyListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return aggregate listeners removed from all PropertyListenerManagers
|
||||
* @return the listenersRemoved
|
||||
*/
|
||||
public static int getListenersRemoved() {
|
||||
return listenersRemoved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return listeners added to this PropertyListenerManager.
|
||||
* @return the listener count
|
||||
*/
|
||||
public final int getListenerCount() {
|
||||
return listeners != null? listeners.size() : 0;
|
||||
}
|
||||
|
||||
// Property listener management methods
|
||||
|
||||
/**
|
||||
|
||||
@ -25,11 +25,8 @@
|
||||
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import jdk.nashorn.internal.scripts.JO;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.PropertyHashMap.EMPTY_HASHMAP;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.SwitchPoint;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
@ -57,9 +54,8 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
private static final int CLONEABLE_FLAGS_MASK = 0b0000_1111;
|
||||
/** Has a listener been added to this property map. This flag is not copied when cloning a map. See {@link PropertyListener} */
|
||||
public static final int IS_LISTENER_ADDED = 0b0001_0000;
|
||||
|
||||
/** Empty map used for seed map for JO$ objects */
|
||||
private static final PropertyMap EMPTY_MAP = new PropertyMap(EMPTY_HASHMAP);
|
||||
/** Is this process wide "shared" map?. This flag is not copied when cloning a map */
|
||||
public static final int IS_SHARED = 0b0010_0000;
|
||||
|
||||
/** Map status flags. */
|
||||
private int flags;
|
||||
@ -145,16 +141,17 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates this PropertyMap instance. This is used by nasgen generated
|
||||
* prototype and constructor classes. {@link PropertyMap} used for singletons
|
||||
* like these (and global instance) are duplicated using this method and used.
|
||||
* The original filled map referenced by static fields of prototype and
|
||||
* constructor classes are not touched. This allows multiple independent global
|
||||
* instances to be used within a single context instance.
|
||||
* Duplicates this PropertyMap instance. This is used to duplicate 'shared'
|
||||
* maps {@link PropertyMap} used as process wide singletons. Shared maps are
|
||||
* duplicated for every global scope object. That way listeners, proto and property
|
||||
* histories are scoped within a global scope.
|
||||
*
|
||||
* @return Duplicated {@link PropertyMap}.
|
||||
*/
|
||||
public PropertyMap duplicate() {
|
||||
if (Context.DEBUG) {
|
||||
duplicatedCount++;
|
||||
}
|
||||
return new PropertyMap(this.properties);
|
||||
}
|
||||
|
||||
@ -172,6 +169,15 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
return new PropertyMap(newProperties, fieldCount, fieldMaximum, spillLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public property map allocator. Used by nasgen generated code.
|
||||
* @param properties Collection of initial properties.
|
||||
* @return New {@link PropertyMap}.
|
||||
*/
|
||||
public static PropertyMap newMap(final Collection<Property> properties) {
|
||||
return (properties == null || properties.isEmpty())? newMap() : newMap(properties, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a sharable empty map.
|
||||
*
|
||||
@ -199,6 +205,8 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
* @return A shared {@link SwitchPoint} for the property.
|
||||
*/
|
||||
public SwitchPoint getProtoGetSwitchPoint(final ScriptObject proto, final String key) {
|
||||
assert !isShared() : "proto SwitchPoint from a shared PropertyMap";
|
||||
|
||||
if (proto == null) {
|
||||
return null;
|
||||
}
|
||||
@ -227,6 +235,8 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
* @param property {@link Property} to invalidate.
|
||||
*/
|
||||
private void invalidateProtoGetSwitchPoint(final Property property) {
|
||||
assert !isShared() : "proto invalidation on a shared PropertyMap";
|
||||
|
||||
if (protoGetSwitches != null) {
|
||||
final String key = property.getKey();
|
||||
final SwitchPoint sp = protoGetSwitches.get(key);
|
||||
@ -240,17 +250,6 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a property to the map.
|
||||
*
|
||||
* @param property {@link Property} being added.
|
||||
*
|
||||
* @return New {@link PropertyMap} with {@link Property} added.
|
||||
*/
|
||||
public PropertyMap newProperty(final Property property) {
|
||||
return addProperty(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a property to the map, re-binding its getters and setters,
|
||||
* if available, to a given receiver. This is typically the global scope. See
|
||||
@ -261,23 +260,8 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
*
|
||||
* @return New {@link PropertyMap} with {@link Property} added.
|
||||
*/
|
||||
PropertyMap newPropertyBind(final AccessorProperty property, final ScriptObject bindTo) {
|
||||
return newProperty(new AccessorProperty(property, bindTo));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new accessor property to the map.
|
||||
*
|
||||
* @param key {@link Property} key.
|
||||
* @param propertyFlags {@link Property} flags.
|
||||
* @param slot {@link Property} slot.
|
||||
* @param getter {@link Property} get accessor method.
|
||||
* @param setter {@link Property} set accessor method.
|
||||
*
|
||||
* @return New {@link PropertyMap} with {@link AccessorProperty} added.
|
||||
*/
|
||||
public PropertyMap newProperty(final String key, final int propertyFlags, final int slot, final MethodHandle getter, final MethodHandle setter) {
|
||||
return newProperty(new AccessorProperty(key, propertyFlags, slot, getter, setter));
|
||||
PropertyMap addPropertyBind(final AccessorProperty property, final ScriptObject bindTo) {
|
||||
return addProperty(new AccessorProperty(property, bindTo));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -478,6 +462,28 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
return newMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this property map 'shared' one. Shared property map instances are
|
||||
* process wide singleton objects. A shaped map should never be added as a listener
|
||||
* to a proto object. Nor it should have history or proto history. A shared map
|
||||
* is just a template that is meant to be duplicated before use. All nasgen initialized
|
||||
* property maps are shared.
|
||||
*
|
||||
* @return this map after making it as shared
|
||||
*/
|
||||
public PropertyMap setIsShared() {
|
||||
assert !isListenerAdded() : "making PropertyMap shared after listener added";
|
||||
assert protoHistory == null : "making PropertyMap shared after associating a proto with it";
|
||||
if (Context.DEBUG) {
|
||||
sharedCount++;
|
||||
}
|
||||
|
||||
flags |= IS_SHARED;
|
||||
// clear any history on this PropertyMap, won't be used.
|
||||
history = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for any configurable properties.
|
||||
*
|
||||
@ -544,6 +550,8 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
* @param newMap {@link PropertyMap} associated with prototype.
|
||||
*/
|
||||
private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
|
||||
assert !isShared() : "proto history modified on a shared PropertyMap";
|
||||
|
||||
if (protoHistory == null) {
|
||||
protoHistory = new WeakHashMap<>();
|
||||
}
|
||||
@ -558,6 +566,8 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
* @param newMap Modified {@link PropertyMap}.
|
||||
*/
|
||||
private void addToHistory(final Property property, final PropertyMap newMap) {
|
||||
assert !isShared() : "history modified on a shared PropertyMap";
|
||||
|
||||
if (!properties.isEmpty()) {
|
||||
if (history == null) {
|
||||
history = new LinkedHashMap<>();
|
||||
@ -682,6 +692,15 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
return (flags & IS_LISTENER_ADDED) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this map shared or not.
|
||||
*
|
||||
* @return true if this map is shared.
|
||||
*/
|
||||
public boolean isShared() {
|
||||
return (flags & IS_SHARED) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if {@link PropertyMap} is extensible.
|
||||
*
|
||||
@ -745,6 +764,8 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
* @return New {@link PropertyMap} with prototype changed.
|
||||
*/
|
||||
PropertyMap changeProto(final ScriptObject oldProto, final ScriptObject newProto) {
|
||||
assert !isShared() : "proto associated with a shared PropertyMap";
|
||||
|
||||
if (oldProto == newProto) {
|
||||
return this;
|
||||
}
|
||||
@ -860,6 +881,8 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
// counters updated only in debug mode
|
||||
private static int count;
|
||||
private static int clonedCount;
|
||||
private static int sharedCount;
|
||||
private static int duplicatedCount;
|
||||
private static int historyHit;
|
||||
private static int protoInvalidations;
|
||||
private static int protoHistoryHit;
|
||||
@ -879,6 +902,20 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
|
||||
return clonedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of maps that are shared.
|
||||
*/
|
||||
public static int getSharedCount() {
|
||||
return sharedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of maps that are duplicated.
|
||||
*/
|
||||
public static int getDuplicatedCount() {
|
||||
return duplicatedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of times history was successfully used.
|
||||
*/
|
||||
|
||||
@ -119,9 +119,15 @@ public final class ScriptEnvironment {
|
||||
/** Create a new class loaded for each compilation */
|
||||
public final boolean _loader_per_compile;
|
||||
|
||||
/** Do not support Java support extensions. */
|
||||
public final boolean _no_java;
|
||||
|
||||
/** Do not support non-standard syntax extensions. */
|
||||
public final boolean _no_syntax_extensions;
|
||||
|
||||
/** Do not support typed arrays. */
|
||||
public final boolean _no_typed_arrays;
|
||||
|
||||
/** Package to which generated class files are added */
|
||||
public final String _package;
|
||||
|
||||
@ -207,7 +213,9 @@ public final class ScriptEnvironment {
|
||||
_fx = options.getBoolean("fx");
|
||||
_lazy_compilation = options.getBoolean("lazy.compilation");
|
||||
_loader_per_compile = options.getBoolean("loader.per.compile");
|
||||
_no_java = options.getBoolean("no.java");
|
||||
_no_syntax_extensions = options.getBoolean("no.syntax.extensions");
|
||||
_no_typed_arrays = options.getBoolean("no.typed.arrays");
|
||||
_package = options.getString("package");
|
||||
_parse_only = options.getBoolean("parse.only");
|
||||
_print_ast = options.getBoolean("print.ast");
|
||||
|
||||
@ -213,7 +213,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
|
||||
final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
|
||||
newMap = newMap.addProperty(prop);
|
||||
} else {
|
||||
newMap = newMap.newPropertyBind((AccessorProperty)property, source);
|
||||
newMap = newMap.addPropertyBind((AccessorProperty)property, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,6 +192,14 @@ nashorn.option.loader.per.compile = { \
|
||||
default=true \
|
||||
}
|
||||
|
||||
nashorn.option.no.java = { \
|
||||
name="--no-java", \
|
||||
short_name="-nj", \
|
||||
is_undocumented=true, \
|
||||
desc="No Java support", \
|
||||
default=false \
|
||||
}
|
||||
|
||||
nashorn.option.no.syntax.extensions = { \
|
||||
name="--no-syntax-extensions", \
|
||||
short_name="-nse", \
|
||||
@ -200,6 +208,14 @@ nashorn.option.no.syntax.extensions = { \
|
||||
default=false \
|
||||
}
|
||||
|
||||
nashorn.option.no.typed.arrays = { \
|
||||
name="--no-typed-arrays", \
|
||||
short_name="-nta", \
|
||||
is_undocumented=true, \
|
||||
desc="No Typed arrays support", \
|
||||
default=false \
|
||||
}
|
||||
|
||||
nashorn.option.package = { \
|
||||
name="--package", \
|
||||
is_undocumented=true, \
|
||||
|
||||
@ -33,7 +33,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
*/
|
||||
public class JO extends ScriptObject {
|
||||
|
||||
private static final PropertyMap map$ = PropertyMap.newMap();
|
||||
private static final PropertyMap map$ = PropertyMap.newMap().setIsShared();
|
||||
|
||||
/**
|
||||
* Returns the initial property map to be used.
|
||||
|
||||
@ -435,6 +435,10 @@ public class Shell {
|
||||
break;
|
||||
}
|
||||
|
||||
if (source.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object res;
|
||||
try {
|
||||
res = context.eval(global, source, global, "<shell>", env._strict);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user