提交 d20ffa8b 编写于 作者: S sundar

8020015: shared PropertyMaps should not be used without duplication

Reviewed-by: hannesw, attila
上级 5a118da3
......@@ -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);
}
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
if (! env._no_java) {
initJavaAccess();
}
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();
static PropertyMap getInitialMap() {
return map$;
}
AnonymousFunction() {
super("", GlobalFunctions.ANONYMOUS, nasgenmap$$, null);
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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册