8011629: Object.defineProperty performance issue
authorjlaskey
Wed, 03 Jul 2013 13:41:18 -0300
changeset 18847 31ca64473a86
parent 18846 4ef5f2321c67
child 18848 e64943db2b06
8011629: Object.defineProperty performance issue Reviewed-by: sundar, attila Contributed-by: james.laskey@oracle.com
nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java
--- a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Wed Jul 03 18:10:12 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Wed Jul 03 13:41:18 2013 -0300
@@ -75,6 +75,8 @@
 
     private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES];
     private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES];
+    private static final MethodType ACCESSOR_GETTER_PRIMITIVE_TYPE;
+    private static final MethodType ACCESSOR_SETTER_PRIMITIVE_TYPE;
     private static final MethodHandle SPILL_ELEMENT_GETTER;
     private static final MethodHandle SPILL_ELEMENT_SETTER;
 
@@ -82,13 +84,25 @@
     private static final MethodHandle[] SPILL_ACCESSORS = new MethodHandle[SPILL_CACHE_SIZE * 2];
 
     static {
+        MethodType getterPrimitiveType = null;
+        MethodType setterPrimitiveType = null;
+
         for (int i = 0; i < NOOF_TYPES; i++) {
             final Type type = ACCESSOR_TYPES.get(i);
             ACCESSOR_GETTER_TYPES[i] = MH.type(type.getTypeClass(), Object.class);
             ACCESSOR_SETTER_TYPES[i] = MH.type(void.class, Object.class, type.getTypeClass());
+
+            if (type == PRIMITIVE_TYPE) {
+                getterPrimitiveType = ACCESSOR_GETTER_TYPES[i];
+                setterPrimitiveType = ACCESSOR_SETTER_TYPES[i];
+            }
         }
 
-        final MethodHandle spillGetter = MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class);
+        ACCESSOR_GETTER_PRIMITIVE_TYPE = getterPrimitiveType;
+        ACCESSOR_SETTER_PRIMITIVE_TYPE = setterPrimitiveType;
+
+        final MethodType spillGetterType = MethodType.methodType(Object[].class, Object.class);
+        final MethodHandle spillGetter = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class), spillGetterType);
         SPILL_ELEMENT_GETTER = MH.filterArguments(MH.arrayElementGetter(Object[].class), 0, spillGetter);
         SPILL_ELEMENT_SETTER = MH.filterArguments(MH.arrayElementSetter(Object[].class), 0, spillGetter);
     }
@@ -177,9 +191,8 @@
                     ACCESSOR_GETTER_TYPES[i]);
             }
         } else {
-            //this will work as the object setter and getter will be converted appropriately
-            objectGetter = getter;
-            objectSetter = setter;
+            objectGetter = getter.type() != Lookup.GET_OBJECT_TYPE ? MH.asType(getter, Lookup.GET_OBJECT_TYPE) : getter;
+            objectSetter = setter != null && setter.type() != Lookup.SET_OBJECT_TYPE ? MH.asType(setter, Lookup.SET_OBJECT_TYPE) : setter;
         }
 
         setCurrentType(getterType);
@@ -195,8 +208,8 @@
             setters = new MethodHandle[fieldCount];
             for(int i = 0; i < fieldCount; ++i) {
                 final String fieldName = ObjectClassGenerator.getFieldName(i, Type.OBJECT);
-                getters[i] = MH.getter(lookup, structure, fieldName, Type.OBJECT.getTypeClass());
-                setters[i] = MH.setter(lookup, structure, fieldName, Type.OBJECT.getTypeClass());
+                getters[i] = MH.asType(MH.getter(lookup, structure, fieldName, Type.OBJECT.getTypeClass()), Lookup.GET_OBJECT_TYPE);
+                setters[i] = MH.asType(MH.setter(lookup, structure, fieldName, Type.OBJECT.getTypeClass()), Lookup.SET_OBJECT_TYPE);
             }
         }
     }
@@ -224,17 +237,18 @@
             final MethodHandle arguments   = MH.getter(lookup, structure, "arguments", Object.class);
             final MethodHandle argumentsSO = MH.asType(arguments, arguments.type().changeReturnType(ScriptObject.class));
 
-            objectGetter = MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot);
-            objectSetter = MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot);
+            objectGetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot), Lookup.GET_OBJECT_TYPE);
+            objectSetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot), Lookup.SET_OBJECT_TYPE);
         } else {
             final GettersSetters gs = GETTERS_SETTERS.get(structure);
             objectGetter = gs.getters[slot];
             objectSetter = gs.setters[slot];
 
             if (!OBJECT_FIELDS_ONLY) {
-                final String fieldNamePrimitive = ObjectClassGenerator.getFieldName(slot, ObjectClassGenerator.PRIMITIVE_TYPE);
-                primitiveGetter = MH.getter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass());
-                primitiveSetter = MH.setter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass());
+                final String fieldNamePrimitive = ObjectClassGenerator.getFieldName(slot, PRIMITIVE_TYPE);
+                final Class<?> typeClass = PRIMITIVE_TYPE.getTypeClass();
+                primitiveGetter = MH.asType(MH.getter(lookup, structure, fieldNamePrimitive, typeClass), ACCESSOR_GETTER_PRIMITIVE_TYPE);
+                primitiveSetter = MH.asType(MH.setter(lookup, structure, fieldNamePrimitive, typeClass), ACCESSOR_SETTER_PRIMITIVE_TYPE);
             }
         }
 
@@ -325,16 +339,8 @@
         final int i = getAccessorTypeIndex(type);
         if (getters[i] == null) {
             getters[i] = debug(
-                MH.asType(
-                    createGetter(
-                        currentType,
-                        type,
-                        primitiveGetter,
-                        objectGetter),
-                    ACCESSOR_GETTER_TYPES[i]),
-                currentType,
-                type,
-                "get");
+                createGetter(currentType, type, primitiveGetter, objectGetter),
+                currentType, type, "get");
         }
 
         return getters[i];
@@ -370,7 +376,6 @@
             objectSetter = getSpillSetter();
         }
         MethodHandle mh = createSetter(forType, type, primitiveSetter, objectSetter);
-        mh = MH.asType(mh, ACCESSOR_SETTER_TYPES[getAccessorTypeIndex(type)]); //has to be the case for invokeexact to work in ScriptObject
         mh = debug(mh, currentType, type, "set");
         return mh;
     }
@@ -423,9 +428,9 @@
         final int slot = getSlot();
         MethodHandle getter = slot < SPILL_CACHE_SIZE ? SPILL_ACCESSORS[slot * 2] : null;
         if (getter == null) {
-            getter = MH.asType(MH.insertArguments(SPILL_ELEMENT_GETTER, 1, slot), Lookup.GET_OBJECT_TYPE);
+            getter = MH.insertArguments(SPILL_ELEMENT_GETTER, 1, slot);
             if (slot < SPILL_CACHE_SIZE) {
-                SPILL_ACCESSORS[slot * 2] = getter;
+                SPILL_ACCESSORS[slot * 2 + 0] = getter;
             }
         }
         return getter;
@@ -435,7 +440,7 @@
         final int slot = getSlot();
         MethodHandle setter = slot < SPILL_CACHE_SIZE ? SPILL_ACCESSORS[slot * 2 + 1] : null;
         if (setter == null) {
-            setter = MH.asType(MH.insertArguments(SPILL_ELEMENT_SETTER, 1, slot), Lookup.SET_OBJECT_TYPE);
+            setter = MH.insertArguments(SPILL_ELEMENT_SETTER, 1, slot);
             if (slot < SPILL_CACHE_SIZE) {
                 SPILL_ACCESSORS[slot * 2 + 1] = setter;
             }