src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java
changeset 48411 4ff5c5206427
parent 48247 fa5a47cad0c9
child 49145 2854589fd853
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java	Wed Dec 20 11:40:45 2017 -0800
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java	Wed Dec 20 17:36:50 2017 +0100
@@ -2203,7 +2203,7 @@
     }
 
     /**
-     * Generate dynamic getter. Pop scope from stack. Push result
+     * Generate dynamic getter. Pop object from stack. Push result.
      *
      * @param valueType type of the value to set
      * @param name      name of property
@@ -2224,7 +2224,7 @@
             type = Type.OBJECT; //promote e.g strings to object generic setter
         }
 
-        popType(Type.SCOPE);
+        popType(Type.OBJECT);
         method.visitInvokeDynamicInsn(NameCodec.encode(name),
                 Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags | dynGetOperation(isMethod, isIndex));
 
@@ -2256,13 +2256,38 @@
             convert(Type.OBJECT); //TODO bad- until we specialize boolean setters,
         }
         popType(type);
-        popType(Type.SCOPE);
+        popType(Type.OBJECT);
 
         method.visitInvokeDynamicInsn(NameCodec.encode(name),
                 methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags | dynSetOperation(isIndex));
     }
 
-     /**
+    /**
+     * Generate dynamic remover. Pop object from stack. Push result.
+     *
+     * @param name      name of property
+     * @param flags     call site flags
+     * @return the method emitter
+     */
+    MethodEmitter dynamicRemove(final String name, final int flags, final boolean isIndex) {
+        if (name.length() > LARGE_STRING_THRESHOLD) { // use removeIndex for extremely long names
+            return load(name).dynamicRemoveIndex(flags);
+        }
+
+        debug("dynamic_remove", name, Type.BOOLEAN, getProgramPoint(flags));
+
+        popType(Type.OBJECT);
+        // Type is widened to OBJECT then coerced back to BOOLEAN
+        method.visitInvokeDynamicInsn(NameCodec.encode(name),
+                Type.getMethodDescriptor(Type.OBJECT, Type.OBJECT), LINKERBOOTSTRAP, flags | dynRemoveOperation(isIndex));
+
+        pushType(Type.OBJECT);
+        convert(Type.BOOLEAN); //most probably a nop
+
+        return this;
+    }
+
+    /**
      * Dynamic getter for indexed structures. Pop index and receiver from stack,
      * generate appropriate signatures based on types
      *
@@ -2342,6 +2367,35 @@
     }
 
     /**
+     * Dynamic remover for indexed structures. Pop index and receiver from stack,
+     * generate appropriate signatures based on types
+     *
+     * @param flags call site flags for getter
+     *
+     * @return the method emitter
+     */
+    MethodEmitter dynamicRemoveIndex(final int flags) {
+        debug("dynamic_remove_index", peekType(1), "[", peekType(), "]", getProgramPoint(flags));
+
+        Type index = peekType();
+        if (index.isObject() || index.isBoolean()) {
+            index = Type.OBJECT; //e.g. string->object
+            convert(Type.OBJECT);
+        }
+        popType();
+
+        popType(Type.OBJECT);
+
+        final String signature = Type.getMethodDescriptor(Type.OBJECT, Type.OBJECT /*e.g STRING->OBJECT*/, index);
+
+        method.visitInvokeDynamicInsn(EMPTY_NAME, signature, LINKERBOOTSTRAP, flags | dynRemoveOperation(true));
+        pushType(Type.OBJECT);
+        convert(Type.BOOLEAN);
+
+        return this;
+    }
+
+    /**
      * Load a key value in the proper form.
      *
      * @param key
@@ -2520,6 +2574,10 @@
         return isIndex ? NashornCallSiteDescriptor.SET_ELEMENT : NashornCallSiteDescriptor.SET_PROPERTY;
     }
 
+    private static int dynRemoveOperation(final boolean isIndex) {
+        return isIndex ? NashornCallSiteDescriptor.REMOVE_ELEMENT : NashornCallSiteDescriptor.REMOVE_PROPERTY;
+    }
+
     private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) {
         final Type from = conversion.getFrom();
         final Type to = conversion.getTo();