Merge
This commit is contained in:
commit
30066363bb
@ -156,6 +156,7 @@
|
||||
<fileset dir="${src.dir}/jdk/nashorn/tools/resources/"/>
|
||||
</copy>
|
||||
<copy file="${src.dir}/jdk/internal/dynalink/support/messages.properties" todir="${build.classes.dir}/jdk/internal/dynalink/support"/>
|
||||
<copy file="${src.dir}/jdk/nashorn/internal/codegen/anchor.properties" todir="${build.classes.dir}/jdk/nashorn/internal/codegen"/>
|
||||
|
||||
<echo message="full=${nashorn.fullversion}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties"/>
|
||||
<echo file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true">${line.separator}</echo>
|
||||
|
@ -140,6 +140,11 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
|
||||
private boolean hasApplies(final FunctionNode functionNode) {
|
||||
try {
|
||||
functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
|
||||
@Override
|
||||
public boolean enterFunctionNode(final FunctionNode fn) {
|
||||
return fn == functionNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enterCallNode(final CallNode callNode) {
|
||||
if (isApply(callNode)) {
|
||||
@ -162,7 +167,7 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
|
||||
* scope, thus we are conservative and treat any access to arguments outside the
|
||||
* apply call as a case of "we cannot apply the optimization".
|
||||
*/
|
||||
private void checkValidTransform(final FunctionNode functionNode) {
|
||||
private static void checkValidTransform(final FunctionNode functionNode) {
|
||||
|
||||
final Set<Expression> argumentsFound = new HashSet<>();
|
||||
final Deque<Set<Expression>> stack = new ArrayDeque<>();
|
||||
|
@ -33,6 +33,8 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@ -221,11 +223,37 @@ public final class OptimisticTypesPersistence {
|
||||
private static void reportError(final String msg, final File file, final Exception e) {
|
||||
final long now = System.currentTimeMillis();
|
||||
if(now - lastReportedError > ERROR_REPORT_THRESHOLD) {
|
||||
getLogger().warning(String.format("Failed to %s %s", msg, file), e);
|
||||
reportError(String.format("Failed to %s %s", msg, file), e);
|
||||
lastReportedError = now;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error message with warning severity (reasoning being that we're reporting an error that'll disable the
|
||||
* type info cache, but it's only logged as a warning because that doesn't prevent Nashorn from running, it just
|
||||
* disables a performance-enhancing cache).
|
||||
* @param msg the message to log
|
||||
* @param e the exception that represents the error.
|
||||
*/
|
||||
private static void reportError(final String msg, final Exception e) {
|
||||
getLogger().warning(msg, "\n", exceptionToString(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper that prints an exception stack trace into a string. We have to do this as if we just pass the exception
|
||||
* to {@link DebugLogger#warning(Object...)}, it will only log the exception message and not the stack, making
|
||||
* problems harder to diagnose.
|
||||
* @param e the exception
|
||||
* @return the string representation of {@link Exception#printStackTrace()} output.
|
||||
*/
|
||||
private static String exceptionToString(final Exception e) {
|
||||
final StringWriter sw = new StringWriter();
|
||||
final PrintWriter pw = new PrintWriter(sw, false);
|
||||
e.printStackTrace(pw);
|
||||
pw.flush();
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
private static File createBaseCacheDir() {
|
||||
if(MAX_FILES == 0 || Options.getBooleanProperty("nashorn.typeInfo.disabled")) {
|
||||
return null;
|
||||
@ -233,7 +261,7 @@ public final class OptimisticTypesPersistence {
|
||||
try {
|
||||
return createBaseCacheDirPrivileged();
|
||||
} catch(final Exception e) {
|
||||
getLogger().warning("Failed to create cache dir", e);
|
||||
reportError("Failed to create cache dir", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -267,7 +295,7 @@ public final class OptimisticTypesPersistence {
|
||||
try {
|
||||
return createCacheDirPrivileged(baseDir);
|
||||
} catch(final Exception e) {
|
||||
getLogger().warning("Failed to create cache dir", e);
|
||||
reportError("Failed to create cache dir", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -280,7 +308,7 @@ public final class OptimisticTypesPersistence {
|
||||
try {
|
||||
versionDirName = getVersionDirName();
|
||||
} catch(final Exception e) {
|
||||
getLogger().warning("Failed to calculate version dir name", e);
|
||||
reportError("Failed to calculate version dir name", e);
|
||||
return null;
|
||||
}
|
||||
final File versionDir = new File(baseDir, versionDirName);
|
||||
@ -328,7 +356,12 @@ public final class OptimisticTypesPersistence {
|
||||
* @throws Exception if digest could not be created
|
||||
*/
|
||||
public static String getVersionDirName() throws Exception {
|
||||
final URL url = OptimisticTypesPersistence.class.getResource("");
|
||||
// NOTE: getResource("") won't work if the JAR file doesn't have directory entries (and JAR files in JDK distro
|
||||
// don't, or at least it's a bad idea counting on it). Alternatively, we could've tried
|
||||
// getResource("OptimisticTypesPersistence.class") but behavior of getResource with regard to its willingness
|
||||
// to hand out URLs to .class files is also unspecified. Therefore, the most robust way to obtain an URL to our
|
||||
// package is to have a small non-class anchor file and start out from its URL.
|
||||
final URL url = OptimisticTypesPersistence.class.getResource("anchor.properties");
|
||||
final String protocol = url.getProtocol();
|
||||
if (protocol.equals("jar")) {
|
||||
// Normal deployment: nashorn.jar
|
||||
|
@ -0,0 +1,27 @@
|
||||
#
|
||||
# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
|
||||
# This file exists only so OptimisticTypesPersistence.getVersionDirName() can take its URL.
|
@ -264,6 +264,10 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
|
||||
case COMMARIGHT: {
|
||||
return rhs.getType(localVariableTypes);
|
||||
}
|
||||
case AND:
|
||||
case OR:{
|
||||
return Type.widestReturnType(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes));
|
||||
}
|
||||
default:
|
||||
if (isComparison()) {
|
||||
return Type.BOOLEAN;
|
||||
|
@ -35,7 +35,6 @@ import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArray
|
||||
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.SwitchPoint;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -93,17 +92,6 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
private static final Object CALL_CMP = new Object();
|
||||
private static final Object TO_LOCALE_STRING = new Object();
|
||||
|
||||
private SwitchPoint lengthMadeNotWritableSwitchPoint;
|
||||
private PushLinkLogic pushLinkLogic;
|
||||
private PopLinkLogic popLinkLogic;
|
||||
private ConcatLinkLogic concatLinkLogic;
|
||||
|
||||
/**
|
||||
* Index for the modification SwitchPoint that triggers when length
|
||||
* becomes not writable
|
||||
*/
|
||||
private static final int LENGTH_NOT_WRITABLE_SWITCHPOINT = 0;
|
||||
|
||||
/*
|
||||
* Constructors.
|
||||
*/
|
||||
@ -271,12 +259,83 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
@Override
|
||||
public Object getLength() {
|
||||
final long length = JSType.toUint32(getArray().length());
|
||||
if(length < Integer.MAX_VALUE) {
|
||||
if (length < Integer.MAX_VALUE) {
|
||||
return (int)length;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
private boolean defineLength(final long oldLen, final PropertyDescriptor oldLenDesc, final PropertyDescriptor desc, final boolean reject) {
|
||||
// Step 3a
|
||||
if (!desc.has(VALUE)) {
|
||||
return super.defineOwnProperty("length", desc, reject);
|
||||
}
|
||||
|
||||
// Step 3b
|
||||
final PropertyDescriptor newLenDesc = desc;
|
||||
|
||||
// Step 3c and 3d - get new length and convert to long
|
||||
final long newLen = NativeArray.validLength(newLenDesc.getValue(), true);
|
||||
|
||||
// Step 3e
|
||||
newLenDesc.setValue(newLen);
|
||||
|
||||
// Step 3f
|
||||
// increasing array length - just need to set new length value (and attributes if any) and return
|
||||
if (newLen >= oldLen) {
|
||||
return super.defineOwnProperty("length", newLenDesc, reject);
|
||||
}
|
||||
|
||||
// Step 3g
|
||||
if (!oldLenDesc.isWritable()) {
|
||||
if (reject) {
|
||||
throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3h and 3i
|
||||
final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable();
|
||||
if (!newWritable) {
|
||||
newLenDesc.setWritable(true);
|
||||
}
|
||||
|
||||
// Step 3j and 3k
|
||||
final boolean succeeded = super.defineOwnProperty("length", newLenDesc, reject);
|
||||
if (!succeeded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3l
|
||||
// make sure that length is set till the point we can delete the old elements
|
||||
long o = oldLen;
|
||||
while (newLen < o) {
|
||||
o--;
|
||||
final boolean deleteSucceeded = delete(o, false);
|
||||
if (!deleteSucceeded) {
|
||||
newLenDesc.setValue(o + 1);
|
||||
if (!newWritable) {
|
||||
newLenDesc.setWritable(false);
|
||||
}
|
||||
super.defineOwnProperty("length", newLenDesc, false);
|
||||
if (reject) {
|
||||
throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3m
|
||||
if (!newWritable) {
|
||||
// make 'length' property not writable
|
||||
final ScriptObject newDesc = Global.newEmptyInstance();
|
||||
newDesc.set(WRITABLE, false, 0);
|
||||
return super.defineOwnProperty("length", newDesc, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ECMA 15.4.5.1 [[DefineOwnProperty]] ( P, Desc, Throw )
|
||||
*/
|
||||
@ -290,82 +349,16 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
|
||||
// Step 2
|
||||
// get old length and convert to long
|
||||
long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true);
|
||||
final long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true);
|
||||
|
||||
// Step 3
|
||||
if ("length".equals(key)) {
|
||||
// check for length being made non-writable
|
||||
final boolean result = defineLength(oldLen, oldLenDesc, desc, reject);
|
||||
if (desc.has(WRITABLE) && !desc.isWritable()) {
|
||||
setIsLengthNotWritable();
|
||||
}
|
||||
|
||||
// Step 3a
|
||||
if (!desc.has(VALUE)) {
|
||||
return super.defineOwnProperty("length", desc, reject);
|
||||
}
|
||||
|
||||
// Step 3b
|
||||
final PropertyDescriptor newLenDesc = desc;
|
||||
|
||||
// Step 3c and 3d - get new length and convert to long
|
||||
final long newLen = NativeArray.validLength(newLenDesc.getValue(), true);
|
||||
|
||||
// Step 3e
|
||||
newLenDesc.setValue(newLen);
|
||||
|
||||
// Step 3f
|
||||
// increasing array length - just need to set new length value (and attributes if any) and return
|
||||
if (newLen >= oldLen) {
|
||||
return super.defineOwnProperty("length", newLenDesc, reject);
|
||||
}
|
||||
|
||||
// Step 3g
|
||||
if (!oldLenDesc.isWritable()) {
|
||||
if (reject) {
|
||||
throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3h and 3i
|
||||
final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable();
|
||||
if (!newWritable) {
|
||||
newLenDesc.setWritable(true);
|
||||
}
|
||||
|
||||
// Step 3j and 3k
|
||||
final boolean succeeded = super.defineOwnProperty("length", newLenDesc, reject);
|
||||
if (!succeeded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3l
|
||||
// make sure that length is set till the point we can delete the old elements
|
||||
while (newLen < oldLen) {
|
||||
oldLen--;
|
||||
final boolean deleteSucceeded = delete(oldLen, false);
|
||||
if (!deleteSucceeded) {
|
||||
newLenDesc.setValue(oldLen + 1);
|
||||
if (!newWritable) {
|
||||
newLenDesc.setWritable(false);
|
||||
}
|
||||
super.defineOwnProperty("length", newLenDesc, false);
|
||||
if (reject) {
|
||||
throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3m
|
||||
if (!newWritable) {
|
||||
// make 'length' property not writable
|
||||
final ScriptObject newDesc = Global.newEmptyInstance();
|
||||
newDesc.set(WRITABLE, false, 0);
|
||||
return super.defineOwnProperty("length", newDesc, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Step 4a
|
||||
@ -441,23 +434,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
@Override
|
||||
public void setIsLengthNotWritable() {
|
||||
super.setIsLengthNotWritable();
|
||||
/*
|
||||
* Switchpoints are created lazily. If we link any push or pop site,
|
||||
* we need to create the "length made not writable" switchpoint, if it
|
||||
* doesn't exist.
|
||||
*
|
||||
* If the switchpoint already exists, we will find it here, and invalidate
|
||||
* it, invalidating all previous callsites that use it.
|
||||
*
|
||||
* If the switchpoint doesn't exist, no push/pop has been linked so far,
|
||||
* because that would create it too. We invalidate it immediately and the
|
||||
* check link logic for all future callsites will fail immediately at link
|
||||
* time
|
||||
*/
|
||||
if (lengthMadeNotWritableSwitchPoint == null) {
|
||||
lengthMadeNotWritableSwitchPoint = new SwitchPoint();
|
||||
}
|
||||
SwitchPoint.invalidateAll(new SwitchPoint[] { lengthMadeNotWritableSwitchPoint });
|
||||
setArray(ArrayData.setIsLengthNotWritable(getArray()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -494,7 +471,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
@Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
|
||||
public static void length(final Object self, final Object length) {
|
||||
if (isArray(self)) {
|
||||
((ScriptObject) self).setLength(validLength(length, true));
|
||||
((ScriptObject)self).setLength(validLength(length, true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1306,10 +1283,13 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
// Get only non-missing elements. Missing elements go at the end
|
||||
// of the sorted array. So, just don't copy these to sort input.
|
||||
final ArrayList<Object> src = new ArrayList<>();
|
||||
for (long i = 0; i < len; i = array.nextIndex(i)) {
|
||||
if (array.has((int) i)) {
|
||||
src.add(array.getObject((int) i));
|
||||
|
||||
for (final Iterator<Long> iter = array.indexIterator(); iter.hasNext(); ) {
|
||||
final long index = iter.next();
|
||||
if (index >= len) {
|
||||
break;
|
||||
}
|
||||
src.add(array.getObject((int)index));
|
||||
}
|
||||
|
||||
final Object[] sorted = sort(src.toArray(), comparefn);
|
||||
@ -1767,11 +1747,11 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
@Override
|
||||
public SpecializedFunction.LinkLogic getLinkLogic(final Class<? extends LinkLogic> clazz) {
|
||||
if (clazz == PushLinkLogic.class) {
|
||||
return pushLinkLogic == null ? new PushLinkLogic(this) : pushLinkLogic;
|
||||
return PushLinkLogic.INSTANCE;
|
||||
} else if (clazz == PopLinkLogic.class) {
|
||||
return popLinkLogic == null ? new PopLinkLogic(this) : pushLinkLogic;
|
||||
return PopLinkLogic.INSTANCE;
|
||||
} else if (clazz == ConcatLinkLogic.class) {
|
||||
return concatLinkLogic == null ? new ConcatLinkLogic(this) : concatLinkLogic;
|
||||
return ConcatLinkLogic.INSTANCE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -1787,21 +1767,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
* modification switchpoint which is touched when length is written.
|
||||
*/
|
||||
private static abstract class ArrayLinkLogic extends SpecializedFunction.LinkLogic {
|
||||
private final NativeArray array;
|
||||
|
||||
protected ArrayLinkLogic(final NativeArray array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
private SwitchPoint getSwitchPoint() {
|
||||
return array.lengthMadeNotWritableSwitchPoint;
|
||||
}
|
||||
|
||||
private SwitchPoint newSwitchPoint() {
|
||||
assert array.lengthMadeNotWritableSwitchPoint == null;
|
||||
final SwitchPoint sp = new SwitchPoint();
|
||||
array.lengthMadeNotWritableSwitchPoint = sp;
|
||||
return sp;
|
||||
protected ArrayLinkLogic() {
|
||||
}
|
||||
|
||||
protected static ContinuousArrayData getContinuousArrayData(final Object self) {
|
||||
@ -1822,68 +1788,13 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
public Class<? extends Throwable> getRelinkException() {
|
||||
return ClassCastException.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModificationSwitchPoints() {
|
||||
return getSwitchPoint() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModificationSwitchPoint(final int index) {
|
||||
assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT;
|
||||
return hasModificationSwitchPoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SwitchPoint getOrCreateModificationSwitchPoint(final int index) {
|
||||
assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT;
|
||||
SwitchPoint sp = getSwitchPoint();
|
||||
if (sp == null) {
|
||||
sp = newSwitchPoint();
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SwitchPoint[] getOrCreateModificationSwitchPoints() {
|
||||
return new SwitchPoint[] { getOrCreateModificationSwitchPoint(LENGTH_NOT_WRITABLE_SWITCHPOINT) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateModificationSwitchPoint(final int index) {
|
||||
assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT;
|
||||
invalidateModificationSwitchPoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateModificationSwitchPoints() {
|
||||
final SwitchPoint sp = getSwitchPoint();
|
||||
assert sp != null : "trying to invalidate non-existant modified SwitchPoint";
|
||||
if (!sp.hasBeenInvalidated()) {
|
||||
SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInvalidatedModificationSwitchPoint(final int index) {
|
||||
assert index == LENGTH_NOT_WRITABLE_SWITCHPOINT;
|
||||
return hasInvalidatedModificationSwitchPoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInvalidatedModificationSwitchPoints() {
|
||||
final SwitchPoint sp = getSwitchPoint();
|
||||
return sp != null && !sp.hasBeenInvalidated();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is linker logic for optimistic concatenations
|
||||
*/
|
||||
private static final class ConcatLinkLogic extends ArrayLinkLogic {
|
||||
private ConcatLinkLogic(final NativeArray array) {
|
||||
super(array);
|
||||
}
|
||||
private static final LinkLogic INSTANCE = new ConcatLinkLogic();
|
||||
|
||||
@Override
|
||||
public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
|
||||
@ -1915,9 +1826,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
* This is linker logic for optimistic pushes
|
||||
*/
|
||||
private static final class PushLinkLogic extends ArrayLinkLogic {
|
||||
private PushLinkLogic(final NativeArray array) {
|
||||
super(array);
|
||||
}
|
||||
private static final LinkLogic INSTANCE = new PushLinkLogic();
|
||||
|
||||
@Override
|
||||
public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
|
||||
@ -1929,9 +1838,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin
|
||||
* This is linker logic for optimistic pops
|
||||
*/
|
||||
private static final class PopLinkLogic extends ArrayLinkLogic {
|
||||
private PopLinkLogic(final NativeArray array) {
|
||||
super(array);
|
||||
}
|
||||
private static final LinkLogic INSTANCE = new PopLinkLogic();
|
||||
|
||||
/**
|
||||
* We need to check if we are dealing with a continuous non empty array data here,
|
||||
|
@ -39,6 +39,7 @@ import jdk.nashorn.internal.runtime.PropertyListeners;
|
||||
import jdk.nashorn.internal.runtime.PropertyMap;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.events.RuntimeEvent;
|
||||
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
@ -65,6 +66,36 @@ public final class NativeDebug extends ScriptObject {
|
||||
return "Debug";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ArrayData class for this ScriptObject
|
||||
* @param self self
|
||||
* @param obj script object to check
|
||||
* @return ArrayData class, or undefined if no ArrayData is present
|
||||
*/
|
||||
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
|
||||
public static Object getArrayDataClass(final Object self, final Object obj) {
|
||||
try {
|
||||
return ((ScriptObject)obj).getArray().getClass();
|
||||
} catch (final ClassCastException e) {
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ArrayData for this ScriptObject
|
||||
* @param self self
|
||||
* @param obj script object to check
|
||||
* @return ArrayData, ArrayDatas have toString methods, return Undefined if data missing
|
||||
*/
|
||||
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
|
||||
public static Object getArrayData(final Object self, final Object obj) {
|
||||
try {
|
||||
return ((ScriptObject)obj).getArray();
|
||||
} catch (final ClassCastException e) {
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nashorn extension: get context, context utility
|
||||
*
|
||||
|
@ -30,7 +30,6 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.SwitchPoint;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
@ -62,10 +61,6 @@ public @interface SpecializedFunction {
|
||||
*/
|
||||
public static final LinkLogic EMPTY_INSTANCE = new Empty();
|
||||
|
||||
private static final SwitchPoint[] INVALIDATED_SWITCHPOINTS = new SwitchPoint[0];
|
||||
|
||||
private SwitchPoint[] modificationSwitchPoints; //cache
|
||||
|
||||
/** Empty link logic class - allow all linking, no guards */
|
||||
private static final class Empty extends LinkLogic {
|
||||
@Override
|
||||
@ -166,92 +161,6 @@ public @interface SpecializedFunction {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the modification SwitchPoint of a particular index from this OptimisticBuiltins
|
||||
* If none exists, one is created and that one is return.
|
||||
*
|
||||
* The implementor must map indexes to specific SwitchPoints for specific events and keep
|
||||
* track of what they mean, for example NativeArray.LENGTH_NOT_WRITABLE_SWITCHPOINT
|
||||
* might be a useful index mapping
|
||||
*
|
||||
* @param index index for SwitchPoint to get or create
|
||||
* @return modification SwitchPoint of particular index for the receiver
|
||||
*/
|
||||
public SwitchPoint getOrCreateModificationSwitchPoint(final int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the modification SwitchPoint from this OptimisticBuiltins. If none
|
||||
* exists, one is created and that one is return.
|
||||
*
|
||||
* @return modification SwitchPoint for the receiver
|
||||
*/
|
||||
public SwitchPoint[] getOrCreateModificationSwitchPoints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to invalidate a modification SwitchPoint by index.
|
||||
*
|
||||
* @param index index for SwitchPoint to invalidate
|
||||
*/
|
||||
public void invalidateModificationSwitchPoint(final int index) {
|
||||
//empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to invalidate all modification SwitchPoints for a receiver
|
||||
*/
|
||||
public void invalidateModificationSwitchPoints() {
|
||||
//empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the receiver has an invalidated modification SwitchPoint.
|
||||
*
|
||||
* @param index index for the modification SwitchPoint
|
||||
* @return true if the particular SwitchPoint at the index is invalidated
|
||||
*/
|
||||
public boolean hasInvalidatedModificationSwitchPoint(final int index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether at least one of the modification SwitchPoints has been
|
||||
* invalidated
|
||||
* @return true if one of the SwitchPoints has been invalidated
|
||||
*/
|
||||
public boolean hasInvalidatedModificationSwitchPoints() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this OptimisticBuiltins has a SwitchPoints of particular
|
||||
* index.
|
||||
*
|
||||
* As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of,
|
||||
* e.g. in the constructor of every subclass.
|
||||
*
|
||||
* @param index index for the modification SwitchPoint
|
||||
* @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not
|
||||
*/
|
||||
public boolean hasModificationSwitchPoint(final int index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this OptimisticBuiltins has SwitchPoints.
|
||||
*
|
||||
* As creation overhead for a SwitchPoint is non-zero, we have to create them lazily instead of,
|
||||
* e.g. in the constructor of every subclass.
|
||||
*
|
||||
* @return true if a modification SwitchPoint exists, no matter if it has been invalidated or not
|
||||
*/
|
||||
public boolean hasModificationSwitchPoints() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check, given a link request and a receiver, if this specialization
|
||||
* fits This is used by the linker in {@link ScriptFunction} to figure
|
||||
@ -265,47 +174,9 @@ public @interface SpecializedFunction {
|
||||
* pick a non specialized target
|
||||
*/
|
||||
public boolean checkLinkable(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
|
||||
// no matter what the modification switchpoints are, if any of them are invalidated,
|
||||
// we can't link. Side effect is that if it's the first time we see this callsite,
|
||||
// we have to create the SwitchPoint(s) so future modification switchpoint invalidations
|
||||
// relink it
|
||||
final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(self);
|
||||
if (sps == INVALIDATED_SWITCHPOINTS) {
|
||||
// nope, can't do the fast link as this assumption
|
||||
// has been invalidated already, e.g. length of an
|
||||
// array set to not writable
|
||||
return false;
|
||||
}
|
||||
modificationSwitchPoints = sps; //cache
|
||||
|
||||
// check the link guard, if it says we can link, go ahead
|
||||
return canLink(self, desc, request);
|
||||
}
|
||||
|
||||
private SwitchPoint[] getOrCreateModificationSwitchPoints(final Object self) {
|
||||
final SwitchPoint[] sps = getOrCreateModificationSwitchPoints(); //ask for all my switchpoints
|
||||
if (sps != null) { //switchpoint exists, but some may be invalidated
|
||||
for (final SwitchPoint sp : sps) {
|
||||
if (sp.hasBeenInvalidated()) {
|
||||
return INVALIDATED_SWITCHPOINTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cached modification switchpoints. Only possible to do after a link
|
||||
* check call has been performed, one that has answered "true", or you will get the
|
||||
* wrong information.
|
||||
*
|
||||
* Should be used only from {@link ScriptFunction#findCallMethod}
|
||||
*
|
||||
* @return cached modification switchpoints for this callsite, null if none
|
||||
*/
|
||||
public SwitchPoint[] getModificationSwitchPoints() {
|
||||
return modificationSwitchPoints == null ? null : modificationSwitchPoints.clone();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,10 +82,9 @@ public abstract class CodeStore implements Loggable {
|
||||
* Returns a new code store instance.
|
||||
*
|
||||
* @param context the current context
|
||||
* @return The instance
|
||||
* @throws IOException If an error occurs
|
||||
* @return The instance, or null if code store could not be created
|
||||
*/
|
||||
public static CodeStore newCodeStore(final Context context) throws IOException {
|
||||
public static CodeStore newCodeStore(final Context context) {
|
||||
final Class<CodeStore> baseClass = CodeStore.class;
|
||||
try {
|
||||
// security check first
|
||||
@ -103,9 +102,14 @@ public abstract class CodeStore implements Loggable {
|
||||
} catch (final AccessControlException e) {
|
||||
context.getLogger(CodeStore.class).warning("failed to load code store provider ", e);
|
||||
}
|
||||
final CodeStore store = new DirectoryCodeStore(context);
|
||||
store.initLogger(context);
|
||||
return store;
|
||||
try {
|
||||
final CodeStore store = new DirectoryCodeStore(context);
|
||||
store.initLogger(context);
|
||||
return store;
|
||||
} catch (final IOException e) {
|
||||
context.getLogger(CodeStore.class).warning("failed to create cache directory ", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,9 +33,11 @@ import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.MutableCallSite;
|
||||
import java.lang.invoke.SwitchPoint;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Supplier;
|
||||
@ -726,34 +728,58 @@ final class CompiledFunction {
|
||||
* @param ipp
|
||||
* @return string describing the ipp map
|
||||
*/
|
||||
private static String toStringInvalidations(final Map<Integer, Type> ipp) {
|
||||
private static List<String> toStringInvalidations(final Map<Integer, Type> ipp) {
|
||||
if (ipp == null) {
|
||||
return "";
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final List<String> list = new ArrayList<>();
|
||||
|
||||
for (final Iterator<Map.Entry<Integer, Type>> iter = ipp.entrySet().iterator(); iter.hasNext(); ) {
|
||||
final Map.Entry<Integer, Type> entry = iter.next();
|
||||
final char bct = entry.getValue().getBytecodeStackType();
|
||||
final String type;
|
||||
|
||||
switch (entry.getValue().getBytecodeStackType()) {
|
||||
case 'A':
|
||||
type = "object";
|
||||
break;
|
||||
case 'I':
|
||||
type = "int";
|
||||
break;
|
||||
case 'J':
|
||||
type = "long";
|
||||
break;
|
||||
case 'D':
|
||||
type = "double";
|
||||
break;
|
||||
default:
|
||||
type = String.valueOf(bct);
|
||||
break;
|
||||
}
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append('[').
|
||||
append("program point: ").
|
||||
append(entry.getKey()).
|
||||
append("->").
|
||||
append(bct == 'A' ? 'O' : bct).
|
||||
append(" -> ").
|
||||
append(type).
|
||||
append(']');
|
||||
|
||||
if (iter.hasNext()) {
|
||||
sb.append(' ');
|
||||
}
|
||||
list.add(sb.toString());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
return list;
|
||||
}
|
||||
|
||||
private void logRecompile(final String reason, final FunctionNode fn, final MethodType type, final Map<Integer, Type> ipp) {
|
||||
if (log.isEnabled()) {
|
||||
log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type, " ", toStringInvalidations(ipp));
|
||||
log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", type);
|
||||
log.indent();
|
||||
for (final String str : toStringInvalidations(ipp)) {
|
||||
log.fine(str);
|
||||
}
|
||||
log.unindent();
|
||||
}
|
||||
}
|
||||
|
||||
@ -769,7 +795,14 @@ final class CompiledFunction {
|
||||
*/
|
||||
private synchronized MethodHandle handleRewriteException(final OptimismInfo oldOptInfo, final RewriteException re) {
|
||||
if (log.isEnabled()) {
|
||||
log.info(new RecompilationEvent(Level.INFO, re, re.getReturnValueNonDestructive()), "RewriteException ", re.getMessageShort());
|
||||
log.info(
|
||||
new RecompilationEvent(
|
||||
Level.INFO,
|
||||
re,
|
||||
re.getReturnValueNonDestructive()),
|
||||
"caught RewriteException ",
|
||||
re.getMessageShort());
|
||||
log.indent();
|
||||
}
|
||||
|
||||
final MethodType type = type();
|
||||
@ -799,7 +832,7 @@ final class CompiledFunction {
|
||||
|
||||
logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
|
||||
fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
|
||||
log.info("Reusable IR generated");
|
||||
log.fine("Reusable IR generated");
|
||||
|
||||
// compile the rest of the function, and install it
|
||||
log.info("Generating and installing bytecode from reusable IR...");
|
||||
@ -815,15 +848,15 @@ final class CompiledFunction {
|
||||
compiler.persistClassInfo(cacheKey, normalFn);
|
||||
}
|
||||
|
||||
log.info("Done.");
|
||||
|
||||
final boolean canBeDeoptimized = normalFn.canBeDeoptimized();
|
||||
|
||||
if (log.isEnabled()) {
|
||||
log.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ") ", canBeDeoptimized ? " can still be deoptimized." : " is completely deoptimized.");
|
||||
}
|
||||
log.unindent();
|
||||
log.info("Done.");
|
||||
|
||||
log.info("Looking up invoker...");
|
||||
log.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ") ", canBeDeoptimized ? "can still be deoptimized." : " is completely deoptimized.");
|
||||
log.finest("Looking up invoker...");
|
||||
}
|
||||
|
||||
final MethodHandle newInvoker = effectiveOptInfo.data.lookup(fn);
|
||||
invoker = newInvoker.asType(type.changeReturnType(newInvoker.type().returnType()));
|
||||
@ -870,7 +903,6 @@ final class CompiledFunction {
|
||||
private SwitchPoint optimisticAssumptions;
|
||||
private final DebugLogger log;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
OptimismInfo(final RecompilableScriptFunctionData data, final Map<Integer, Type> invalidatedProgramPoints) {
|
||||
this.data = data;
|
||||
this.log = data.getLogger();
|
||||
|
@ -509,11 +509,7 @@ public final class Context {
|
||||
}
|
||||
|
||||
if (env._persistent_cache) {
|
||||
try {
|
||||
codeStore = newCodeStore(this);
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException("Error initializing code cache", e);
|
||||
}
|
||||
codeStore = newCodeStore(this);
|
||||
}
|
||||
|
||||
// print version info if asked.
|
||||
@ -1200,7 +1196,7 @@ public final class Context {
|
||||
FunctionNode functionNode = null;
|
||||
// We only use the code store here if optimistic types are disabled. With optimistic types, initial compilation
|
||||
// just creates a thin wrapper, and actual code is stored per function in RecompilableScriptFunctionData.
|
||||
final boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types;
|
||||
final boolean useCodeStore = codeStore != null && !env._parse_only && !env._optimistic_types;
|
||||
final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;
|
||||
|
||||
if (useCodeStore) {
|
||||
|
@ -26,7 +26,6 @@
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
@ -620,20 +619,25 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
return f;
|
||||
}
|
||||
|
||||
MethodHandle lookup(final FunctionInitializer fnInit) {
|
||||
private void logLookup(final boolean shouldLog, final MethodType targetType) {
|
||||
if (shouldLog && log.isEnabled()) {
|
||||
log.info("Looking up ", DebugLogger.quote(functionName), " type=", targetType);
|
||||
}
|
||||
}
|
||||
|
||||
private MethodHandle lookup(final FunctionInitializer fnInit, final boolean shouldLog) {
|
||||
final MethodType type = fnInit.getMethodType();
|
||||
logLookup(shouldLog, type);
|
||||
return lookupCodeMethod(fnInit.getCode(), type);
|
||||
}
|
||||
|
||||
MethodHandle lookup(final FunctionNode fn) {
|
||||
final MethodType type = new FunctionSignature(fn).getMethodType();
|
||||
logLookup(true, type);
|
||||
return lookupCodeMethod(fn.getCompileUnit().getCode(), type);
|
||||
}
|
||||
|
||||
MethodHandle lookupCodeMethod(final Class<?> codeClass, final MethodType targetType) {
|
||||
if (log.isEnabled()) {
|
||||
log.info("Looking up ", DebugLogger.quote(functionName), " type=", targetType);
|
||||
}
|
||||
return MH.findStatic(LOOKUP, codeClass, functionName, targetType);
|
||||
}
|
||||
|
||||
@ -649,7 +653,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
if(!code.isEmpty()) {
|
||||
throw new IllegalStateException(name);
|
||||
}
|
||||
addCode(lookup(initializer), null, null, initializer.getFlags());
|
||||
addCode(lookup(initializer, true), null, null, initializer.getFlags());
|
||||
}
|
||||
|
||||
private CompiledFunction addCode(final MethodHandle target, final Map<Integer, Type> invalidatedProgramPoints,
|
||||
@ -671,10 +675,10 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
*/
|
||||
private CompiledFunction addCode(final FunctionInitializer fnInit, final MethodType callSiteType) {
|
||||
if (isVariableArity()) {
|
||||
return addCode(lookup(fnInit), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
|
||||
return addCode(lookup(fnInit, true), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
|
||||
}
|
||||
|
||||
final MethodHandle handle = lookup(fnInit);
|
||||
final MethodHandle handle = lookup(fnInit, true);
|
||||
final MethodType fromType = handle.type();
|
||||
MethodType toType = needsCallee(fromType) ? callSiteType.changeParameterType(0, ScriptFunction.class) : callSiteType.dropParameterTypes(0, 1);
|
||||
toType = toType.changeReturnType(fromType.returnType());
|
||||
@ -699,7 +703,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
|
||||
toType = toType.dropParameterTypes(fromCount, toCount);
|
||||
}
|
||||
|
||||
return addCode(lookup(fnInit).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
|
||||
return addCode(lookup(fnInit, false).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -603,16 +603,6 @@ public abstract class ScriptFunction extends ScriptObject {
|
||||
log.info("Linking optimistic builtin function: '", name, "' args=", Arrays.toString(request.getArguments()), " desc=", desc);
|
||||
}
|
||||
|
||||
final SwitchPoint[] msps = linkLogic.getModificationSwitchPoints();
|
||||
if (msps != null) {
|
||||
for (final SwitchPoint sp : msps) {
|
||||
if (sp != null) {
|
||||
assert !sp.hasBeenInvalidated();
|
||||
sps.add(sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exceptionGuard = linkLogic.getRelinkException();
|
||||
|
||||
break;
|
||||
|
@ -510,6 +510,13 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidateGlobalConstant(final String key) {
|
||||
final GlobalConstants globalConstants = getGlobalConstants();
|
||||
if (globalConstants != null) {
|
||||
globalConstants.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ECMA 8.12.9 [[DefineOwnProperty]] (P, Desc, Throw)
|
||||
*
|
||||
@ -525,6 +532,8 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
final Object current = getOwnPropertyDescriptor(key);
|
||||
final String name = JSType.toString(key);
|
||||
|
||||
invalidateGlobalConstant(key);
|
||||
|
||||
if (current == UNDEFINED) {
|
||||
if (isExtensible()) {
|
||||
// add a new own property
|
||||
@ -923,10 +932,8 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (property instanceof UserAccessorProperty) {
|
||||
((UserAccessorProperty)property).setAccessors(this, getMap(), null);
|
||||
}
|
||||
final GlobalConstants globalConstants = getGlobalConstants();
|
||||
if (globalConstants != null) {
|
||||
globalConstants.delete(property.getKey());
|
||||
}
|
||||
|
||||
invalidateGlobalConstant(property.getKey());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1352,12 +1359,9 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
final PropertyMap selfMap = this.getMap();
|
||||
|
||||
final ArrayData array = getArray();
|
||||
final long length = array.length();
|
||||
|
||||
for (long i = 0; i < length; i = array.nextIndex(i)) {
|
||||
if (array.has((int)i)) {
|
||||
keys.add(JSType.toString(i));
|
||||
}
|
||||
for (final Iterator<Long> iter = array.indexIterator(); iter.hasNext(); ) {
|
||||
keys.add(JSType.toString(iter.next().longValue()));
|
||||
}
|
||||
|
||||
for (final Property property : selfMap.getProperties()) {
|
||||
@ -1516,12 +1520,12 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
*
|
||||
* @return {@code true} if 'length' property is non-writable
|
||||
*/
|
||||
public final boolean isLengthNotWritable() {
|
||||
public boolean isLengthNotWritable() {
|
||||
return (flags & IS_LENGTH_NOT_WRITABLE) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag this object as having non-writable length property
|
||||
* Flag this object as having non-writable length property.
|
||||
*/
|
||||
public void setIsLengthNotWritable() {
|
||||
flags |= IS_LENGTH_NOT_WRITABLE;
|
||||
@ -3152,6 +3156,8 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
public final void setObject(final FindProperty find, final int callSiteFlags, final String key, final Object value) {
|
||||
FindProperty f = find;
|
||||
|
||||
invalidateGlobalConstant(key);
|
||||
|
||||
if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
|
||||
final boolean isScope = NashornCallSiteDescriptor.isScopeFlag(callSiteFlags);
|
||||
// If the start object of the find is not this object it means the property was found inside a
|
||||
@ -3177,7 +3183,6 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
|
||||
throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3588,7 +3593,6 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return deleteObject(JSType.toObject(key), strict);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,9 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
@ -55,6 +58,21 @@ public abstract class ArrayData {
|
||||
* a proper ArrayData when we try to write to it */
|
||||
public static final ArrayData EMPTY_ARRAY = new UntouchedArrayData();
|
||||
|
||||
/**
|
||||
* Length of the array data. Not necessarily length of the wrapped array.
|
||||
* This is private to ensure that no one in a subclass is able to touch the length
|
||||
* without going through {@link setLength}. This is used to implement
|
||||
* {@link LengthNotWritableFilter}s, ensuring that there are no ways past
|
||||
* a {@link setLength} function replaced by a nop
|
||||
*/
|
||||
private long length;
|
||||
|
||||
/**
|
||||
* Method handle to throw an {@link UnwarrantedOptimismException} when getting an element
|
||||
* of the wrong type
|
||||
*/
|
||||
protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class);
|
||||
|
||||
/**
|
||||
* Immutable empty array to get ScriptObjects started.
|
||||
* Use the same array and convert it to mutable as soon as it is modified
|
||||
@ -82,7 +100,7 @@ public abstract class ArrayData {
|
||||
|
||||
@Override
|
||||
public ContinuousArrayData copy() {
|
||||
return new UntouchedArrayData((int)length);
|
||||
return new UntouchedArrayData((int)length());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -112,6 +130,16 @@ public abstract class ArrayData {
|
||||
return toRealArrayData(0).convert(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData delete(final int index) {
|
||||
return new DeletedRangeArrayFilter(this, index, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData delete(final long fromIndex, final long toIndex) {
|
||||
return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shiftLeft(final int by) {
|
||||
//nop, always empty or we wouldn't be of this class
|
||||
@ -172,16 +200,6 @@ public abstract class ArrayData {
|
||||
return false; //empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData delete(final int index) {
|
||||
return new DeletedRangeArrayFilter(this, index, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData delete(final long fromIndex, final long toIndex) {
|
||||
return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
@ -230,17 +248,6 @@ public abstract class ArrayData {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Length of the array data. Not necessarily length of the wrapped array.
|
||||
*/
|
||||
protected long length;
|
||||
|
||||
/**
|
||||
* Method handle to throw an {@link UnwarrantedOptimismException} when getting an element
|
||||
* of the wrong type
|
||||
*/
|
||||
protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param length Virtual length of the array.
|
||||
@ -393,6 +400,16 @@ public abstract class ArrayData {
|
||||
return new NonExtensibleArrayFilter(underlying);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent this array from having its length reset
|
||||
*
|
||||
* @param underlying the underlying ArrayDAta to wrap in the non extensible filter
|
||||
* @return new array data, filtered
|
||||
*/
|
||||
public static final ArrayData setIsLengthNotWritable(final ArrayData underlying) {
|
||||
return new LengthNotWritableFilter(underlying);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the array data. This may differ from the actual
|
||||
* length of the array this wraps as length may be set or gotten as any
|
||||
@ -445,6 +462,22 @@ public abstract class ArrayData {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase length by 1
|
||||
* @return the new length, not the old one (i.e. pre-increment)
|
||||
*/
|
||||
protected final long increaseLength() {
|
||||
return ++this.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease length by 1.
|
||||
* @return the new length, not the old one (i.e. pre-decrement)
|
||||
*/
|
||||
protected final long decreaseLength() {
|
||||
return --this.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift the array data left
|
||||
*
|
||||
@ -454,7 +487,7 @@ public abstract class ArrayData {
|
||||
*
|
||||
* @param by offset to shift
|
||||
*/
|
||||
public abstract void shiftLeft(int by);
|
||||
public abstract void shiftLeft(final int by);
|
||||
|
||||
/**
|
||||
* Shift the array right
|
||||
@ -463,7 +496,7 @@ public abstract class ArrayData {
|
||||
|
||||
* @return New arraydata (or same)
|
||||
*/
|
||||
public abstract ArrayData shiftRight(int by);
|
||||
public abstract ArrayData shiftRight(final int by);
|
||||
|
||||
/**
|
||||
* Ensure that the given index exists and won't fail subsequent
|
||||
@ -471,7 +504,7 @@ public abstract class ArrayData {
|
||||
* @param safeIndex the index to ensure wont go out of bounds
|
||||
* @return new array data (or same)
|
||||
*/
|
||||
public abstract ArrayData ensure(long safeIndex);
|
||||
public abstract ArrayData ensure(final long safeIndex);
|
||||
|
||||
/**
|
||||
* Shrink the array to a new length, may or may not retain the
|
||||
@ -481,7 +514,7 @@ public abstract class ArrayData {
|
||||
*
|
||||
* @return new array data (or same)
|
||||
*/
|
||||
public abstract ArrayData shrink(long newLength);
|
||||
public abstract ArrayData shrink(final long newLength);
|
||||
|
||||
/**
|
||||
* Set an object value at a given index
|
||||
@ -491,7 +524,7 @@ public abstract class ArrayData {
|
||||
* @param strict are we in strict mode
|
||||
* @return new array data (or same)
|
||||
*/
|
||||
public abstract ArrayData set(int index, Object value, boolean strict);
|
||||
public abstract ArrayData set(final int index, final Object value, final boolean strict);
|
||||
|
||||
/**
|
||||
* Set an int value at a given index
|
||||
@ -501,7 +534,7 @@ public abstract class ArrayData {
|
||||
* @param strict are we in strict mode
|
||||
* @return new array data (or same)
|
||||
*/
|
||||
public abstract ArrayData set(int index, int value, boolean strict);
|
||||
public abstract ArrayData set(final int index, final int value, final boolean strict);
|
||||
|
||||
/**
|
||||
* Set a long value at a given index
|
||||
@ -511,7 +544,7 @@ public abstract class ArrayData {
|
||||
* @param strict are we in strict mode
|
||||
* @return new array data (or same)
|
||||
*/
|
||||
public abstract ArrayData set(int index, long value, boolean strict);
|
||||
public abstract ArrayData set(final int index, final long value, final boolean strict);
|
||||
|
||||
/**
|
||||
* Set an double value at a given index
|
||||
@ -521,7 +554,7 @@ public abstract class ArrayData {
|
||||
* @param strict are we in strict mode
|
||||
* @return new array data (or same)
|
||||
*/
|
||||
public abstract ArrayData set(int index, double value, boolean strict);
|
||||
public abstract ArrayData set(final int index, final double value, final boolean strict);
|
||||
|
||||
/**
|
||||
* Set an empty value at a given index. Should only affect Object array.
|
||||
@ -552,7 +585,7 @@ public abstract class ArrayData {
|
||||
* @param index the index
|
||||
* @return the value
|
||||
*/
|
||||
public abstract int getInt(int index);
|
||||
public abstract int getInt(final int index);
|
||||
|
||||
/**
|
||||
* Returns the optimistic type of this array data. Basically, when an array data object needs to throw an
|
||||
@ -581,7 +614,7 @@ public abstract class ArrayData {
|
||||
* @param index the index
|
||||
* @return the value
|
||||
*/
|
||||
public abstract long getLong(int index);
|
||||
public abstract long getLong(final int index);
|
||||
|
||||
/**
|
||||
* Get optimistic long - default is that it's impossible. Overridden
|
||||
@ -601,7 +634,7 @@ public abstract class ArrayData {
|
||||
* @param index the index
|
||||
* @return the value
|
||||
*/
|
||||
public abstract double getDouble(int index);
|
||||
public abstract double getDouble(final int index);
|
||||
|
||||
/**
|
||||
* Get optimistic double - default is that it's impossible. Overridden
|
||||
@ -621,14 +654,14 @@ public abstract class ArrayData {
|
||||
* @param index the index
|
||||
* @return the value
|
||||
*/
|
||||
public abstract Object getObject(int index);
|
||||
public abstract Object getObject(final int index);
|
||||
|
||||
/**
|
||||
* Tests to see if an entry exists (avoids boxing.)
|
||||
* @param index the index
|
||||
* @return true if entry exists
|
||||
*/
|
||||
public abstract boolean has(int index);
|
||||
public abstract boolean has(final int index);
|
||||
|
||||
/**
|
||||
* Returns if element at specific index can be deleted or not.
|
||||
@ -674,7 +707,7 @@ public abstract class ArrayData {
|
||||
* @param index the index
|
||||
* @return new array data (or same)
|
||||
*/
|
||||
public abstract ArrayData delete(int index);
|
||||
public abstract ArrayData delete(final int index);
|
||||
|
||||
/**
|
||||
* Delete a given range from this array;
|
||||
@ -684,7 +717,7 @@ public abstract class ArrayData {
|
||||
*
|
||||
* @return new ArrayData after deletion
|
||||
*/
|
||||
public abstract ArrayData delete(long fromIndex, long toIndex);
|
||||
public abstract ArrayData delete(final long fromIndex, final long toIndex);
|
||||
|
||||
/**
|
||||
* Convert the ArrayData to one with a different element type
|
||||
@ -694,7 +727,7 @@ public abstract class ArrayData {
|
||||
* @param type new element type
|
||||
* @return new array data
|
||||
*/
|
||||
public abstract ArrayData convert(Class<?> type);
|
||||
public abstract ArrayData convert(final Class<?> type);
|
||||
|
||||
/**
|
||||
* Push an array of items to the end of the array
|
||||
@ -778,7 +811,7 @@ public abstract class ArrayData {
|
||||
* @param to end index + 1
|
||||
* @return new array data
|
||||
*/
|
||||
public abstract ArrayData slice(long from, long to);
|
||||
public abstract ArrayData slice(final long from, final long to);
|
||||
|
||||
/**
|
||||
* Fast splice operation. This just modifies the array according to the number of
|
||||
@ -822,6 +855,34 @@ public abstract class ArrayData {
|
||||
return widest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of keys in the array for the iterators
|
||||
* @return iterator key list
|
||||
*/
|
||||
protected List<Long> computeIteratorKeys() {
|
||||
final List<Long> keys = new ArrayList<>();
|
||||
|
||||
final long len = length();
|
||||
for (long i = 0L; i < len; i = nextIndex(i)) {
|
||||
if (has((int)i)) {
|
||||
keys.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an iterator that goes through all indexes of elements
|
||||
* in this array. This includes those after array.length if
|
||||
* they exist
|
||||
*
|
||||
* @return iterator
|
||||
*/
|
||||
public Iterator<Long> indexIterator() {
|
||||
return computeIteratorKeys().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exponential growth function for array size when in
|
||||
* need of resizing.
|
||||
@ -841,7 +902,7 @@ public abstract class ArrayData {
|
||||
*
|
||||
* @return the next index
|
||||
*/
|
||||
public long nextIndex(final long index) {
|
||||
long nextIndex(final long index) {
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ abstract class ArrayFilter extends ArrayData {
|
||||
protected ArrayData underlying;
|
||||
|
||||
ArrayFilter(final ArrayData underlying) {
|
||||
super(underlying.length);
|
||||
super(underlying.length());
|
||||
this.underlying = underlying;
|
||||
}
|
||||
|
||||
@ -70,62 +70,55 @@ abstract class ArrayFilter extends ArrayData {
|
||||
@Override
|
||||
public void shiftLeft(final int by) {
|
||||
underlying.shiftLeft(by);
|
||||
setLength(underlying.length);
|
||||
setLength(underlying.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData shiftRight(final int by) {
|
||||
underlying = underlying.shiftRight(by);
|
||||
setLength(underlying.length);
|
||||
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData ensure(final long safeIndex) {
|
||||
underlying = underlying.ensure(safeIndex);
|
||||
setLength(underlying.length);
|
||||
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData shrink(final long newLength) {
|
||||
underlying = underlying.shrink(newLength);
|
||||
setLength(underlying.length);
|
||||
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final Object value, final boolean strict) {
|
||||
underlying = underlying.set(index, value, strict);
|
||||
setLength(underlying.length);
|
||||
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final int value, final boolean strict) {
|
||||
underlying = underlying.set(index, value, strict);
|
||||
setLength(underlying.length);
|
||||
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final long value, final boolean strict) {
|
||||
underlying = underlying.set(index, value, strict);
|
||||
setLength(underlying.length);
|
||||
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final double value, final boolean strict) {
|
||||
underlying = underlying.set(index, value, strict);
|
||||
setLength(underlying.length);
|
||||
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -189,29 +182,28 @@ abstract class ArrayFilter extends ArrayData {
|
||||
@Override
|
||||
public ArrayData delete(final int index) {
|
||||
underlying = underlying.delete(index);
|
||||
setLength(underlying.length);
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData delete(final long from, final long to) {
|
||||
underlying = underlying.delete(from, to);
|
||||
setLength(underlying.length);
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData convert(final Class<?> type) {
|
||||
underlying = underlying.convert(type);
|
||||
setLength(underlying.length);
|
||||
setLength(underlying.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
final Object value = underlying.pop();
|
||||
setLength(underlying.length);
|
||||
|
||||
setLength(underlying.length());
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ public abstract class ContinuousArrayData extends ArrayData {
|
||||
* @return true if we don't need to do any array reallocation to fit an element at index
|
||||
*/
|
||||
public final boolean hasRoomFor(final int index) {
|
||||
return has(index) || (index == length && ensure(index) == this);
|
||||
return has(index) || (index == length() && ensure(index) == this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,7 +73,7 @@ public abstract class ContinuousArrayData extends ArrayData {
|
||||
* @return true if empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return length == 0L;
|
||||
return length() == 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,8 +38,7 @@ final class DeletedArrayFilter extends ArrayFilter {
|
||||
|
||||
DeletedArrayFilter(final ArrayData underlying) {
|
||||
super(underlying);
|
||||
|
||||
this.deleted = new BitVector(underlying.length);
|
||||
this.deleted = new BitVector(underlying.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -79,25 +78,24 @@ final class DeletedArrayFilter extends ArrayFilter {
|
||||
@Override
|
||||
public void shiftLeft(final int by) {
|
||||
super.shiftLeft(by);
|
||||
deleted.shiftLeft(by, length);
|
||||
deleted.shiftLeft(by, length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData shiftRight(final int by) {
|
||||
super.shiftRight(by);
|
||||
deleted.shiftRight(by, length);
|
||||
|
||||
deleted.shiftRight(by, length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData ensure(final long safeIndex) {
|
||||
if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) {
|
||||
if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
|
||||
return new SparseArrayData(this, safeIndex + 1);
|
||||
}
|
||||
|
||||
super.ensure(safeIndex);
|
||||
deleted.resize(length);
|
||||
deleted.resize(length());
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -105,36 +103,31 @@ final class DeletedArrayFilter extends ArrayFilter {
|
||||
@Override
|
||||
public ArrayData shrink(final long newLength) {
|
||||
super.shrink(newLength);
|
||||
deleted.resize(length);
|
||||
|
||||
deleted.resize(length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final Object value, final boolean strict) {
|
||||
deleted.clear(ArrayIndex.toLongIndex(index));
|
||||
|
||||
return super.set(index, value, strict);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final int value, final boolean strict) {
|
||||
deleted.clear(ArrayIndex.toLongIndex(index));
|
||||
|
||||
return super.set(index, value, strict);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final long value, final boolean strict) {
|
||||
deleted.clear(ArrayIndex.toLongIndex(index));
|
||||
|
||||
return super.set(index, value, strict);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final double value, final boolean strict) {
|
||||
deleted.clear(ArrayIndex.toLongIndex(index));
|
||||
|
||||
return super.set(index, value, strict);
|
||||
}
|
||||
|
||||
@ -146,7 +139,7 @@ final class DeletedArrayFilter extends ArrayFilter {
|
||||
@Override
|
||||
public ArrayData delete(final int index) {
|
||||
final long longIndex = ArrayIndex.toLongIndex(index);
|
||||
assert longIndex >= 0 && longIndex < length;
|
||||
assert longIndex >= 0 && longIndex < length();
|
||||
deleted.set(longIndex);
|
||||
underlying.setEmpty(index);
|
||||
return this;
|
||||
@ -154,7 +147,7 @@ final class DeletedArrayFilter extends ArrayFilter {
|
||||
|
||||
@Override
|
||||
public ArrayData delete(final long fromIndex, final long toIndex) {
|
||||
assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length;
|
||||
assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length();
|
||||
deleted.setRange(fromIndex, toIndex + 1);
|
||||
underlying.setEmpty(fromIndex, toIndex);
|
||||
return this;
|
||||
@ -162,7 +155,7 @@ final class DeletedArrayFilter extends ArrayFilter {
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
final long index = length - 1;
|
||||
final long index = length() - 1;
|
||||
|
||||
if (super.has((int)index)) {
|
||||
final boolean isDeleted = deleted.isSet(index);
|
||||
@ -179,7 +172,7 @@ final class DeletedArrayFilter extends ArrayFilter {
|
||||
final ArrayData newArray = underlying.slice(from, to);
|
||||
final DeletedArrayFilter newFilter = new DeletedArrayFilter(newArray);
|
||||
newFilter.getDeleted().copy(deleted);
|
||||
newFilter.getDeleted().shiftLeft(from, newFilter.length);
|
||||
newFilter.getDeleted().shiftLeft(from, newFilter.length());
|
||||
|
||||
return newFilter;
|
||||
}
|
||||
|
@ -42,10 +42,10 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
|
||||
}
|
||||
|
||||
private static ArrayData maybeSparse(final ArrayData underlying, final long hi) {
|
||||
if(hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) {
|
||||
if (hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) {
|
||||
return underlying;
|
||||
}
|
||||
return new SparseArrayData(underlying, underlying.length);
|
||||
return new SparseArrayData(underlying, underlying.length());
|
||||
}
|
||||
|
||||
private boolean isEmpty() {
|
||||
@ -93,7 +93,7 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
|
||||
|
||||
@Override
|
||||
public ArrayData ensure(final long safeIndex) {
|
||||
if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) {
|
||||
if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
|
||||
return new SparseArrayData(this, safeIndex + 1);
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
|
||||
@Override
|
||||
public ArrayData shiftRight(final int by) {
|
||||
super.shiftRight(by);
|
||||
final long len = length;
|
||||
final long len = length();
|
||||
lo = Math.min(len, lo + by);
|
||||
hi = Math.min(len - 1, hi + by);
|
||||
|
||||
@ -238,7 +238,7 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
final int index = (int)length - 1;
|
||||
final int index = (int)length() - 1;
|
||||
if (super.has(index)) {
|
||||
final boolean isDeleted = isDeleted(index);
|
||||
final Object value = super.pop();
|
||||
|
@ -26,9 +26,9 @@
|
||||
package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||
|
||||
import jdk.nashorn.internal.objects.Global;
|
||||
import jdk.nashorn.internal.runtime.PropertyDescriptor;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
|
||||
/**
|
||||
* ArrayData after the array has been frozen by Object.freeze call.
|
||||
@ -79,4 +79,15 @@ final class FrozenArrayFilter extends SealedArrayFilter {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData push(final boolean strict, final Object... items) {
|
||||
return this; //nop
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
final int len = (int)underlying.length();
|
||||
return len == 0 ? ScriptRuntime.UNDEFINED : underlying.getObject(len - 1);
|
||||
}
|
||||
}
|
||||
|
@ -119,22 +119,24 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
|
||||
@Override
|
||||
public IntArrayData copy() {
|
||||
return new IntArrayData(array.clone(), (int)length);
|
||||
return new IntArrayData(array.clone(), (int)length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asArrayOfType(final Class<?> componentType) {
|
||||
if (componentType == int.class) {
|
||||
return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length);
|
||||
final int len = (int)length();
|
||||
return array.length == len ? array.clone() : Arrays.copyOf(array, len);
|
||||
}
|
||||
return super.asArrayOfType(componentType);
|
||||
}
|
||||
|
||||
private Object[] toObjectArray(final boolean trim) {
|
||||
assert length <= array.length : "length exceeds internal array size";
|
||||
final Object[] oarray = new Object[trim ? (int)length : array.length];
|
||||
assert length() <= array.length : "length exceeds internal array size";
|
||||
final int len = (int)length();
|
||||
final Object[] oarray = new Object[trim ? len : array.length];
|
||||
|
||||
for (int index = 0; index < length; index++) {
|
||||
for (int index = 0; index < len; index++) {
|
||||
oarray[index] = Integer.valueOf(array[index]);
|
||||
}
|
||||
|
||||
@ -142,10 +144,11 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
}
|
||||
|
||||
private double[] toDoubleArray() {
|
||||
assert length <= array.length : "length exceeds internal array size";
|
||||
assert length() <= array.length : "length exceeds internal array size";
|
||||
final int len = (int)length();
|
||||
final double[] darray = new double[array.length];
|
||||
|
||||
for (int index = 0; index < length; index++) {
|
||||
for (int index = 0; index < len; index++) {
|
||||
darray[index] = array[index];
|
||||
}
|
||||
|
||||
@ -153,10 +156,11 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
}
|
||||
|
||||
private long[] toLongArray() {
|
||||
assert length <= array.length : "length exceeds internal array size";
|
||||
assert length() <= array.length : "length exceeds internal array size";
|
||||
final int len = (int)length();
|
||||
final long[] larray = new long[array.length];
|
||||
|
||||
for (int index = 0; index < length; index++) {
|
||||
for (int index = 0; index < len; index++) {
|
||||
larray[index] = array[index];
|
||||
}
|
||||
|
||||
@ -164,15 +168,15 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
}
|
||||
|
||||
private LongArrayData convertToLong() {
|
||||
return new LongArrayData(toLongArray(), (int)length);
|
||||
return new LongArrayData(toLongArray(), (int)length());
|
||||
}
|
||||
|
||||
private NumberArrayData convertToDouble() {
|
||||
return new NumberArrayData(toDoubleArray(), (int)length);
|
||||
return new NumberArrayData(toDoubleArray(), (int)length());
|
||||
}
|
||||
|
||||
private ObjectArrayData convertToObject() {
|
||||
return new ObjectArrayData(toObjectArray(false), (int)length);
|
||||
return new ObjectArrayData(toObjectArray(false), (int)length());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -196,7 +200,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
|
||||
@Override
|
||||
public ArrayData shiftRight(final int by) {
|
||||
final ArrayData newData = ensure(by + length - 1);
|
||||
final ArrayData newData = ensure(by + length() - 1);
|
||||
if (newData != this) {
|
||||
newData.shiftRight(by);
|
||||
return newData;
|
||||
@ -241,7 +245,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
@Override
|
||||
public ArrayData set(final int index, final int value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -250,7 +254,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
public ArrayData set(final int index, final long value, final boolean strict) {
|
||||
if (JSType.isRepresentableAsInt(value)) {
|
||||
array[index] = JSType.toInt32(value);
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -261,7 +265,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
public ArrayData set(final int index, final double value, final boolean strict) {
|
||||
if (JSType.isRepresentableAsInt(value)) {
|
||||
array[index] = (int)(long)value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -305,7 +309,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
|
||||
@Override
|
||||
public boolean has(final int index) {
|
||||
return 0 <= index && index < length;
|
||||
return 0 <= index && index < length();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -320,11 +324,12 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
if (length == 0) {
|
||||
final int len = (int)length();
|
||||
if (len == 0) {
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
|
||||
final int newLength = (int)length - 1;
|
||||
final int newLength = len - 1;
|
||||
final int elem = array[newLength];
|
||||
array[newLength] = 0;
|
||||
setLength(newLength);
|
||||
@ -334,12 +339,12 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
|
||||
@Override
|
||||
public ArrayData slice(final long from, final long to) {
|
||||
return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length : from)));
|
||||
return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length() : from)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ArrayData push(final boolean strict, final int item) {
|
||||
final long len = length;
|
||||
final long len = length();
|
||||
final ArrayData newData = ensure(len);
|
||||
if (newData == this) {
|
||||
array[(int)len] = item;
|
||||
@ -350,7 +355,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
|
||||
@Override
|
||||
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
|
||||
final long oldLength = length;
|
||||
final long oldLength = length();
|
||||
final long newLength = oldLength - removed + added;
|
||||
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
|
||||
throw new UnsupportedOperationException();
|
||||
@ -384,21 +389,21 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
|
||||
@Override
|
||||
public long fastPush(final int arg) {
|
||||
final int len = (int)length;
|
||||
final int len = (int)length();
|
||||
if (len == array.length) {
|
||||
array = Arrays.copyOf(array, nextSize(len));
|
||||
}
|
||||
array[len] = arg;
|
||||
return ++length;
|
||||
return increaseLength();
|
||||
}
|
||||
|
||||
//length must not be zero
|
||||
@Override
|
||||
public int fastPopInt() {
|
||||
if (length == 0) {
|
||||
if (length() == 0) {
|
||||
throw new ClassCastException(); //relink
|
||||
}
|
||||
final int newLength = (int)--length;
|
||||
final int newLength = (int)decreaseLength();
|
||||
final int elem = array[newLength];
|
||||
array[newLength] = 0;
|
||||
return elem;
|
||||
@ -421,8 +426,8 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
|
||||
@Override
|
||||
public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
|
||||
final int otherLength = (int)otherData.length;
|
||||
final int thisLength = (int)length;
|
||||
final int otherLength = (int)otherData.length();
|
||||
final int thisLength = (int)length();
|
||||
assert otherLength > 0 && thisLength > 0;
|
||||
|
||||
final int[] otherArray = ((IntArrayData)otherData).array;
|
||||
@ -437,7 +442,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
assert length <= array.length : length + " > " + array.length;
|
||||
return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length));
|
||||
assert length() <= array.length : length() + " > " + array.length;
|
||||
return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length()));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,198 @@
|
||||
package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
|
||||
/**
|
||||
* Filter to use for ArrayData where the length is not writable.
|
||||
* The default behavior is just to ignore {@link ArrayData#setLength}
|
||||
*/
|
||||
final class LengthNotWritableFilter extends ArrayFilter {
|
||||
private final SortedMap<Long, Object> extraElements; //elements with index >= length
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param underlying array
|
||||
*/
|
||||
LengthNotWritableFilter(final ArrayData underlying) {
|
||||
this(underlying, new TreeMap<Long, Object>());
|
||||
}
|
||||
|
||||
private LengthNotWritableFilter(final ArrayData underlying, final SortedMap<Long, Object> extraElements) {
|
||||
super(underlying);
|
||||
this.extraElements = extraElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData copy() {
|
||||
return new LengthNotWritableFilter(underlying.copy(), new TreeMap<>(extraElements));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(final int index) {
|
||||
return super.has(index) || extraElements.containsKey((long)index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the length of the data array
|
||||
*
|
||||
* @param length the new length for the data array
|
||||
*/
|
||||
@Override
|
||||
public void setLength(final long length) {
|
||||
//empty - setting length for a LengthNotWritableFilter is always a nop
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData ensure(final long index) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData slice(final long from, final long to) {
|
||||
//return array[from...to), or array[from...length] if undefined, in this case not as we are an ArrayData
|
||||
return new LengthNotWritableFilter(underlying.slice(from, to), extraElements.subMap(from, to));
|
||||
}
|
||||
|
||||
private boolean checkAdd(final long index, final Object value) {
|
||||
if (index >= length()) {
|
||||
extraElements.put(index, value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Object get(final long index) {
|
||||
final Object obj = extraElements.get(index);
|
||||
if (obj == null) {
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(final int index) {
|
||||
if (index >= length()) {
|
||||
return JSType.toInt32(get(index));
|
||||
}
|
||||
return underlying.getInt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntOptimistic(final int index, final int programPoint) {
|
||||
if (index >= length()) {
|
||||
return JSType.toInt32Optimistic(get(index), programPoint);
|
||||
}
|
||||
return underlying.getIntOptimistic(index, programPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(final int index) {
|
||||
if (index >= length()) {
|
||||
return JSType.toLong(get(index));
|
||||
}
|
||||
return underlying.getLong(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongOptimistic(final int index, final int programPoint) {
|
||||
if (index >= length()) {
|
||||
return JSType.toLongOptimistic(get(index), programPoint);
|
||||
}
|
||||
return underlying.getLongOptimistic(index, programPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(final int index) {
|
||||
if (index >= length()) {
|
||||
return JSType.toNumber(get(index));
|
||||
}
|
||||
return underlying.getDouble(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDoubleOptimistic(final int index, final int programPoint) {
|
||||
if (index >= length()) {
|
||||
return JSType.toNumberOptimistic(get(index), programPoint);
|
||||
}
|
||||
return underlying.getDoubleOptimistic(index, programPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getObject(final int index) {
|
||||
if (index >= length()) {
|
||||
return get(index);
|
||||
}
|
||||
return underlying.getObject(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final Object value, final boolean strict) {
|
||||
if (checkAdd(index, value)) {
|
||||
return this;
|
||||
}
|
||||
underlying = underlying.set(index, value, strict);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final int value, final boolean strict) {
|
||||
if (checkAdd(index, value)) {
|
||||
return this;
|
||||
}
|
||||
underlying = underlying.set(index, value, strict);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final long value, final boolean strict) {
|
||||
if (checkAdd(index, value)) {
|
||||
return this;
|
||||
}
|
||||
underlying = underlying.set(index, value, strict);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final double value, final boolean strict) {
|
||||
if (checkAdd(index, value)) {
|
||||
return this;
|
||||
}
|
||||
underlying = underlying.set(index, value, strict);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData delete(final int index) {
|
||||
extraElements.remove(index);
|
||||
underlying = underlying.delete(index);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData delete(final long fromIndex, final long toIndex) {
|
||||
for (final Iterator<Long> iter = extraElements.keySet().iterator(); iter.hasNext();) {
|
||||
final long next = iter.next();
|
||||
if (next >= fromIndex && next <= toIndex) {
|
||||
iter.remove();
|
||||
}
|
||||
if (next > toIndex) { //ordering guaranteed because TreeSet
|
||||
break;
|
||||
}
|
||||
}
|
||||
underlying = underlying.delete(fromIndex, toIndex);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Long> indexIterator() {
|
||||
final List<Long> keys = computeIteratorKeys();
|
||||
keys.addAll(extraElements.keySet()); //even if they are outside length this is fine
|
||||
return keys.iterator();
|
||||
}
|
||||
|
||||
}
|
@ -27,7 +27,6 @@ package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
|
||||
import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Arrays;
|
||||
@ -77,7 +76,7 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
|
||||
@Override
|
||||
public LongArrayData copy() {
|
||||
return new LongArrayData(array.clone(), (int)length);
|
||||
return new LongArrayData(array.clone(), (int)length());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -86,10 +85,11 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
}
|
||||
|
||||
private Object[] toObjectArray(final boolean trim) {
|
||||
assert length <= array.length : "length exceeds internal array size";
|
||||
final Object[] oarray = new Object[trim ? (int)length : array.length];
|
||||
assert length() <= array.length : "length exceeds internal array size";
|
||||
final int len = (int)length();
|
||||
final Object[] oarray = new Object[trim ? len : array.length];
|
||||
|
||||
for (int index = 0; index < length; index++) {
|
||||
for (int index = 0; index < len; index++) {
|
||||
oarray[index] = Long.valueOf(array[index]);
|
||||
}
|
||||
|
||||
@ -99,16 +99,18 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
@Override
|
||||
public Object asArrayOfType(final Class<?> componentType) {
|
||||
if (componentType == long.class) {
|
||||
return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length);
|
||||
final int len = (int)length();
|
||||
return array.length == len ? array.clone() : Arrays.copyOf(array, len);
|
||||
}
|
||||
return super.asArrayOfType(componentType);
|
||||
}
|
||||
|
||||
private double[] toDoubleArray() {
|
||||
assert length <= array.length : "length exceeds internal array size";
|
||||
assert length() <= array.length : "length exceeds internal array size";
|
||||
final int len = (int)length();
|
||||
final double[] darray = new double[array.length];
|
||||
|
||||
for (int index = 0; index < length; index++) {
|
||||
for (int index = 0; index < len; index++) {
|
||||
darray[index] = array[index];
|
||||
}
|
||||
|
||||
@ -120,7 +122,7 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
if (type == Integer.class || type == Long.class) {
|
||||
return this;
|
||||
}
|
||||
final int len = (int)length;
|
||||
final int len = (int)length();
|
||||
if (type == Double.class) {
|
||||
return new NumberArrayData(toDoubleArray(), len);
|
||||
}
|
||||
@ -134,7 +136,7 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
|
||||
@Override
|
||||
public ArrayData shiftRight(final int by) {
|
||||
final ArrayData newData = ensure(by + length - 1);
|
||||
final ArrayData newData = ensure(by + length() - 1);
|
||||
if (newData != this) {
|
||||
newData.shiftRight(by);
|
||||
return newData;
|
||||
@ -179,14 +181,14 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
@Override
|
||||
public ArrayData set(final int index, final int value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final long value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -194,7 +196,7 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
public ArrayData set(final int index, final double value, final boolean strict) {
|
||||
if (JSType.isRepresentableAsLong(value)) {
|
||||
array[index] = (long)value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
return convert(Double.class).set(index, value, strict);
|
||||
@ -265,7 +267,7 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
|
||||
@Override
|
||||
public boolean has(final int index) {
|
||||
return 0 <= index && index < length;
|
||||
return 0 <= index && index < length();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -280,11 +282,12 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
if (length == 0) {
|
||||
final int len = (int)length();
|
||||
if (len == 0) {
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
|
||||
final int newLength = (int)length - 1;
|
||||
final int newLength = len - 1;
|
||||
final long elem = array[newLength];
|
||||
array[newLength] = 0;
|
||||
setLength(newLength);
|
||||
@ -294,14 +297,14 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
|
||||
@Override
|
||||
public ArrayData slice(final long from, final long to) {
|
||||
final long start = from < 0 ? from + length : from;
|
||||
final long start = from < 0 ? from + length() : from;
|
||||
final long newLength = to - start;
|
||||
return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ArrayData push(final boolean strict, final long item) {
|
||||
final long len = length;
|
||||
final long len = length();
|
||||
final ArrayData newData = ensure(len);
|
||||
if (newData == this) {
|
||||
array[(int)len] = item;
|
||||
@ -312,7 +315,7 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
|
||||
@Override
|
||||
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
|
||||
final long oldLength = length;
|
||||
final long oldLength = length();
|
||||
final long newLength = oldLength - removed + added;
|
||||
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
|
||||
throw new UnsupportedOperationException();
|
||||
@ -345,20 +348,20 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
|
||||
@Override
|
||||
public long fastPush(final long arg) {
|
||||
final int len = (int)length;
|
||||
final int len = (int)length();
|
||||
if (len == array.length) {
|
||||
array = Arrays.copyOf(array, nextSize(len));
|
||||
}
|
||||
array[len] = arg;
|
||||
return ++length;
|
||||
return increaseLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long fastPopLong() {
|
||||
if (length == 0) {
|
||||
throw new ClassCastException();
|
||||
if (length() == 0) {
|
||||
throw new ClassCastException(); //undefined result
|
||||
}
|
||||
final int newLength = (int)--length;
|
||||
final int newLength = (int)decreaseLength();
|
||||
final long elem = array[newLength];
|
||||
array[newLength] = 0;
|
||||
return elem;
|
||||
@ -376,8 +379,8 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
|
||||
@Override
|
||||
public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
|
||||
final int otherLength = (int)otherData.length;
|
||||
final int thisLength = (int)length;
|
||||
final int otherLength = (int)otherData.length();
|
||||
final int thisLength = (int)length();
|
||||
assert otherLength > 0 && thisLength > 0;
|
||||
|
||||
final long[] otherArray = ((LongArrayData)otherData).array;
|
||||
@ -392,13 +395,14 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
assert length <= array.length : length + " > " + array.length;
|
||||
assert length() <= array.length : length() + " > " + array.length;
|
||||
|
||||
final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).
|
||||
append(": [");
|
||||
for (int i = 0; i < length; i++) {
|
||||
final int len = (int)length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
sb.append(array[i]).append('L'); //make sure L suffix is on elements, to discriminate this from IntArrayData.toString()
|
||||
if (i + 1 < length) {
|
||||
if (i + 1 < len) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
/**
|
||||
* Filter class that wrap arrays that have been tagged non extensible
|
||||
*/
|
||||
public class NonExtensibleArrayFilter extends ArrayFilter {
|
||||
final class NonExtensibleArrayFilter extends ArrayFilter {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param underlying array
|
||||
*/
|
||||
public NonExtensibleArrayFilter(final ArrayData underlying) {
|
||||
NonExtensibleArrayFilter(final ArrayData underlying) {
|
||||
super(underlying);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,6 @@ package jdk.nashorn.internal.runtime.arrays;
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
|
||||
import static jdk.nashorn.internal.lookup.Lookup.MH;
|
||||
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Arrays;
|
||||
@ -76,7 +75,7 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public NumberArrayData copy() {
|
||||
return new NumberArrayData(array.clone(), (int)length);
|
||||
return new NumberArrayData(array.clone(), (int)length());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,10 +84,11 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
}
|
||||
|
||||
private Object[] toObjectArray(final boolean trim) {
|
||||
assert length <= array.length : "length exceeds internal array size";
|
||||
final Object[] oarray = new Object[trim ? (int)length : array.length];
|
||||
assert length() <= array.length : "length exceeds internal array size";
|
||||
final int len = (int)length();
|
||||
final Object[] oarray = new Object[trim ? len : array.length];
|
||||
|
||||
for (int index = 0; index < length; index++) {
|
||||
for (int index = 0; index < len; index++) {
|
||||
oarray[index] = Double.valueOf(array[index]);
|
||||
}
|
||||
return oarray;
|
||||
@ -96,8 +96,9 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public Object asArrayOfType(final Class<?> componentType) {
|
||||
if(componentType == double.class) {
|
||||
return array.length == length ? array.clone() : Arrays.copyOf(array, (int)length);
|
||||
if (componentType == double.class) {
|
||||
final int len = (int)length();
|
||||
return array.length == len ? array.clone() : Arrays.copyOf(array, len);
|
||||
}
|
||||
return super.asArrayOfType(componentType);
|
||||
}
|
||||
@ -105,7 +106,7 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
@Override
|
||||
public ContinuousArrayData convert(final Class<?> type) {
|
||||
if (type != Double.class && type != Integer.class && type != Long.class) {
|
||||
final int len = (int)length;
|
||||
final int len = (int)length();
|
||||
return new ObjectArrayData(toObjectArray(false), len);
|
||||
}
|
||||
return this;
|
||||
@ -118,7 +119,7 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public ArrayData shiftRight(final int by) {
|
||||
final ArrayData newData = ensure(by + length - 1);
|
||||
final ArrayData newData = ensure(by + length() - 1);
|
||||
if (newData != this) {
|
||||
newData.shiftRight(by);
|
||||
return newData;
|
||||
@ -163,21 +164,21 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
@Override
|
||||
public ArrayData set(final int index, final int value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final long value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final double value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -241,7 +242,7 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public boolean has(final int index) {
|
||||
return 0 <= index && index < length;
|
||||
return 0 <= index && index < length();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -256,11 +257,12 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
if (length == 0) {
|
||||
final int len = (int)length();
|
||||
if (len == 0) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
final int newLength = (int)length - 1;
|
||||
final int newLength = len - 1;
|
||||
final double elem = array[newLength];
|
||||
array[newLength] = 0;
|
||||
setLength(newLength);
|
||||
@ -269,14 +271,14 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public ArrayData slice(final long from, final long to) {
|
||||
final long start = from < 0 ? from + length : from;
|
||||
final long start = from < 0 ? from + length() : from;
|
||||
final long newLength = to - start;
|
||||
return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ArrayData push(final boolean strict, final double item) {
|
||||
final long len = length;
|
||||
final long len = length();
|
||||
final ArrayData newData = ensure(len);
|
||||
if (newData == this) {
|
||||
array[(int)len] = item;
|
||||
@ -287,7 +289,7 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
|
||||
final long oldLength = length;
|
||||
final long oldLength = length();
|
||||
final long newLength = oldLength - removed + added;
|
||||
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
|
||||
throw new UnsupportedOperationException();
|
||||
@ -325,21 +327,21 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public long fastPush(final double arg) {
|
||||
final int len = (int)length;
|
||||
final int len = (int)length();
|
||||
if (len == array.length) {
|
||||
//note that fastpush never creates spares arrays, there is nothing to gain by that - it will just use even more memory
|
||||
array = Arrays.copyOf(array, nextSize(len));
|
||||
}
|
||||
array[len] = arg;
|
||||
return ++length;
|
||||
return increaseLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double fastPopDouble() {
|
||||
if (length == 0) {
|
||||
if (length() == 0) {
|
||||
throw new ClassCastException();
|
||||
}
|
||||
final int newLength = (int)--length;
|
||||
final int newLength = (int)decreaseLength();
|
||||
final double elem = array[newLength];
|
||||
array[newLength] = 0;
|
||||
return elem;
|
||||
@ -352,8 +354,8 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
|
||||
final int otherLength = (int)otherData.length;
|
||||
final int thisLength = (int)length;
|
||||
final int otherLength = (int)otherData.length();
|
||||
final int thisLength = (int)length();
|
||||
assert otherLength > 0 && thisLength > 0;
|
||||
|
||||
final double[] otherArray = ((NumberArrayData)otherData).array;
|
||||
@ -368,7 +370,7 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
assert length <= array.length : length + " > " + array.length;
|
||||
return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length));
|
||||
assert length() <= array.length : length() + " > " + array.length;
|
||||
return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length()));
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
package jdk.nashorn.internal.runtime.arrays;
|
||||
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Arrays;
|
||||
@ -77,16 +76,16 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
|
||||
@Override
|
||||
public ObjectArrayData copy() {
|
||||
return new ObjectArrayData(array.clone(), (int)length);
|
||||
return new ObjectArrayData(array.clone(), (int)length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] asObjectArray() {
|
||||
return array.length == length ? array.clone() : asObjectArrayCopy();
|
||||
return array.length == length() ? array.clone() : asObjectArrayCopy();
|
||||
}
|
||||
|
||||
private Object[] asObjectArrayCopy() {
|
||||
final long len = length;
|
||||
final long len = length();
|
||||
assert len <= Integer.MAX_VALUE;
|
||||
final Object[] copy = new Object[(int)len];
|
||||
System.arraycopy(array, 0, copy, 0, (int)len);
|
||||
@ -105,7 +104,7 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
|
||||
@Override
|
||||
public ArrayData shiftRight(final int by) {
|
||||
final ArrayData newData = ensure(by + length - 1);
|
||||
final ArrayData newData = ensure(by + length() - 1);
|
||||
if (newData != this) {
|
||||
newData.shiftRight(by);
|
||||
return newData;
|
||||
@ -137,28 +136,28 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
@Override
|
||||
public ArrayData set(final int index, final Object value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final int value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final long value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData set(final int index, final double value, final boolean strict) {
|
||||
array[index] = value;
|
||||
setLength(Math.max(index + 1, length));
|
||||
setLength(Math.max(index + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -231,7 +230,7 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
|
||||
@Override
|
||||
public boolean has(final int index) {
|
||||
return 0 <= index && index < length;
|
||||
return 0 <= index && index < length();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -263,20 +262,20 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
|
||||
@Override
|
||||
public long fastPush(final Object arg) {
|
||||
final int len = (int)length;
|
||||
final int len = (int)length();
|
||||
if (len == array.length) {
|
||||
array = Arrays.copyOf(array, nextSize(len));
|
||||
}
|
||||
array[len] = arg;
|
||||
return ++length;
|
||||
return increaseLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fastPopObject() {
|
||||
if (length == 0) {
|
||||
if (length() == 0) {
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
final int newLength = (int)--length;
|
||||
final int newLength = (int)decreaseLength();
|
||||
final Object elem = array[newLength];
|
||||
array[newLength] = ScriptRuntime.EMPTY;
|
||||
return elem;
|
||||
@ -284,11 +283,11 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
if (length == 0) {
|
||||
if (length() == 0) {
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
|
||||
final int newLength = (int)length - 1;
|
||||
final int newLength = (int)length() - 1;
|
||||
final Object elem = array[newLength];
|
||||
setEmpty(newLength);
|
||||
setLength(newLength);
|
||||
@ -297,14 +296,14 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
|
||||
@Override
|
||||
public ArrayData slice(final long from, final long to) {
|
||||
final long start = from < 0 ? from + length : from;
|
||||
final long start = from < 0 ? from + length() : from;
|
||||
final long newLength = to - start;
|
||||
return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData push(final boolean strict, final Object item) {
|
||||
final long len = length;
|
||||
final long len = length();
|
||||
final ArrayData newData = ensure(len);
|
||||
if (newData == this) {
|
||||
array[(int)len] = item;
|
||||
@ -315,7 +314,7 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
|
||||
@Override
|
||||
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
|
||||
final long oldLength = length;
|
||||
final long oldLength = length();
|
||||
final long newLength = oldLength - removed + added;
|
||||
if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
|
||||
throw new UnsupportedOperationException();
|
||||
@ -343,8 +342,8 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
|
||||
@Override
|
||||
public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
|
||||
final int otherLength = (int)otherData.length;
|
||||
final int thisLength = (int)length;
|
||||
final int otherLength = (int)otherData.length();
|
||||
final int thisLength = (int)length();
|
||||
assert otherLength > 0 && thisLength > 0;
|
||||
|
||||
final Object[] otherArray = ((ObjectArrayData)otherData).array;
|
||||
@ -359,7 +358,7 @@ final class ObjectArrayData extends ContinuousArrayData implements AnyElements {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
assert length <= array.length : length + " > " + array.length;
|
||||
return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length));
|
||||
assert length() <= array.length : length() + " > " + array.length;
|
||||
return getClass().getSimpleName() + ':' + Arrays.toString(Arrays.copyOf(array, (int)length()));
|
||||
}
|
||||
}
|
||||
|
@ -53,21 +53,21 @@ class SparseArrayData extends ArrayData {
|
||||
|
||||
SparseArrayData(final ArrayData underlying, final long length, final TreeMap<Long, Object> sparseMap) {
|
||||
super(length);
|
||||
assert underlying.length <= length;
|
||||
assert underlying.length() <= length;
|
||||
this.underlying = underlying;
|
||||
this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length);
|
||||
this.maxDenseLength = Math.max(MAX_DENSE_LENGTH, underlying.length());
|
||||
this.sparseMap = sparseMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData copy() {
|
||||
return new SparseArrayData(underlying.copy(), length, new TreeMap<>(sparseMap));
|
||||
return new SparseArrayData(underlying.copy(), length(), new TreeMap<>(sparseMap));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] asObjectArray() {
|
||||
final int len = (int)Math.min(length, Integer.MAX_VALUE);
|
||||
final int underlyingLength = (int)Math.min(len, underlying.length);
|
||||
final int len = (int)Math.min(length(), Integer.MAX_VALUE);
|
||||
final int underlyingLength = (int)Math.min(len, underlying.length());
|
||||
final Object[] objArray = new Object[len];
|
||||
|
||||
for (int i = 0; i < underlyingLength; i++) {
|
||||
@ -104,14 +104,15 @@ class SparseArrayData extends ArrayData {
|
||||
}
|
||||
|
||||
sparseMap = newSparseMap;
|
||||
setLength(Math.max(length - by, 0));
|
||||
setLength(Math.max(length() - by, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData shiftRight(final int by) {
|
||||
final TreeMap<Long, Object> newSparseMap = new TreeMap<>();
|
||||
if (underlying.length + by > maxDenseLength) {
|
||||
for (long i = maxDenseLength - by; i < underlying.length; i++) {
|
||||
final long len = underlying.length();
|
||||
if (len + by > maxDenseLength) {
|
||||
for (long i = maxDenseLength - by; i < len; i++) {
|
||||
if (underlying.has((int) i)) {
|
||||
newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i));
|
||||
}
|
||||
@ -127,23 +128,23 @@ class SparseArrayData extends ArrayData {
|
||||
}
|
||||
|
||||
sparseMap = newSparseMap;
|
||||
setLength(length + by);
|
||||
setLength(length() + by);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData ensure(final long safeIndex) {
|
||||
if (safeIndex < maxDenseLength && underlying.length <= safeIndex) {
|
||||
if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) {
|
||||
underlying = underlying.ensure(safeIndex);
|
||||
}
|
||||
setLength(Math.max(safeIndex + 1, length));
|
||||
setLength(Math.max(safeIndex + 1, length()));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData shrink(final long newLength) {
|
||||
if (newLength < underlying.length) {
|
||||
if (newLength < underlying.length()) {
|
||||
underlying = underlying.shrink(newLength);
|
||||
underlying.setLength(newLength);
|
||||
sparseMap.clear();
|
||||
@ -160,11 +161,11 @@ class SparseArrayData extends ArrayData {
|
||||
if (index >= 0 && index < maxDenseLength) {
|
||||
ensure(index);
|
||||
underlying = underlying.set(index, value, strict);
|
||||
setLength(Math.max(underlying.length, length));
|
||||
setLength(Math.max(underlying.length(), length()));
|
||||
} else {
|
||||
final Long longIndex = indexToKey(index);
|
||||
sparseMap.put(longIndex, value);
|
||||
setLength(Math.max(longIndex + 1, length));
|
||||
setLength(Math.max(longIndex + 1, length()));
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -175,11 +176,11 @@ class SparseArrayData extends ArrayData {
|
||||
if (index >= 0 && index < maxDenseLength) {
|
||||
ensure(index);
|
||||
underlying = underlying.set(index, value, strict);
|
||||
setLength(Math.max(underlying.length, length));
|
||||
setLength(Math.max(underlying.length(), length()));
|
||||
} else {
|
||||
final Long longIndex = indexToKey(index);
|
||||
sparseMap.put(longIndex, value);
|
||||
setLength(Math.max(longIndex + 1, length));
|
||||
setLength(Math.max(longIndex + 1, length()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -189,11 +190,11 @@ class SparseArrayData extends ArrayData {
|
||||
if (index >= 0 && index < maxDenseLength) {
|
||||
ensure(index);
|
||||
underlying = underlying.set(index, value, strict);
|
||||
setLength(Math.max(underlying.length, length));
|
||||
setLength(Math.max(underlying.length(), length()));
|
||||
} else {
|
||||
final Long longIndex = indexToKey(index);
|
||||
sparseMap.put(longIndex, value);
|
||||
setLength(Math.max(longIndex + 1, length));
|
||||
setLength(Math.max(longIndex + 1, length()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -203,11 +204,11 @@ class SparseArrayData extends ArrayData {
|
||||
if (index >= 0 && index < maxDenseLength) {
|
||||
ensure(index);
|
||||
underlying = underlying.set(index, value, strict);
|
||||
setLength(Math.max(underlying.length, length));
|
||||
setLength(Math.max(underlying.length(), length()));
|
||||
} else {
|
||||
final Long longIndex = indexToKey(index);
|
||||
sparseMap.put(longIndex, value);
|
||||
setLength(Math.max(longIndex + 1, length));
|
||||
setLength(Math.max(longIndex + 1, length()));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -294,7 +295,7 @@ class SparseArrayData extends ArrayData {
|
||||
@Override
|
||||
public boolean has(final int index) {
|
||||
if (index >= 0 && index < maxDenseLength) {
|
||||
return index < underlying.length && underlying.has(index);
|
||||
return index < underlying.length() && underlying.has(index);
|
||||
}
|
||||
|
||||
return sparseMap.containsKey(indexToKey(index));
|
||||
@ -303,7 +304,7 @@ class SparseArrayData extends ArrayData {
|
||||
@Override
|
||||
public ArrayData delete(final int index) {
|
||||
if (index >= 0 && index < maxDenseLength) {
|
||||
if (index < underlying.length) {
|
||||
if (index < underlying.length()) {
|
||||
underlying = underlying.delete(index);
|
||||
}
|
||||
} else {
|
||||
@ -315,8 +316,8 @@ class SparseArrayData extends ArrayData {
|
||||
|
||||
@Override
|
||||
public ArrayData delete(final long fromIndex, final long toIndex) {
|
||||
if (fromIndex < maxDenseLength && fromIndex < underlying.length) {
|
||||
underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length - 1));
|
||||
if (fromIndex < maxDenseLength && fromIndex < underlying.length()) {
|
||||
underlying = underlying.delete(fromIndex, Math.min(toIndex, underlying.length() - 1));
|
||||
}
|
||||
if (toIndex >= maxDenseLength) {
|
||||
sparseMap.subMap(fromIndex, true, toIndex, true).clear();
|
||||
@ -336,30 +337,34 @@ class SparseArrayData extends ArrayData {
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
if (length == 0) {
|
||||
final long len = length();
|
||||
final long underlyingLen = underlying.length();
|
||||
if (len == 0) {
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
if (length == underlying.length) {
|
||||
if (len == underlyingLen) {
|
||||
final Object result = underlying.pop();
|
||||
setLength(underlying.length);
|
||||
setLength(underlying.length());
|
||||
return result;
|
||||
}
|
||||
setLength(length - 1);
|
||||
final Long key = Long.valueOf(length);
|
||||
setLength(len - 1);
|
||||
final Long key = Long.valueOf(len - 1);
|
||||
return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData slice(final long from, final long to) {
|
||||
assert to <= length;
|
||||
final long start = from < 0 ? (from + length) : from;
|
||||
assert to <= length();
|
||||
final long start = from < 0 ? (from + length()) : from;
|
||||
final long newLength = to - start;
|
||||
|
||||
final long underlyingLength = underlying.length();
|
||||
|
||||
if (start >= 0 && to <= maxDenseLength) {
|
||||
if (newLength <= underlying.length) {
|
||||
if (newLength <= underlyingLength) {
|
||||
return underlying.slice(from, to);
|
||||
}
|
||||
return underlying.slice(from, to).ensure(newLength - 1).delete(underlying.length, newLength);
|
||||
return underlying.slice(from, to).ensure(newLength - 1).delete(underlyingLength, newLength);
|
||||
}
|
||||
|
||||
ArrayData sliced = EMPTY_ARRAY;
|
||||
@ -369,13 +374,13 @@ class SparseArrayData extends ArrayData {
|
||||
sliced = sliced.set((int)(i - start), getObject((int)i), false);
|
||||
}
|
||||
}
|
||||
assert sliced.length == newLength;
|
||||
assert sliced.length() == newLength;
|
||||
return sliced;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextIndex(final long index) {
|
||||
if (index < underlying.length - 1) {
|
||||
if (index < underlying.length() - 1) {
|
||||
return underlying.nextIndex(index);
|
||||
}
|
||||
|
||||
@ -383,6 +388,7 @@ class SparseArrayData extends ArrayData {
|
||||
if (nextKey != null) {
|
||||
return nextKey;
|
||||
}
|
||||
return length;
|
||||
|
||||
return length();
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public abstract class TypedArrayData<T extends Buffer> extends ContinuousArrayDa
|
||||
* @return element length
|
||||
*/
|
||||
public final int getElementLength() {
|
||||
return (int)length;
|
||||
return (int)length();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,7 +119,7 @@ public abstract class TypedArrayData<T extends Buffer> extends ContinuousArrayDa
|
||||
|
||||
@Override
|
||||
public final boolean has(final int index) {
|
||||
return 0 <= index && index < length;
|
||||
return 0 <= index && index < length();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,8 +39,7 @@ final class UndefinedArrayFilter extends ArrayFilter {
|
||||
|
||||
UndefinedArrayFilter(final ArrayData underlying) {
|
||||
super(underlying);
|
||||
|
||||
this.undefined = new BitVector(underlying.length);
|
||||
this.undefined = new BitVector(underlying.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,25 +79,24 @@ final class UndefinedArrayFilter extends ArrayFilter {
|
||||
@Override
|
||||
public void shiftLeft(final int by) {
|
||||
super.shiftLeft(by);
|
||||
undefined.shiftLeft(by, length);
|
||||
undefined.shiftLeft(by, length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData shiftRight(final int by) {
|
||||
super.shiftRight(by);
|
||||
undefined.shiftRight(by, length);
|
||||
|
||||
undefined.shiftRight(by, length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayData ensure(final long safeIndex) {
|
||||
if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length) {
|
||||
if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
|
||||
return new SparseArrayData(this, safeIndex + 1);
|
||||
}
|
||||
|
||||
super.ensure(safeIndex);
|
||||
undefined.resize(length);
|
||||
undefined.resize(length());
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -106,8 +104,7 @@ final class UndefinedArrayFilter extends ArrayFilter {
|
||||
@Override
|
||||
public ArrayData shrink(final long newLength) {
|
||||
super.shrink(newLength);
|
||||
undefined.resize(length);
|
||||
|
||||
undefined.resize(length());
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -216,7 +213,7 @@ final class UndefinedArrayFilter extends ArrayFilter {
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
final long index = length - 1;
|
||||
final long index = length() - 1;
|
||||
|
||||
if (super.has((int)index)) {
|
||||
final boolean isUndefined = undefined.isSet(index);
|
||||
@ -233,7 +230,7 @@ final class UndefinedArrayFilter extends ArrayFilter {
|
||||
final ArrayData newArray = underlying.slice(from, to);
|
||||
final UndefinedArrayFilter newFilter = new UndefinedArrayFilter(newArray);
|
||||
newFilter.getUndefined().copy(undefined);
|
||||
newFilter.getUndefined().shiftLeft(from, newFilter.length);
|
||||
newFilter.getUndefined().shiftLeft(from, newFilter.length());
|
||||
|
||||
return newFilter;
|
||||
}
|
||||
|
225
nashorn/test/script/basic/JDK-8035312.js
Normal file
225
nashorn/test/script/basic/JDK-8035312.js
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8035312 push to frozen array must not increase length property
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
* @fork
|
||||
* @option -Dnashorn.debug=true
|
||||
*/
|
||||
|
||||
function printArrayDataClass(x) {
|
||||
if (typeof Debug !== 'undefined') {
|
||||
print(Debug.getArrayDataClass(x));
|
||||
}
|
||||
}
|
||||
|
||||
function gpush(x, elem) {
|
||||
try {
|
||||
print("Pushing " + elem + " to " + x);
|
||||
x.push(elem);
|
||||
} catch (e) {
|
||||
print("caught error" + e);
|
||||
}
|
||||
print("\tarray is now [" + x + "] length is = " + x.length);
|
||||
print();
|
||||
printArrayDataClass(x);
|
||||
}
|
||||
|
||||
function gpop(x) {
|
||||
try {
|
||||
print("Popping from " + x);
|
||||
x.pop();
|
||||
} catch (e) {
|
||||
if (!(e instanceof TypeError)) {
|
||||
print("e of wrong type " + e);
|
||||
}
|
||||
}
|
||||
print("\tarray is now [" + x + "] length is = " + x.length);
|
||||
print();
|
||||
printArrayDataClass(x);
|
||||
}
|
||||
|
||||
function checkArray(x) {
|
||||
print();
|
||||
print(">>> Push test");
|
||||
|
||||
var olen = x.length;
|
||||
gpush(x, 0);
|
||||
|
||||
print("x.length === " + x.length + " (should be " + olen + ")");
|
||||
print("x[3] === " + x[3] + " (should be 0)");
|
||||
print("x[4] === " + x[4] + " (should be undefined)");
|
||||
|
||||
print();
|
||||
print(">>> Pop test");
|
||||
gpop(x);
|
||||
gpop(x);
|
||||
print("x.length === " + x.length + " (should be " + olen + ")");
|
||||
print("x === " + x);
|
||||
|
||||
for (var i = 0 ; i < 5; i++) {
|
||||
gpop(x);
|
||||
}
|
||||
|
||||
print("x.length === " + x.length + " (should be " + olen + ")");
|
||||
print("x === " + x);
|
||||
}
|
||||
|
||||
print("*** Freezing");
|
||||
var frozen = [1,2,3];
|
||||
Object.freeze(frozen);
|
||||
checkArray(frozen);
|
||||
printArrayDataClass(frozen);
|
||||
|
||||
//so far so good
|
||||
|
||||
print();
|
||||
print("*** Other length not writable issues");
|
||||
var lengthNotWritable = [1,2,3];
|
||||
Object.defineProperty(lengthNotWritable, "length", { writable: false });
|
||||
checkArray(lengthNotWritable);
|
||||
printArrayDataClass(lengthNotWritable);
|
||||
|
||||
function set(array, from, to, stride) {
|
||||
//add three elements
|
||||
for (var i = from; i < to; i+=stride) {
|
||||
try {
|
||||
print("Writing " + i);
|
||||
array[i] = i;
|
||||
printArrayDataClass(array);
|
||||
} catch (e) {
|
||||
print(e instanceof TypeError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//define empty array with non writable length
|
||||
var arr = [1];
|
||||
Object.defineProperty(arr, "length", { writable: false });
|
||||
|
||||
var olen2 = arr.length;
|
||||
|
||||
set(arr, 0, 3, 1);
|
||||
|
||||
if (arr.length != olen2) {
|
||||
throw new ("error: " + arr.length + " != " + olen2);
|
||||
}
|
||||
|
||||
print();
|
||||
print("array writing 0-3, with 1 stride, array = " + arr);
|
||||
print("length = " + arr.length + ", but elements are: " + arr[0] + " " + arr[1] + " " + arr[2]);
|
||||
print();
|
||||
|
||||
//do the same but sparse/deleted range
|
||||
var arr2 = [1];
|
||||
Object.defineProperty(arr2, "length", { writable: false });
|
||||
|
||||
print("initial length = " + arr2.length);
|
||||
var olen3 = arr2.length;
|
||||
|
||||
set(arr2, 0, 30, 3);
|
||||
|
||||
if (arr2.length != olen3) {
|
||||
throw new ("error: " + arr2.length + " != " + olen3);
|
||||
}
|
||||
|
||||
print();
|
||||
var larger = 20;
|
||||
print("array writing 0-" + larger + ", with 3 stride, array = " + arr2);
|
||||
print("length = " + arr2.length + ", but elements are: " + arr2[0] + " " + arr2[1] + " " + arr2[2]);
|
||||
|
||||
for (var i = 0; i < larger; i++) {
|
||||
if (arr2[i] === undefined) {
|
||||
continue;
|
||||
}
|
||||
print(arr2[i] + " has length " + arr2.length);
|
||||
}
|
||||
|
||||
print();
|
||||
var elem = 0x7fffffff - 10;
|
||||
printArrayDataClass(arr2);
|
||||
print("adding a new element high up in the array");
|
||||
print("length before element was added " + arr2.length);
|
||||
print("putting sparse at " + elem);
|
||||
arr2[elem] = "sparse";
|
||||
print("length after element was added " + arr2.length + " should be the same");
|
||||
printArrayDataClass(arr2);
|
||||
|
||||
print();
|
||||
print("Printing arr2 - this will fail if length is > 28 and it is " + arr2.length);
|
||||
print("arr2 = [" + arr2 + "]");
|
||||
print("new length that should not be writable = " + arr2.length);
|
||||
print(arr2[elem] === "sparse");
|
||||
print(arr2[elem]);
|
||||
for (var i = 0; i < larger; i++) {
|
||||
print(arr2[i]);
|
||||
}
|
||||
for (var key in arr2) {
|
||||
print(key + ":" + arr2[key]);
|
||||
}
|
||||
|
||||
//issues reported by sundar - generic setter doesn't go through push/pop bulkable
|
||||
|
||||
function sundarExample2(arr, _writable) {
|
||||
print("Checking if push works for bulkable non bulkable arrays - Setting length property not allowed");
|
||||
arr[0] = "bar";
|
||||
print(arr.length + " should be 1"); // should be 1
|
||||
print(arr[0] + " should be bar");
|
||||
print("["+ arr + "] should be [bar]");
|
||||
|
||||
// Object.defineProperty(arr, "length", { configurable: _writable });
|
||||
Object.defineProperty(arr, "length", { writable: _writable });
|
||||
arr[1] = "baz";
|
||||
|
||||
if (_writable) {
|
||||
print(arr.length + " should be 2");
|
||||
print(arr[0] + " should be bar");
|
||||
print(arr[1] + " should be baz");
|
||||
print("["+ arr + "] should be [bar,baz]");
|
||||
} else {
|
||||
print(arr.length + " should STILL be 1");
|
||||
print(arr[0] + " should be bar");
|
||||
print(arr[1] + " should be baz");
|
||||
print("["+ arr + "] should be [bar]");
|
||||
}
|
||||
}
|
||||
|
||||
var newArr1 = [];
|
||||
sundarExample2(newArr1, false);
|
||||
print();
|
||||
try {
|
||||
sundarExample2(newArr1, true);
|
||||
print("should not get here");
|
||||
} catch (e) {
|
||||
if (!(e instanceof TypeError)) {
|
||||
print("Wrong exception");
|
||||
}
|
||||
print("got TypeError when redefining length, as expected")
|
||||
}
|
||||
print();
|
||||
|
||||
sundarExample2([], true);
|
||||
print("Done");
|
186
nashorn/test/script/basic/JDK-8035312.js.EXPECTED
Normal file
186
nashorn/test/script/basic/JDK-8035312.js.EXPECTED
Normal file
@ -0,0 +1,186 @@
|
||||
*** Freezing
|
||||
|
||||
>>> Push test
|
||||
Pushing 0 to 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
|
||||
x.length === 3 (should be 3)
|
||||
x[3] === undefined (should be 0)
|
||||
x[4] === undefined (should be undefined)
|
||||
|
||||
>>> Pop test
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
|
||||
x.length === 3 (should be 3)
|
||||
x === 1,2,3
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
|
||||
x.length === 3 (should be 3)
|
||||
x === 1,2,3
|
||||
class jdk.nashorn.internal.runtime.arrays.FrozenArrayFilter
|
||||
|
||||
*** Other length not writable issues
|
||||
|
||||
>>> Push test
|
||||
Pushing 0 to 1,2,3
|
||||
caught errorTypeError: "length" is not a writable property of [object Array]
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
x.length === 3 (should be 3)
|
||||
x[3] === 0 (should be 0)
|
||||
x[4] === undefined (should be undefined)
|
||||
|
||||
>>> Pop test
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
x.length === 3 (should be 3)
|
||||
x === 1,2,3
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Popping from 1,2,3
|
||||
array is now [1,2,3] length is = 3
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
x.length === 3 (should be 3)
|
||||
x === 1,2,3
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 0
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 1
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 2
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
|
||||
array writing 0-3, with 1 stride, array = 0
|
||||
length = 1, but elements are: 0 undefined 2
|
||||
|
||||
initial length = 1
|
||||
Writing 0
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 3
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 6
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 9
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 12
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 15
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 18
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 21
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 24
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
Writing 27
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
|
||||
array writing 0-20, with 3 stride, array = 0
|
||||
length = 1, but elements are: 0 undefined undefined
|
||||
0 has length 1
|
||||
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
adding a new element high up in the array
|
||||
length before element was added 1
|
||||
putting sparse at 2147483637
|
||||
length after element was added 1 should be the same
|
||||
class jdk.nashorn.internal.runtime.arrays.LengthNotWritableFilter
|
||||
|
||||
Printing arr2 - this will fail if length is > 28 and it is 1
|
||||
arr2 = [0]
|
||||
new length that should not be writable = 1
|
||||
true
|
||||
sparse
|
||||
0
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
undefined
|
||||
0:0
|
||||
2147483637:sparse
|
||||
Checking if push works for bulkable non bulkable arrays - Setting length property not allowed
|
||||
1 should be 1
|
||||
bar should be bar
|
||||
[bar] should be [bar]
|
||||
1 should STILL be 1
|
||||
bar should be bar
|
||||
baz should be baz
|
||||
[bar] should be [bar]
|
||||
|
||||
Checking if push works for bulkable non bulkable arrays - Setting length property not allowed
|
||||
1 should be 1
|
||||
bar should be bar
|
||||
[bar] should be [bar]
|
||||
got TypeError when redefining length, as expected
|
||||
|
||||
Checking if push works for bulkable non bulkable arrays - Setting length property not allowed
|
||||
1 should be 1
|
||||
bar should be bar
|
||||
[bar] should be [bar]
|
||||
2 should be 2
|
||||
bar should be bar
|
||||
baz should be baz
|
||||
[bar,baz] should be [bar,baz]
|
||||
Done
|
65
nashorn/test/script/basic/JDK-8035312_2.js
Normal file
65
nashorn/test/script/basic/JDK-8035312_2.js
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8035312_2 - length setter and iterators
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
"use strict"
|
||||
|
||||
function printArray(a,n) {
|
||||
print("PRINT_ARRAY CALLED: length = " + a.length);
|
||||
print();
|
||||
|
||||
print("INDEXED");
|
||||
for (var x = 0; x<n; x++) {
|
||||
print("\t" + x + ":"+a[x]);
|
||||
}
|
||||
print("KEYS");
|
||||
for (var key in a) {
|
||||
print("\t" + key + ";" + a[key]);
|
||||
}
|
||||
}
|
||||
|
||||
var b = [1,2,3];
|
||||
|
||||
Object.defineProperty(b, "length", { writable: false });
|
||||
var high = 8;
|
||||
b[high] = high;
|
||||
|
||||
printArray(b, high + 5);
|
||||
|
||||
var c = [1,2,3];
|
||||
c[high] = high;
|
||||
print();
|
||||
print("element[" + high + "]: " + c.length + " " + c[high]);
|
||||
print("Resetting length");
|
||||
c.length = 3;
|
||||
print("element[" + high + "]: " + c.length + " " + c[high]);
|
||||
print();
|
||||
|
||||
printArray(c, high + 5);
|
||||
print();
|
47
nashorn/test/script/basic/JDK-8035312_2.js.EXPECTED
Normal file
47
nashorn/test/script/basic/JDK-8035312_2.js.EXPECTED
Normal file
@ -0,0 +1,47 @@
|
||||
PRINT_ARRAY CALLED: length = 3
|
||||
|
||||
INDEXED
|
||||
0:1
|
||||
1:2
|
||||
2:3
|
||||
3:undefined
|
||||
4:undefined
|
||||
5:undefined
|
||||
6:undefined
|
||||
7:undefined
|
||||
8:8
|
||||
9:undefined
|
||||
10:undefined
|
||||
11:undefined
|
||||
12:undefined
|
||||
KEYS
|
||||
0;1
|
||||
1;2
|
||||
2;3
|
||||
8;8
|
||||
|
||||
element[8]: 9 8
|
||||
Resetting length
|
||||
element[8]: 3 undefined
|
||||
|
||||
PRINT_ARRAY CALLED: length = 3
|
||||
|
||||
INDEXED
|
||||
0:1
|
||||
1:2
|
||||
2:3
|
||||
3:undefined
|
||||
4:undefined
|
||||
5:undefined
|
||||
6:undefined
|
||||
7:undefined
|
||||
8:undefined
|
||||
9:undefined
|
||||
10:undefined
|
||||
11:undefined
|
||||
12:undefined
|
||||
KEYS
|
||||
0;1
|
||||
1;2
|
||||
2;3
|
||||
|
43
nashorn/test/script/basic/JDK-8035312_3.js
Normal file
43
nashorn/test/script/basic/JDK-8035312_3.js
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8035312_3 - sparse array, non writable length
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
var b = [1,2,3];
|
||||
|
||||
Object.defineProperty(b, "length", { writable: false });
|
||||
var high = 23534343;
|
||||
b[high-10] = high-10;
|
||||
|
||||
print(b[high-10]);
|
||||
|
||||
var c = [1,2,3];
|
||||
c[high-10] = high-10;
|
||||
c.length = 3;
|
||||
print(c);
|
||||
print(c[high-10]);
|
3
nashorn/test/script/basic/JDK-8035312_3.js.EXPECTED
Normal file
3
nashorn/test/script/basic/JDK-8035312_3.js.EXPECTED
Normal file
@ -0,0 +1,3 @@
|
||||
23534333
|
||||
1,2,3
|
||||
undefined
|
59
nashorn/test/script/basic/JDK-8035312_4.js
Normal file
59
nashorn/test/script/basic/JDK-8035312_4.js
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8035312_4 - pushes and pops for non writable length
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
var b = [1,2,3];
|
||||
Object.defineProperty(b, "length", { writable: false });
|
||||
|
||||
try {
|
||||
b.push(4);
|
||||
} catch (e) {
|
||||
print("length = " + b.length);
|
||||
print("i caught an error");
|
||||
}
|
||||
print(b);
|
||||
print(b[3]);
|
||||
print("length = " + b.length);
|
||||
|
||||
var c = [1,2,3];
|
||||
Object.defineProperty(c, "length", { writable: false });
|
||||
|
||||
for (var i = 0; i < 5; i++) {
|
||||
try {
|
||||
c.pop();
|
||||
} catch (e) {
|
||||
print("length = " + c.length);
|
||||
print("I caught an error");
|
||||
print(c);
|
||||
}
|
||||
}
|
||||
|
||||
print(c);
|
||||
print(c[3]);
|
||||
print("length = " + b.length);
|
23
nashorn/test/script/basic/JDK-8035312_4.js.EXPECTED
Normal file
23
nashorn/test/script/basic/JDK-8035312_4.js.EXPECTED
Normal file
@ -0,0 +1,23 @@
|
||||
length = 3
|
||||
i caught an error
|
||||
1,2,3
|
||||
4
|
||||
length = 3
|
||||
length = 3
|
||||
I caught an error
|
||||
1,2,
|
||||
length = 3
|
||||
I caught an error
|
||||
1,2,
|
||||
length = 3
|
||||
I caught an error
|
||||
1,2,
|
||||
length = 3
|
||||
I caught an error
|
||||
1,2,
|
||||
length = 3
|
||||
I caught an error
|
||||
1,2,
|
||||
1,2,
|
||||
undefined
|
||||
length = 3
|
60
nashorn/test/script/basic/JDK-8035312_5.js
Normal file
60
nashorn/test/script/basic/JDK-8035312_5.js
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8035312_5 - pushes and pops for frozen array
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
var b = [1,2,3];
|
||||
Object.freeze(b);
|
||||
|
||||
try {
|
||||
b.push(4);
|
||||
} catch (e) {
|
||||
print("length = " + b.length);
|
||||
print("i caught an error");
|
||||
}
|
||||
print(b);
|
||||
print(b[3]);
|
||||
print("length = " + b.length);
|
||||
|
||||
var c = [1,2,3];
|
||||
Object.freeze(c);
|
||||
|
||||
for (var i = 0; i < 5; i++) {
|
||||
try {
|
||||
c.pop();
|
||||
} catch (e) {
|
||||
print("length = " + c.length);
|
||||
print("I caught an error");
|
||||
print(c);
|
||||
}
|
||||
}
|
||||
|
||||
print(c);
|
||||
print(c[3]);
|
||||
print("length = " + b.length);
|
||||
|
6
nashorn/test/script/basic/JDK-8035312_5.js.EXPECTED
Normal file
6
nashorn/test/script/basic/JDK-8035312_5.js.EXPECTED
Normal file
@ -0,0 +1,6 @@
|
||||
1,2,3
|
||||
undefined
|
||||
length = 3
|
||||
1,2,3
|
||||
undefined
|
||||
length = 3
|
103
nashorn/test/script/basic/JDK-8062799.js
Normal file
103
nashorn/test/script/basic/JDK-8062799.js
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8062799: Binary logical expressions can have numeric types
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect;
|
||||
|
||||
var b = true;
|
||||
var i = 1;
|
||||
var l = 4294967296;
|
||||
var d = 2.1;
|
||||
var o = "foo";
|
||||
|
||||
print(inspect(b || b, "b || b"));
|
||||
print(inspect(b || i, "b || i"));
|
||||
print(inspect(b || l, "b || l"));
|
||||
print(inspect(b || d, "b || d"));
|
||||
print(inspect(b || o, "b || o"));
|
||||
|
||||
print(inspect(i || b, "i || b"));
|
||||
print(inspect(i || i, "i || i"));
|
||||
print(inspect(i || l, "i || l"));
|
||||
print(inspect(i || d, "i || d"));
|
||||
print(inspect(i || o, "i || o"));
|
||||
|
||||
print(inspect(l || b, "l || b"));
|
||||
print(inspect(l || i, "l || i"));
|
||||
print(inspect(l || l, "l || l"));
|
||||
print(inspect(l || d, "l || d"));
|
||||
print(inspect(l || o, "l || o"));
|
||||
|
||||
print(inspect(d || b, "d || b"));
|
||||
print(inspect(d || i, "d || i"));
|
||||
print(inspect(d || l, "d || l"));
|
||||
print(inspect(d || d, "d || d"));
|
||||
print(inspect(d || o, "d || o"));
|
||||
|
||||
print(inspect(o || b, "o || b"));
|
||||
print(inspect(o || i, "o || i"));
|
||||
print(inspect(o || l, "o || l"));
|
||||
print(inspect(o || d, "o || d"));
|
||||
print(inspect(o || o, "o || o"));
|
||||
|
||||
print(inspect(b && b, "b && b"));
|
||||
print(inspect(b && i, "b && i"));
|
||||
print(inspect(b && l, "b && l"));
|
||||
print(inspect(b && d, "b && d"));
|
||||
print(inspect(b && o, "b && o"));
|
||||
|
||||
print(inspect(i && b, "i && b"));
|
||||
print(inspect(i && i, "i && i"));
|
||||
print(inspect(i && l, "i && l"));
|
||||
print(inspect(i && d, "i && d"));
|
||||
print(inspect(i && o, "i && o"));
|
||||
|
||||
print(inspect(l && b, "l && b"));
|
||||
print(inspect(l && i, "l && i"));
|
||||
print(inspect(l && l, "l && l"));
|
||||
print(inspect(l && d, "l && d"));
|
||||
print(inspect(l && o, "l && o"));
|
||||
|
||||
print(inspect(d && b, "d && b"));
|
||||
print(inspect(d && i, "d && i"));
|
||||
print(inspect(d && l, "d && l"));
|
||||
print(inspect(d && d, "d && d"));
|
||||
print(inspect(d && o, "d && o"));
|
||||
|
||||
print(inspect(o && b, "o && b"));
|
||||
print(inspect(o && i, "o && i"));
|
||||
print(inspect(o && l, "o && l"));
|
||||
print(inspect(o && d, "o && d"));
|
||||
print(inspect(o && o, "o && o"));
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
50
nashorn/test/script/basic/JDK-8062799.js.EXPECTED
Normal file
50
nashorn/test/script/basic/JDK-8062799.js.EXPECTED
Normal file
@ -0,0 +1,50 @@
|
||||
b || b: boolean
|
||||
b || i: boolean
|
||||
b || l: boolean
|
||||
b || d: boolean
|
||||
b || o: boolean
|
||||
i || b: int
|
||||
i || i: int
|
||||
i || l: long
|
||||
i || d: double
|
||||
i || o: int
|
||||
l || b: long
|
||||
l || i: long
|
||||
l || l: long
|
||||
l || d: double
|
||||
l || o: long
|
||||
d || b: double
|
||||
d || i: double
|
||||
d || l: double
|
||||
d || d: double
|
||||
d || o: double
|
||||
o || b: object
|
||||
o || i: object
|
||||
o || l: object
|
||||
o || d: object
|
||||
o || o: object
|
||||
b && b: boolean
|
||||
b && i: int
|
||||
b && l: long
|
||||
b && d: double
|
||||
b && o: object
|
||||
i && b: boolean
|
||||
i && i: int
|
||||
i && l: long
|
||||
i && d: double
|
||||
i && o: object
|
||||
l && b: boolean
|
||||
l && i: long
|
||||
l && l: long
|
||||
l && d: double
|
||||
l && o: object
|
||||
d && b: boolean
|
||||
d && i: double
|
||||
d && l: double
|
||||
d && d: double
|
||||
d && o: object
|
||||
o && b: boolean
|
||||
o && i: int
|
||||
o && l: long
|
||||
o && d: double
|
||||
o && o: object
|
46
nashorn/test/script/basic/JDK-8062937.js
Normal file
46
nashorn/test/script/basic/JDK-8062937.js
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8062937 - GlobalConstants produces wrong result with defineProperty and index setters
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
var x = 1;
|
||||
for (var i = 2; i < 5; i++) {
|
||||
print(x);
|
||||
Object.defineProperty(this, "x", {value: i});
|
||||
}
|
||||
print(x);
|
||||
|
||||
print();
|
||||
|
||||
var name = "y";
|
||||
var y = 1;
|
||||
for (var i = 2; i < 5; i++) {
|
||||
print(y);
|
||||
this[name] = i;
|
||||
}
|
||||
print(y);
|
9
nashorn/test/script/basic/JDK-8062937.js.EXPECTED
Normal file
9
nashorn/test/script/basic/JDK-8062937.js.EXPECTED
Normal file
@ -0,0 +1,9 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
@ -1,6 +1,6 @@
|
||||
1,2,3,4,5,6
|
||||
first: true
|
||||
1,2,3,4,5,6,7
|
||||
1,2,3,4,5,6
|
||||
1,2,3,,,,4711.17,dingo!,4,5,6
|
||||
second: true
|
||||
1,2,3,,,,4711.17,dingo!,4,5,6,7
|
||||
1,2,3,,,,4711.17,dingo!,4,5,6
|
||||
|
Loading…
Reference in New Issue
Block a user