src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java
--- 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();